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.

This is a tricky one. :confused: The problem is that scaled sprites are a convenience I added in the Lua wrapper and at the base level they're normal image-based sprites. When you call kScene:setScale(2) it takes the current image, scales it up 2x and sets that on the underlying sprite. Drawing into the pre-scaled image doesn't trigger a redraw because that logic is down in the base code. You can force a redraw with markDirty() but that just redraws the original image that was set. I'll add a check for changes to the original image in the scaled/rotated case, which should make this work as expected. Until then, you can do something to force a redraw of the scaled image, like:

	kScene:setImage(nil)
	kScene:setImage(kSceneImage)

Okay, fix is in for that. I wish I could say it'll be out soon, but I don't know when we'll be able to push the update. We screwed up and didn't keep the new code for Catalog separate from the 1.13.0 release, so we've created a QA nightmare. :frowning:

Wish I could help with that. I can't say I haven't merged a feature branch with a master branch at the wrong time...before.

1 Like

FTR the fix is finally out the door in the 2.3 update