Changing tiles in a tilemap in a sprite no longer reliably repaints

paint

There’s a couple of weird behaviors going on here that all seem to be able to be described as “tilemap sprites don’t always repaint everything when you change tiles.”

The visual representation of the game board in my Minesweeper game is a sprite containing a playdate.graphics.tilemap. The sprite system seems to fail to repaint all impacted cells after an interaction. The attached GIF shows the cell under the cursor failing to repaint after a reveal, which the player “fixes” by moving the cursor around over the cell.

A similar issue happens with any “chording” interaction. When you hold down the A button on an unrevealed cell, the potentially chordable cells are supposed to show their pressed state, but they currently don’t.

This may actually be the same issue as Sprites seem to ignore `playdate.graphics.setDrawOffset()`, but only sometimes . They’re both situations where the sprite system is failing to draw content after changing some property, so it may be that they’re both caused by the same underlying failure to trigger a repaint.

Relevant code is in draw() in gameUI.lua:129. The issue can be partially (but not entirely) mitigated by adding tilemapSprite:markDirty() at gameUI.lua:160. The mitigation fixes the “under cursor revealed cell” issue, but not the chording cell preview issue.

Mines.zip (587.9 KB)

1 Like

okay, the problem is we have an optimization where a dirty rect is ignored if it’s covered by an opaque sprite that hasn’t changed–but it’s not correctly checking for changed tilemaps. So a quick fix on your end is to not mark the tilemap sprite opaque. On our side… maybe we shouldn’t allow tilemap sprites to be opaque? If you set a tile index to a number outside the # of images in the tilemap’s image table the tile will be empty/transparent, and tracking that condition just for this case seems kind of ugly.

Yeah, I think I’ll just make setOpaque a no-op on tilemap sprites.

wait, nope, I should have tested that first. There’s still a problem because the background sprite is opaque and that optimization didn’t see that anything had changed so it skipped the redraw. Very weird case here. If you also don’t mark the background opaque it should work, even though that’s a totally normal thing to do.

Okay, fixed! Wow, that wound up being a lot trickier than I’d expected! But it appears to be working correctly now.

One sort-of-bug I found in the game: if you click on a number square, it toggles the neighboring hidden squares back and forth. (If you turn on Highlight Screen Updates it’s pretty obvious.) This actually wound up being really useful for pointing out one of my drawing bugs. :slight_smile:

That sounds like you’re describing the chording feature to me :grinning:

If you click a number, it’ll show the press state on the neighboring unrevealed cells. If you click a number which is surrounded by the same number of flags, then when you release the click it’ll fully reveal all the neighboring unrevealed cells. In other words, if you click a “2”, and you’ve already planted two flags around it, it’ll fully reveal any unrevealed neighboring cells. This is a convenience speed feature that can really help clear out the board quickly, but there’s a risk: if you have enough flags around a number for chording to reveal the unrevealed cells, but one of those flags is incorrectly placed, then a chorded reveal could reveal a mine, losing the game.

mines

@dave was undecided whether to file this as a new issue or not, but figured I’ll just post it here to avoid making too many similar tickets.

I think the issue with tilemap painting was fixed, but the interaction with other sprites on and overlapping the tilemap isn’t quite right. And I think this is a new regression, though it may have existed before.

As you can see in the GIF, when the arrow moves around on the right edge of the board part of the arrow lingers behind. It’s not shown in this GIF, but I’ve sporadically gotten it to stick around on the bottom edge, too.

Also, after clicking a mine, if I wait a moment and then move the cursor, a copy of the cursor image stays behind (you can move the cursor during the camera shake, and if you do so you won’t get the retained image).

ha! It’s always something… I’m seeing the same thing, so it should be pretty easy to track down. Thanks again for finding yet another one of my goofs :sweat_smile:

Still seeing this issue in 1.4.0, though I don’t know if a fix was intended for that release.

my bad, sorry! I had that ready but I forgot to remove the “draft” flag from the MR. I can’t remember now if I found a related issue I also wanted to fix, or I was just avoiding making a test case for QA, but I verified my fix still works and have it ready to go. Sorry for the delay!

2 Likes

Tested in the simulator and on a device in 1.7.0, and it looks like it’s fixed! :tada:

2 Likes