Collision — overlap detection
collisionreports when targets' bounds overlap. It runs in the stage's Detect phase, reads targets' shapes, and emits events — it does not decide what a collision means. Detection is a pure, deterministic function of this frame's positions; the response (bounce, stop, score) is a script's job. Detect and report; let policy live above.
Status: design. Not built yet.
What it is
collision is the interactive sibling of motion and tween: once things move, you want to know when they touch. Each tick, after motion and tween have written positions in Advance, collision runs in Detect — it reads the enrolled targets' bounds, finds which pairs overlap, and emits an event for each. That is all it does, and the whole point is that it stops there.
Detection is deterministic; response is not
This split is the load-bearing decision, and it's why collision stays clean where physics engines get messy:
- Detection is a pure function of positions — "do these two bounds overlap on this frame?" is exact AABB / circle maths on the settled Advance-phase positions. Deterministic, frame-order-independent, replayable.
- Response is where determinism dies — "bounce," "push apart," "resolve penetration" is iterative, order-sensitive, and frame-rate-dependent in the general case; it is the tar pit that makes physics engines non-deterministic.
So collision detects and reports; it never moves anything. What happens on a collision is ordinary AntBASIC / Luau — stop the motion, start a tween, play a sound, add a point. Mechanism in the core, policy in scripts. (A small set of canned, deterministic responses — stop-on-contact, reflect — can be offered as convenience, but they are opt-in and pure; anything iterative stays out until you deliberately add a physics layer, below.)
Bounds and layers
A target enrolled for collision carries a bound — an AABB (axis-aligned box) or a circle, the two shapes whose overlap test is cheap and exact. Testing every pair against every other is N²; two things keep it cheap and controlled:
- A broad phase — a spatial partition (grid, or sort-and-sweep) narrows the candidate pairs before the exact test, so a crowded scene stays fast.
- Layers and masks — each target sits on a layer and tests only against a mask of layers. Players test walls and pickups, not each other; bullets test enemies, not other bullets. This is both a performance lever and how you express what should interact.
Events — enter, stay, exit
collision compares this frame's overlapping set with last frame's and emits three kinds of event, so a handler reacts to transitions, not just steady state:
enter— a pair began overlapping this tick (the hit);stay— a pair still overlaps (ongoing contact);exit— a pair stopped overlapping (separation).
Events are raised in Detect and delivered in React (per the stage's rule), in a defined order, so handling a collision never perturbs the frame that produced it — and the same inputs replay the same events.
Queries
Detection runs continuously; sometimes you want to ask directly:
overlapping(a, b)— do these two overlap right now (a boolean, for a script that would rather test than subscribe);at(x, y)/query(shape)— which targets are under a point or inside a region — hit-testing, picking, area-of-effect.
Queries read the same bounds as detection, so they agree with it exactly.
Response stays in scripts — and physics is a later, opt-in choice
To be explicit about the ladder: today collision is detect + emit + query, and every response is script policy. If you later want simulated physics — momentum, restitution, stacking — that is a separate, opt-in physics layer with its own deterministic fixed-step integrator, in its own stage phase between Detect and React. It is deliberately not baked into collision, so the common case (arcade-style "did I hit it? then do this") stays pure and simple, and the heavyweight case is something you choose, never something you inherit.
On the stage
collision is a stage sibling: it runs in Detect, reads target bounds (written by motion / tween in the preceding Advance), emits events, and references no other system. It inherits the determinism contract: detection is pure, delivery is ordered, so a whole interactive scene replays identically.
Clients
- AntBASIC —
TOUCHING(a%, b%)is the immediate-test front door, and anON COLLISION a%, b% …handler subscribes to theenterevent — collision as a beginner can reach it. - Luau —
require("collision"):watch/on/overlapping/atfor tools, games, and apps.
Related
- motion · tween — the movement siblings · stage — the substrate (phase order, events) ·
physics— the opt-in simulation layer (future) - luau_collision — the Luau API · AntBASIC — the
TOUCHING/ON COLLISIONfront door