plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


db32e90 — Peter John 2026-11-02T18:28:00+05:30
README: Scene z-index, sortChildren, culling and the layer recipe
Files changed (1) hide show
  1. README.md +18 -0
README.md CHANGED
@@ -1045,6 +1045,24 @@ Games run in the browser on Plum's own WebGPU renderer (`plum-game/web/plum_brid
1045
1045
 
1046
1046
  **`std/Scene`** is a scene-graph library written in Plum (see [`plum-examples/scene.plum`](plum-examples/scene.plum)): a tree of `Node`s (group, sprite, rect, circle, text) under a `Stage`, with parent-relative position, rotation, scale and colour, per-node `act` behaviours, a camera and hit testing; its demo renders a minimap into a texture with `textureCreate` and `renderTarget`. Use it for UI and other hierarchical scenes, where moving a parent should move everything in it. For a large world, keep the game objects in flat records and lists instead (for example `enum Entity = Unit | House` with an `update` and a `draw` that the enum dispatches to its variants) and draw them directly through `std/Game`; a tree of thousands of nodes costs a closure call and a matrix composition per node every frame.
1047
1047
 
1048
+ `std/Scene` follows libGDX Scene2D for draw order and culling. A node's z-index is its position in its parent's child list (draw order is list order, hit testing goes in reverse):
1049
+
1050
+ ```plum
1051
+ n.zIndex() # index among its siblings, -1 without a parent
1052
+ n.setZIndex(0) # move within the parent (clamped to 0..length-1)
1053
+ n.toFront() # last child: drawn on top, hit first
1054
+ n.toBack() # first child: drawn first
1055
+
1056
+ world.sortChildren(|a, b| a.y < b.y) # stable, in place, no allocation once warm
1057
+ world.setCullingArea(cam.x, cam.y, viewW, viewH) # in world's own coordinates
1058
+ world.clearCullingArea()
1059
+ ```
1060
+
1061
+ `sortChildren(before)` is a natural merge sort with a scratch list kept on the node: a list that is already sorted costs n - 1 comparisons and a nearly sorted one (a y-sorted layer re-sorted every frame) about 2n, with O(n log n) as the worst case; equal keys keep their order, so ties do not flicker. `setCullingArea` makes a group skip each direct child whose box (position and size, scaled about its origin; rotation ignored) lies outside the rectangle, in both `draw` and `hit`, with the child's whole subtree; children with no size (plain groups) are never culled. In [`plum-game/web-test/BENCHMARK.md`](plum-game/web-test/BENCHMARK.md) a 20,000-sprite y-sorted layer costs 1.15 ms per frame with culling and 4.20 ms without.
1062
+
1063
+ A layered world (a layer recipe for a large map) is a few groups under the stage root, drawn in order: `terrain` (static, culled), `world` (y-sorted every frame, culled), `effects` (culled) and `ui` (not culled, in screen space with a second `Stage` or camera). Each frame: `world.sortChildren(|a, b| a.y < b.y)`, then `setCullingArea` on `terrain`, `world` and `effects` from the camera view.
1064
+
1065
+
1048
1066
  A game declares three exports. `G` is any record and holds all game state (there are no globals):
1049
1067
 
1050
1068
  ```plum