ysort
ysort
¶
Depth-ordered drawing for top-down games, the Y-sort trick.
In a top-down world something lower on the screen should draw in front of
something higher up, so a character walking below a tree covers its trunk. The
way to get that is to draw everything in order of its Y, lowest first, so the
nearest thing lands on top. A DrawQueue collects what to draw along with the
Y to sort by, then draws it all in that order in one call, so you are not
hand-sorting a list every frame.
You queue an item with the Y to sort by and the item itself, then flush
draws them through a proc you give it. The sort key is usually a sprite's feet,
the base Y where it meets the ground, rather than its center, so a tall sprite
overlaps by where it stands. The item is stored as plain data rather than a
closure, which keeps it clear of the Nim trap where closures made inside a loop
all capture the final loop value, and it avoids allocating a closure per
sprite.
An optional integer layer draws in bands. A ground layer stays under everything and a roof or a heads-up layer stays on top, with the Y-sort happening inside each band. Items at the same layer and Y keep the order they were added in, so two sprites level with each other do not swap and flicker.
This is an opt-in module, imported on its own with import nim2d/ysort. The
core engine does not pull it in.
DrawQueue
¶
type DrawQueue[T] = ref object
Collects items to draw with a Y sort key and an optional layer, then draws
them back to front. T is your own sprite or entity type. Make one with
newDrawQueue, refill it each frame, and flush it.
newDrawQueue ¶
proc newDrawQueue(): DrawQueue[T]
A new empty queue. Keep it across frames rather than making one each frame;
flush empties it for you so it is ready to refill.
Returns
DrawQueue[T]
add ¶
proc add(q: DrawQueue[T]; y: float; item: T)
Queue item, sorted by y. A larger y, meaning lower on the screen,
draws in front. Pass the sprite's feet for y, not its center. This uses
layer 0; the layered overload puts it in a band.
Parameters
-
q(DrawQueue[T]) -
y(float) -
item(T)
add ¶
proc add(q: DrawQueue[T]; layer: int; y: float; item: T)
Queue item in a layer band. Lower layers draw first, underneath higher
ones, and within a layer a larger y draws in front.
Parameters
-
q(DrawQueue[T]) -
layer(int) -
y(float) -
item(T)
len ¶
proc len(q: DrawQueue[T]): int
clear ¶
proc clear(q: DrawQueue[T])
Drop everything queued without drawing it.
Parameters
-
q(DrawQueue[T])
flush ¶
proc flush(q: DrawQueue[T]; nim2d: Nim2d; draw: proc (nim2d: Nim2d; item: T))
Draw everything queued in depth order, layer by layer and, within a layer,
from the lowest Y to the highest, then empty the queue. draw runs once per
item with the item you queued, so it holds the actual drawing. Call this once
a frame from your draw callback, after the frame's sprites are queued.
Parameters
-
q(DrawQueue[T]) -
nim2d(Nim2d) -
draw(proc (nim2d: Nim2d; item: T))