Optional world boundaries / bounds (keep entities in a play area) #84

Closed
opened 2026-09-02 04:52:42 +02:00 by orkun · 1 comment
Owner

There is no built-in world boundary. Games hand-roll clamping (clamp Position each frame) to fake walls / keep entities inside a play area.

Proposal: an optional world-bounds feature — a bounds rect/config (per-world or per-scene) with a policy (clamp / wrap / bounce / kill-on-exit), applied by the move system when enabled. Off by default (open world). Seen: an external game clamps Body entities manually.

There is no built-in world boundary. Games hand-roll clamping (clamp Position each frame) to fake walls / keep entities inside a play area. Proposal: an optional world-bounds feature — a bounds rect/config (per-world or per-scene) with a policy (clamp / wrap / bounce / kill-on-exit), applied by the move system when enabled. Off by default (open world). Seen: an external game clamps Body entities manually.
Author
Owner

Shipped in ad3be0c (full suite 112/0, goldens byte-identical, fixpoint intact).

Declare a single Bounds config entity (a rect x, y, w, h + a policy, shipped from ludic.core) and the engine-owned world-bounds system keeps every moving Body inside the play area each frame — no more hand-clamping Position. Four policies:

  • 0 clamp — stop at the edge (walls)
  • 1 wrap — reappear on the opposite side (toroidal)
  • 2 bounce — clamp and flip the Body velocity on the axis that hit
  • 3 kill — despawn a body fully outside (offscreen cleanup)

It reads each body's Collider size so the whole box stays inside. Off by default (no Bounds entity = open world), registered on the engine-system registry for LateUpdate (after movement integrates), and spliced only when a game declares Bounds, so a game that never does compiles byte-identically.

Also adds World.despawn(entity) — the reflective, by-id form of the despawn statement (runs @OnDespawn + frees the slot), which the kill policy uses and any system can call; its @fn_world_despawn helper is emitted in the codegen tail once a use is seen (the same g_uses_*-prelude pattern the string/net helpers use), so non-users are byte-identical.

Verified by examples/library/world_bounds.ludic — clamp (stops at the wall, 184), wrap (-16), bounce (clamped + velocity flipped), kill (body fully outside removed): prints 184 -16 184 1 0. Docs page for World.despawn added.

Shipped in ad3be0c (full suite 112/0, goldens byte-identical, fixpoint intact). Declare a single **`Bounds`** config entity (a rect `x, y, w, h` + a policy, shipped from **ludic.core**) and the engine-owned world-bounds system keeps every moving `Body` inside the play area each frame — no more hand-clamping `Position`. Four policies: - `0` **clamp** — stop at the edge (walls) - `1` **wrap** — reappear on the opposite side (toroidal) - `2` **bounce** — clamp and flip the Body velocity on the axis that hit - `3` **kill** — despawn a body fully outside (offscreen cleanup) It reads each body's `Collider` size so the whole box stays inside. **Off by default** (no Bounds entity = open world), registered on the engine-system registry for **LateUpdate** (after movement integrates), and spliced only when a game declares `Bounds`, so a game that never does compiles **byte-identically**. Also adds **`World.despawn(entity)`** — the reflective, by-id form of the `despawn` statement (runs `@OnDespawn` + frees the slot), which the kill policy uses and any system can call; its `@fn_world_despawn` helper is emitted in the codegen tail once a use is seen (the same `g_uses_*`-prelude pattern the string/net helpers use), so non-users are byte-identical. Verified by `examples/library/world_bounds.ludic` — clamp (stops at the wall, 184), wrap (-16), bounce (clamped + velocity flipped), kill (body fully outside removed): prints `184 -16 184 1 0`. Docs page for World.despawn added.
orkun closed this issue 2026-09-02 06:45:03 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: workshopsoft/ludic#84
No description provided.