Command Palette

Search for a command to run...

Hectal
Course outline
Topic 16.5Advanced ~31 min · step 5 of 6

A Test Ride

In one line

A small game is a loop of input, physics and camera: held keys or buttons set forces, the world steps at a fixed rate, the camera follows, and a watchdog resets the bike when it falls over. Script the input with fixed steps and the whole ride becomes testable.

0/6 · 0%

Think of it like this

A driving lesson on an empty car park. The learner presses pedals (input), the car obeys physics, the instructor watches from the passenger seat (the follow camera), and if the car ends up on the kerb, everyone gets out and puts it back on the start line (the reset).

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

input state
What the player is doing right now (pedal held, brake held), kept in an object the physics step reads.
linear damping
A force against motion proportional to speed, the engine's stand-in for rolling resistance and air.
follow camera
A camera that moves with the player's object each step, keeping it in view.
watchdog
Code that notices a stuck or broken state (on its side, off the track) and recovers from it.
scripted input
Input set by code at known step counts, so a test sees the same ride every time.

Step by step

01Read the scripted ride

The first example sets ride.input.pedal, ride.input.brake, and calls ride.step() a fixed number of times. No clock is involved, so the numbers repeat exactly.

02Check the physics with arithmetic

Top speed 30 / (20 × 0.3) = 5 m/s, approached as 5 × (1 − e^(−0.3 t)). After the brake the last 8 s start from almost a standstill: the formula gives 4.55 m/s, a run with no ramp prints 4.50 m/s, and the ramp costs a little more (4.31 m/s). The camera's movement equals the bike's.

03Flip it on purpose

The second example gives the body an angular velocity of 14 rad/s round z, watches the watchdog, then calls end(), which removes the track and restores Phase 9's showroom speed.

04Add the controls

In the build (Topic 16.6), held keys and held buttons write the same input object: W or the up arrow, S, the down arrow or Space; Pedal and Brake buttons use pointer events, so mouse, touch and pen all work.

Try it yourself

  1. 1

    Pedal harder

    In the first example, set PEDAL_FORCE to 60. Top speed doubles to 10 m/s: after 2 s it is at 4.45 m/s, and by the end it has ridden off the end of the 40 m track (measured: x 51.41, falling, tilted −100°). The watchdog puts it back one second later.

  2. 2

    Softer brakes

    Set BRAKE_DAMPING to 1. After 1 s of braking the bike still rolls at 0.83 m/s (it was 0.05 with 4). Damping removes a share of the speed each step, so it never quite reaches 0 on its own; damping 4 gets close enough within a second.

Code & diagrams

A scripted test ride New tab

The real `physics.js` of the build, inlined, with a stand-in bike. Fixed step counts, so the numbers are the same every run.

idle

Console

Run the scene to see its console.

Expected console output

settled on the track     x -0.00 | speed 0.00 m/s | y -0.00 | tilt -0.0°
2 s pedalling            x 2.46 | speed 2.23 m/s | y -0.00 | tilt -0.0°
1 s braking              x 3.04 | speed 0.05 m/s | y -0.00 | tilt -0.0°
8 s more pedalling       x 25.28 | speed 4.31 m/s | y -0.00 | tilt -0.0°
highest point over the ramp: 0.12 m | the camera followed: 25.28 m
The bike flips over, and comes back New tab
idle

Console

Run the scene to see its console.

Expected console output

rolling                  x 2.46 | speed 2.23 m/s | y -0.00 | tilt -0.0°
0.67 s after the kick    x 4.31 | speed 1.82 m/s | y 0.86 | tilt 83.3°
1.5 s later              x -0.00 | speed 0.00 m/s | y -0.00 | tilt -0.0°
after end(): track in the scene: false | wheel speed back to 1.667 m/s

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Leave the friction rule at its default

In the first example, remove .setFrictionCombineRule(RAPIER.CoefficientCombineRule.Min) from the wheels.

terminal
$ Press Run
── what you'll see ──
2 s pedalling x 0.00 | speed -0.00 m/s | y -0.00 | tilt -0.0°
The bike never moves, however long you pedal.

Myth vs fact

Myth

A game loop reads the keyboard and moves the object.

Fact

Input sets forces or targets; the physics step moves the object. Moving it directly skips collisions and makes it teleport (Topic 16.4).

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Scripted input at fixed steps turns a game into a unit test: the same inputs give the same positions, so you can assert "after 2 s of pedalling, speed is 2.23 m/s" in CI.

  • ▸

    Pointer events on hold-buttons need touch-action: none (no scrolling or zooming starts on the button) and pointerleave and pointercancel as well as pointerup, or a finger that slides off the button leaves the pedal stuck down.

Remember this

  1. 1

    The problem this solves: Tomás wants customers to feel the bike: push, roll, brake, go over a bump. That needs input that works with a keyboard, a mouse and a finger, a camera that keeps the bike in view, and a way back when things go wrong, because in physics things do go wrong.

  2. 2

    One body, honest shapes. The ride's bike is one rigid body: a box for the frame (about 15.6 kg) and two balls for the wheels (about 2.3 kg each), about 20 kg in all. It may pitch (rotate round z, over the ramp) but not roll sideways or steer: enabledRotations(false, false, true). Its wheels have friction 0 with the Min combine rule, so they slide like perfectly rolling wheels; without that rule the floor's 0.5 averages to 0.25 and holds the bike still.

  3. 3

    Forces, not positions. Pedalling adds a 30 N force each step. Rolling resistance is linear damping 0.3, so the top speed is force / (mass × damping) = 30 / (20 × 0.3) = 5 m/s (18 km/h), reached gradually. Braking raises the damping to 4. The first example scripts a ride with fixed step counts: 2 s of pedalling reaches 2.23 m/s, 1 s of braking stops it, and 8 s more takes it over the ramp (12 cm up) to 4.31 m/s.

  4. 4

    The follow camera. After each step, the camera and its orbit target move by exactly the bike's movement, so the view angle stays the same and the visitor can still orbit round the bike. The example's camera travelled the same 25.28 m as the bike.

  5. 5

    The watchdog. If the bike's up direction tips below 0.3 (about 73° from upright) or it falls below y = −2, a timer counts; after one second the bike is reset to the start, with zero velocity. The second example kicks it into a flip: 0.67 s later it is at 83° and 0.86 m up, and 1.5 s later it is back at the start.

Explain it without notes

01

Walk through one frame of the test ride: from a held key to a moved camera.

02

Why does the ride use forces and damping instead of setting the bike's velocity directly?

Practice

01

Add a boost key (B) that doubles the pedal force while held.

02

Make the watchdog reset a fallen bike after half a second instead of one.

Done when you can

  • You drive a body with forces and damping from an input object

  • You can compute the top speed from force, mass and damping

  • You follow the body with the camera and orbit target together

  • You reset a fallen body with a watchdog, and test the ride with scripted steps