Overlapping sprites sorting order?

When you use the sprite:overlappingSprites() method, and you overlap with 2 or more sprites, what is the sorting order? Is it the one that overlaps the most that gets index 1, does zindex play any part, or is it just random? I'm getting very mixed results in my game.

I also found the order to be unexpected. I thought maybe it was the spirite that moved most recently was first, but I didn't look into it further.

I simply worked around it by checking the type of sprite 1 (car or obstacle) and branching

2 Likes

Mine are all stationary (except for the player sprite) and other than the player they are all objects that I need to be able to "examine". Any more branching and if statements would grow way too long.

Thinking about it some more, it could be as simple as the fact that Lua table iteration is not guaranteed to be in order. (unless using ipairs?)

I've added @dan to this as I believe he wrote the collision stuff.

1 Like

I was also wondering this, and also discovered that alpha collision tests do not work on sprites you draw yourself.

Any feedback from @dan yet?

Panic are a little swamped at the moment, but will take a look at this as soon as possible. Thanks for the report!

I created a temporary solution for my game, where I sort the collided objects by their Z index and the lowest one is the one I interact with.

local collisions = player:overlappingSprites()
local found = 0
local new_col = {}
for k, v in pairs(collisions) do
	if player:alphaCollision(v) then
		table.insert(new_col, {z = v:getZIndex(), index = k})
	end
end
table.sort(new_col, function(a,b) return a.z < b.z end)
for k, v in pairs(new_col) do
	found = v.index
	break
end

Then I use the index saved in found to get the data for the right sprite I want.

Yeah, I don't think there's any good way for us to make that work--when you use the draw callback you're drawing directly into the framebuffer. If you need custom drawing and also alpha collision testing you should create an image for the sprite and draw into that when the image needs to change.

1 Like

I figured if I:

  • set the size
  • set the sprite as opaque
  • set a collision bound that matched the size

that at the minimum, the opaqueness would get used by alpha collision (since it is never "transparent") and the highest on the z-index opaque sprite would be used.

The collision detection uses a spatial hash, dividing the screen up into cells where each cell tracks which sprites are in it, in order to reduce the number of pairwise bounds checks we have to do. The overlappingSprites function iterates across those top to bottom, left to right, then it looks like there's a hash table in the cell so it'll be effectively random after that. I'm not sure it's worth sorting those before returning since different games have different needs, might be adding extra work there unnecessarily.

Right now the sprite:alphaCollision() function returns false if either sprite doesn't have an image set. But you're right, it should treat opaque sprites like solid rectangles regardless of how they're drawn. I'll file that now. It probably won't make it into the next update because we're wrapping that up now and this isn't a simple change, but it's in the queue.

1 Like

One option could be to add an optional argument to the overlappingSprites function for sorting. If empty, then it returns the table as it does today, but if the argument is (for example) 'zindex' then it could loop through them like I did in my code example, before returning the table. A few other sorting ways could be added the same way.
But yes, the needs for this are heavily dependent on the game that is being made, but a few built in standard sorting methods might be useful to a lot of people.