Strangeness when updating the image of a sprite that is :setScale(2)

If you set a sprite's image, and later draw to that image, the sprite will reflect the changes.

But if the sprite is set to a larger scale, it won't reflect those changes.

The ways I've found around this are to either quickly set the scale to 1 and then immediately back to 2, or change the image of the sprite and then change it back.

Please try sprite:markDirty()

That will give us more intimation what's wrong.

It didn't solve it.

(BTW, I am running setAlwaysRedraw(true) anyway)

What does simulator "Show screen updates" look like? With and without always redraw would be useful.

Hello! I just ran into this exact bug today. Here's a small code to reproduce this bug:

import "CoreLibs/graphics"
import "CoreLibs/sprites"
import "CoreLibs/timer"

local x = 0
local y = 0

local kSceneImage <const> = playdate.graphics.image.new(128, 128, playdate.graphics.kColorBlack)
local kScene <const> = playdate.graphics.sprite.new(kSceneImage)
kScene:setRedrawsOnImageChange(true)
kScene:moveTo(200, 120)
kScene:setScale(2)
kScene:add()

function playdate.update()

	playdate.timer.updateTimers()
	playdate.graphics.sprite.update()

	x = (x + 1) % 128
	y = (y + 1) % 128

	playdate.graphics.pushContext(kSceneImage)
		playdate.graphics.setImageDrawMode(playdate.graphics.kDrawModeFillWhite)
		playdate.graphics.drawText("Hello world", x, y)
		playdate.graphics.setImageDrawMode(playdate.graphics.kDrawModeCopy)
	playdate.graphics.popContext()

end

If you comment the kScene:setScale(2) line, you'll see that everything works properly at default scale. Any idea?

It seems like a bug! It’s even more weird that when I change the scale on every update, it seems to work.

Check following (I lowered framerate and added some gradual change of scale):

import "CoreLibs/graphics"
import "CoreLibs/sprites"
import "CoreLibs/timer"

local x = 0
local y = 0

playdate.display.setRefreshRate(3)

local kSceneImage <const> = playdate.graphics.image.new(128, 128, playdate.graphics.kColorBlack)
local kScene <const> = playdate.graphics.sprite.new(kSceneImage)
kScene:setRedrawsOnImageChange(true)
kScene:moveTo(200, 120)
kScene:add()

local i = 10

function playdate.update()
	i = (i + 1) % 10
	kScene:setScale(i / 10 + 1)

	playdate.timer.updateTimers()
	playdate.graphics.sprite.update()

	x = (x + 1) % 128
	y = (y + 1) % 128

	playdate.graphics.pushContext(kSceneImage)
		playdate.graphics.setImageDrawMode(playdate.graphics.kDrawModeFillWhite)
		playdate.graphics.drawText("Hello world", x, y)
		playdate.graphics.setImageDrawMode(playdate.graphics.kDrawModeCopy)
	playdate.graphics.popContext()
end

I came through a link and didn’t notice there are posts above the last one!

Just to answer the earlier question from @matt: markDirty seems to change rendering (without it, there are no indicated screen updates, with it, sprite’s area is getting rerendered), but the rendered image stays the same. You can try it with the examples from @hteumeuleu and me.