5 minutes
Every answer this stage has so far runs through the front bumper, and lesson 4 made that expensive — the ram that kills a hostile bills you for the same collision. Outrunning the problem is not the plan either: the red pool's profile tops out at 34 against your 30. A combat car needs something it can leave behind it.
Two charges, three clocks
One component, on the player, next to the drive law:
No new entity. deployKeys is a list of KeyboardEvent.code values, and the Input entity from lesson 2 is what publishes the keyboard.keydown those keys are matched against — without it the car has a rack of smoke and no button.
A screen is not one cloud, and the state it needs to be four numbers wide:
Press the button and the car vents for ventSeconds, dropping a puff every dropInterval — a line of overlapping clouds laid down the road, each blinding for puffLifetime before it thins out. Which is why the screen keeps working while you are turning: the puffs mark where you were.
stepSmokeScreen advances all four in one call and reports what the frame owes:
The second call is the interesting one. The button is down, the rack is not empty, and nothing happens — a press made mid-vent is ignored, not refused, so leaning on the key cannot drain both charges into one cloud. refused is reserved for the press that finds an empty rack, and it is what fires smokeScreen.depleted for the empty-click sound.
drops is normally 0 or 1. It goes higher only after a long frame, because dropTimer carries its remainder across frames rather than resetting: puff spacing comes out identical at 30fps and at 144, and a hitch drops the puffs it owes instead of skipping them, capped at maxPuffs so a stall cannot mint a hundred clouds.
Continue reading
Unlock the Full Course
Every lesson, the runnable examples, and the finished build — yours to keep.