RoadHazard
Oil slicks, smoke clouds and bomb craters left lying on the road.
What it does
- An
oilslick spins a car out, once per car per slick. The side the car enters on decides which way. - A
smokecloud blinds an AI driver while it is inside, and forblindSecondsafter. - A
craterjolts a car and damages it on the way in.
Each hazard is a pooled entity that lives life seconds and shrinks away over the last fade. Lay one with dropHazard. A bomb that bursts on the road turns into a crater from a pool named crater, if the scene has one. Whoever laid a hazard is safe from it for its first 1.5 seconds, so the player does not spin on the oil they just dropped.
Use it in a scene
A scene is just data — a list of entities, each with its components. At startup the SceneLoader turns this JSON into a live world; edit the file and reload to rebuild it.
Build it from scratch with the bjs CLI:
- 1Scaffold a project
World, renderer, and dev server — ready to run.
- 2Install dependencies
- 3Add RoadHazard
Copies its source into src/ so the scene resolves.
First time? Run bjs login once.
- 4Paste the scene into src/scenes/arcade-room.ts and run
SceneLoader builds the world from the JSON; reload to rebuild.
Lay one from code with the helper in RoadHazard.defs:
dropHazard(world, 'oil', x, z, owner) lays a slick from the oil pool at (x, z). It returns null if the pool is not up yet.
Which way oil spins
A car that clips the left edge of a slick should spin the other way from one that clips the right edge. oilSpin works that out with one dot product:
(rx, rz) points straight across the car, so the sign of side says which half of the slick the car came in on. Every spin is the same size: spin rad/s, with no grip for slipSeconds. Each slick keeps a set of the cars it has spun, so a car that sits in the oil for 30 frames spins once, not 30 times. A crater uses the same sum at 0.4 of its spin for 0.3 seconds, which reads as a jolt.
How a hazard fades
A new slick starts at 35% size and spreads to full in a quarter second. Take the defaults, a 14 s life and a 1.5 s fade. At 13 seconds the slick has 1 second left, so it is at two thirds of full size. Its 2.6 m reach shrinks to 1.7 m, plus 0.6 m of slack for the car's body. A dying slick looks smaller and is a smaller trap.
Settings
| Field | Default | What it does |
|---|---|---|
kind | "oil" | oil, smoke or crater |
radius | 2.6 | Reach in metres at full size. A car counts as inside 0.6 m further out. |
life | 14 | Seconds it lies on the road |
fade | 1.5 | Seconds it shrinks over at the end |
spin | 5.5 | Oil: spin given to a car, rad/s. A crater gives 0.4 of it. |
slipSeconds | 1.1 | Oil: seconds the car has no grip |
blindSeconds | 1.6 | Smoke: seconds an AI driver stays blind after it leaves the cloud |
damage | 10 | Crater: damage on the way in, scaled by the car's damageTaken |
smokeColor | [0.82, 0.82, 0.8] | Smoke colour. Saved with the scene, but no system reads it yet. |
puffsPerSecond | 40 | Smoke puff rate. Saved with the scene, but no system reads it yet. |
Events
RoadFX draws the smoke cloud off roadHazard.laid. A director reads owner on roadHazard.entered to credit a kill to whoever laid the slick.
| Event | Payload | Direction |
|---|---|---|
roadHazard.laid | { entityId, kind, x, z, radius, life } | emits, on a hazard's first frame |
roadHazard.entered | { hazardId, entityId, kind, owner } | emits, each time a car drives in |
carCollision.spin | { entityId, spin, seconds } | emits, from oil and craters |
autoRunnerDriver.blind | { entityId, seconds } | emits, every frame an AI driver is in smoke |
health.damage | { entityId, damage } | emits, when a car drives into a crater |
autoRunnerProjectile.exploded | { entityId, owner, kind, x, z, radius, ground } | listens: a bomb with ground true becomes a crater |
Needs
- MeshPrimitive draws the hazard and gives each car's position.
- CarDrive marks which entities are cars, and gives their heading.
- CarCollision takes the spin, skips ghost cars, and scales crater damage by
damageTaken. - AutoRunnerDriver takes the blind from smoke.
- Health takes crater damage.









































