Skip to content

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

How many items are queued.

Parameters

  • q (DrawQueue[T])

Returns

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))
Generated with mkdocstrings-nim