Skip list:Drawing Order

Z-ordering in LÖVE is tedious because the engine doesn't offer any suppoer for it. You must draw the sprites in order by yourself, making it practically impossible to handle a large number of sprites on different planes.

With the skip list data structure, you can do:

Clown = makeSprite (100, 100, 1, "clown.png") -- x, y, z, image
Frogs = makeSprite (100, 110, 1, "frogs.png") -- on top of the clown (on the same plane, but created after)
Tools = makeSprite (90,  120, 0, "tools.png") -- under the clown

zlist = makeSkipList(3)

zlist:insert( Frogs )
zlist:insert( Tools )
zlist:insert( Clown ) -- You can insert them in any order

for _, sprite in zlist:iter() do
	-- draw the sprite in Z order :-)
	print( sprite.x, sprite.y, sprite.z, sprite.image ) 
end

Output:

90      120     0       tools.png
100     100     1       clown.png
100     110     1       frogs.png


If you want to change the position of an item on the Z axis, you remove it and insert it back.

Tools.z = 2
zlist:delete(Tools)
zlist:insert(Tools) -- now Tools is on top of the pile

for _,sprite in zlist:iter() do
	print(sprite.x, sprite.y, sprite.z, sprite.image) -- draw(sprite)
end

Here's the output:

100     100     1       clown.png
100     110     1       frogs.png
90      120     2       tools.png

=== Toy implementation of makesprite:

do
local count = 0
function counter()
	count = count + 1
	return count
end
end


do
local lt = function(a,b)
	if a.z < b.z then return true
	elseif a.z==b.z and a.id < b.id then return true
	else return false
	end
end

local mt={
	__lt=lt,
	__le=lt
}
function makeSprite (x,y,z,image)
	local s={x = x, y = y, z = z, image=image, id = counter()} 
-- the id field is necessary because, otherwise, items on the same plane would cause troubles.
	return setmetatable(s,mt)
end

end