have you ever wanted to do z ordering, but without careful programming practices?
well i have the product for you!
introducing: the queue() and drawq() functions!
usage:
queue(--[[any function (spr, rect, pal, anything)]],{--[[array of parameters]]},--[[order index]])
use this to put things in the queue.
drawq()
no parameters here! it just bubble sorts --[[oh god]] the functions and calls them in that order,
meaning that --[[for example]], spr calls with the y pos passed as an index, will be stacked like real things, and no more characters standing on each others heads!
q={}
run this to clear the queue. this is the var which i used for queues. this is not perfect, but improvements are left as an exercise for the reader. --please post them, as i know i could do better.
anyway, the script:
function queue(f,p,o) add(q,{f,p,o}) end function drawq() --improvements by @packrat! repeat local swp=true for l=1,#q-1 do if q[l][3]>q[l+1][3] then q[l+1],q[l]=q[l],q[l+1] swp=false end end until swp for d in all(q) do d[1](unpack(d[2])) end end |
here's a little example!
nice!
quick lua notes:
x, y = y, x
will exchange x and y without issue in lua - you don't need to explicitly create a tmp swap variable
also this feels like a really good use case for a repeat-until loop, which we love unreasonably but more importantly in this case saves tokens because swp doesn't need to be defined outside the loop
function drawq() repeat local swp=true for l=1,#q-1 do if q[l][3]>q[l+1][3] then q[l+1],q[l]=q[l],q[l+1] swp=false end end until swp for d in all(q) do d[1](unpack(d[2])) end end |
thanks again - this is way easier than what we did last time we tried to do a draw order (which, uh, we never actually got working I think)
@packbat nice! gotta implement that. but later, as its late.
have a nice day!
@packbat nevermind i implemented it. this is mostly to help people with quickly setting up z-order stuff. have fun!
Bubble sorting every frame is extremely costly... why don't you change for a presorted selective insertion list?
function queue(f,p,o) q[o]=q[o] or {} add(q[o],{f,p}) end function drawq() for _,l in pairs(q) do for d in all(l) do d[1](unpack(d[2])) end end end |
With that change your demo goes from 11-12% cpu (bubble sort) to 4% cpu (presorted insertion)
There is a small issue though, you require int orders
Hmm sorry... has some issues with sorting... I will patch my suggestion ;) give me some time
For a small number of objects, this is indeed an option.
I have a variant that I used for my Nuklear Klone, that simply uses a sparse table of objects with the same "z-order".
It is twice as fast as using @kirbofan sort :]
Ok, not fully optimal... you can have a more efficient selective insert strategy but still more efficient than the bubble sort.. (around 5.5%) Only requiring an extra array for the "orders"
function queue(f,p,o) q[o]=q[o] or {} add(q[o],{f,p}) if #order==0 then add(order,o) else -- todo optimizable with better -- selective insertion algorithm local idx = 1 for val in all(order) do if (val > o) break idx+=1 end add(order,o,idx) end end function drawq() for _,o in ipairs(order) do for d in all(q[o]) do d[1](unpack(d[2])) end end end |
Similar variant as @slainte using a linked list - still slower than the brute force "array" version :]
Queue API:
-- basic 2d z-ordering -- sorted list variant by @freds72 local q={z=-0x8000} function queue(f,p,o) local head,prev=q,q while head and head.z<o do -- swap/advance prev,head=head,head.next end -- insert new thing prev.next={f,p,z=o,next=prev.next} end function drawq() local head=q.next while head do head[1](unpack(head[2])) head=head.next end q={z=-0x8000} end |
[Please log in to post a comment]