1.13 firmware regression: collidingSprites ignores collisions

I’m using playdate.graphics.sprite:overlappingSprites to detect when the player sprite overlaps with an item sprite to collect the item (with the player moving and the item checking collisions). Unfortunately, with 1.13 it no longer reliably works and overlappingSprites often returns an empty table while the two collision rects are overlapping. For some items the collision works but when it doesn’t I can move around forever and it’s still not recognized.
It doesn’t matter whether I build the game with 1.12.3 or 1.13. The issue appears in the new firmware version independent of the SDK used. It also happens in the 1.13 simulator where I see the collision rects overlapping.
I have not been able to produce a small demo. In a demo with just the two sprites it still works. But I have recorded the behavior in the simulator to show the issue. This appears in the first level of my game so it’s completely unplayable in 1.13.
no-collision

The longer I test this, the weirder it gets.

  • Sometimes I can walk over the item 50 times and nothing happens.
  • Sometimes it works on the second or third try but rarely on later attempts.
  • Sometimes the collision happens too early as if the collide rects were completely ignored and the sprite boundaries were used instead.
  • Sometimes it looks like the collision happens a couple frames too late when the collide rects don’t overlap anymore. Manual calculation of the overlap from positions and collide rects suggest the same but I might have made a mistake.
  • Sometimes I can pick up the item at a completely different position but not where it’s actually at
  • Sometimes it even works like it did in 1.12.

This sounds similar to an issue I had with earlier SDKs Collision detection failing between sprites at negative Y coordinates, except in my testing so far, that seems to be fixed in 1.13. My playdate hasn’t gotten the update yet so I can only test in the simulator, though.

Yes, that would be my best guess that this is related to the fix.

stacky hero seems to have the same issue, i can just pass through everything and no collisions seems to be detected
Playdate 2023-02-11_01-35-15

@AlenB

1 Like

Thanks @joyrider3774
What’s weird is that the stacking is working but the obstacles are ignored..

1 Like

Just wondering but Could the Zindex have any effect on this ?

@AlenB

I've installed Previous SDK version (1.12.3) and ran stacky hero inside it there it shows collision boxes around the objects

However in latest SDK Version (1.13) it's not showing the collision boxes so it pass through them.

this might be a different issue than what this topic is about, and you might need to open a new topic about it if you figure out whats causing it

2 Likes

Here comes the kicker. I found a workaround. :partying_face: Calling collisionsEnabled() on the item sprite returns true right before the collision is ignored but calling setCollisionsEnabled(true) on the item right before checking for collisions fixes the issue!

2 Likes

Another interesting observation. I just ran the game in the simulator with and without the workaround and with the same seed so the whole setup was identical apart from the workaround.

  • Without the workaround I can pick up the item at a different position but not where it’s actually at. The collision rect is shown in the right position but internally it appears to be somewhere else.
  • With the workaround – which is just setting a boolean value and not manipulating anything else – I can pick up the item at the right position.

Where the other location comes from when not using the workaround is completely unclear to me. There is no other colliding sprite in the game at that point. I have a copy of the save with the seed that can reproduce this right at the start of the level.

I have a fix in for StackyHero, and I'm betting it's same issue in Oubilette. The problem is sprite.x/y/width/height are returning the value from the sprite's table storage instead of the live property, and that value in the table isn't getting updated properly. In StackHero that leads to the collision rects being set with width=0. I think I implemented it that way to avoid breaking a really weird use case that was possible in 1.12.3--you could set sprite.x (though it doesn't actually move the sprite) and read that value back until it gets overwritten by sprite:moveTo()--but in 1.13.0 setting sprite.x throws an error, and it doesn't look like anyone's had a problem with that. So I'm moving the live values ahead of the table storage, and we'll see if that causes any trouble. So far it looks good!

I plan to get simulator builds with these fixes up today or tomorrow. As soon as it looks like we've taken care of the game-breaking regressions that have popped up (and not caused any new ones) we'll push a 1.13.1 update.

Sorry for the headaches!

4 Likes

Does that require building with SDK 1.13 or just running on it?

nope, it's in the runtime, you'd see it now on existing builds.

1 Like

I see those in my game. It’s in 3 years old code on my side that never caused an issue until now.

Oof. I thought we'd be safe changing that behavior since setting those values didn't do anything and then they got overwritten when you moved the sprite or changed its size. So you're getting the warning, but is it affecting the game logic at all?

Just double checked and it works in 1.13 but the warning is shown.
Some context: I wasn’t trying to manipulate the sprite that way, just saving the numeric width for later calculations. In most cases there’s a setImage call a couple lines later.

PS: Back when I implemented this there was no documented width property for sprites.

I need to find time to test Daily Driver as I believe I also read sprite values directly for calculations.

Thought: is it possible to scan a game written in Lua to see what API functions it uses? Though I guess this type of sprite property access isn't really API use. Maybe a corpus of games and an automated scanner would remove the guesswork from these type of internal changes?

We're testing the waters here to see how much trouble it would cause if setting x/y/width/height actually did change the sprite's position/size--a lot of people starting out are confused that you can read those values but setting them doesn't have any effect. That would be behind a version check so that the behavior wouldn't change in already-built games, of course.

Many thanks for the update!