Start the runner and jump over the scrolling obstacles while the hero stays at a fixed horizontal position. Each jump requires a fresh activation while grounded. After two active seconds the distance is 200 logical pixels while hero x remains 50. The reproducible no-jump inspection loses at 2.51 seconds with distance 251; it does not award a pass or invent a finish after three obstacles.

Define a fixed hero and a scrolling world
Use a 320 × 240 logical field with floor y=220. The hero is 20 × 20 with fixed left x=50 and initial top y=200, grounded with vertical velocity zero.
Original obstacles are 24 × 24, top y=196 and bottom y=220. Each starts at x=320 and moves left at 100 logical pixels per simulation second. Spawn the first at time zero, then one every 1.8 simulation seconds.
The author's Canvas Runner tutorial describes a jumping player, moving obstacles and removal of old entities. This example uses a fixed obstacle schedule and a shared simulation clock. Author Reference: Canvas Runner
The drawing uses simple rectangles with readable position and state text. Logical pixels are model units; they are not real meters, miles or a physical running measurement.
Use the same active clock for distance and spawning
Define distance as 100 × active simulation time. After two active seconds, distance is 200 logical pixels while the hero still has x=50. The first obstacle has moved 200 pixels from x=320 to x=120.
This distance represents world scrolling, not the hero's horizontal coordinate or the number of rendered frames. Its value is nondecreasing during a run and remains unchanged while Paused or Lost.
The obstacle schedule uses that same clock. The original spawn times are 0, 1.8, 3.6, 5.4 seconds and onward. A hidden or paused ten-second wall-clock interval adds neither distance nor new scheduled obstacles.
Assign each obstacle an ID containing run generation and spawn index: G1-O1, G1-O2 and so on. A later obstacle must not inherit an earlier passed obstacle's ID just because a memory slot or drawing object is reused.
Use simulation ticks for schedule comparisons, so floating-point accumulation does not delay a nominal 1.8-second event. Spawns have age zero at the scheduled tick; position then depends on that age.
Check collision before recycling or credit
The grounded hero spans x=50–70 and y=200–220. The obstacle spans y=196–220. Strict positive rectangle overlap on both axes is a collision.
An obstacle left x=70 only touches the hero's right edge: no hit. At x=69, its horizontal interval overlaps by one pixel and a grounded hero is hit. At x=26, obstacle right=50 only touches the hero's left edge: no hit. That contact also has not passed the strict scoring threshold.
Within each 0.01-second step, the game checks the interval where the obstacle overlaps horizontally and compares the hero's full vertical trajectory there. This catches a descending overlap even when both sampled endpoints are clear. Jumping at 2.02 seconds loses during the 2.93-to-2.94-second interval; Inspect jump at 2.02s shows that result without replacing your current run.
Collision sets Lost before any pass credit or removal. Without a jump, the first obstacle reaches x=70 at t=2.5, touching only; at t=2.51 it reaches x=69 and the expected result is Lost. Distance at that terminal tick is 251 logical pixels, then frozen. Choose the no-jump inspection button to run this sequence through the game's updater.
Jump and pause the same world
A fresh grounded Jump sets vertical velocity of -300 with downward gravity 600. Each 0.01-second step updates position using prior velocity plus half the gravity displacement, then updates velocity. An isolated jump reaches y 173 after 0.1 seconds and y 125 at its 0.5-second apex before returning to floor y 200. Landing clamps velocity to zero and marks grounded.
The Jump button or focused Space/Arrow Up uses the same guarded action. Jump-button Space is handled on keydown. A held key or fresh airborne press cannot add another jump, and releasing Space after landing does not queue a jump. Other control buttons retain their normal keyboard activation. Start is not a jump. Pause, hiding the page or leaving the game region freezes physics, distance and spawning. Resume starts from a fresh timing stamp without hidden-time catch-up.
The loop caps each frame at ten simulation steps and discards excess elapsed time as a slowdown policy. Obstacle IDs include the run generation and spawn index. A surviving obstacle earns one pass only when its right edge is strictly less than 50, then leaves active collision tests. The stream has no Finished state; new scheduled obstacles continue until loss or pause.
Reset increments the generation, cancels the old callback and clears entities, metrics and input. The no-jump inspection button uses the same updater with no jump input. It is an executed deterministic diagnostic, not a claim that the obstacle stream is fair or indefinitely survivable.
Copy a prompt for this example
Create one self-contained HTML endless runner with embedded CSS and JavaScript. Use a 320 by 240 logical field, a floor at y = 220, simple original rectangles, large controls, and readable state and distance text.
The hero is 20 by 20 pixels with fixed left x = 50 and initial top y = 200. A fresh grounded jump sets vertical velocity to -300. Apply downward gravity of 600 using 0.01-second steps: update position from prior velocity plus half the gravity displacement, then update velocity. Clamp landing to y = 200 with zero velocity. Ignore airborne and repeated held-key jump requests.
Obstacles are 24 by 24 pixels at top y = 196. Start them at x = 320, move them left at 100 logical pixels per simulation second, and spawn at time zero and every 1.8 simulation seconds. Give each obstacle a run-generation and spawn-index ID.
Distance equals 100 times active simulation time. Check strict rectangle overlap throughout each step's horizontal-overlap interval, using the hero's quadratic vertical trajectory and floor clamp. Include the 2.02-second jump regression, which loses on the step ending at 2.94 seconds. Check collision before crediting a pass. A surviving obstacle passes once when its right edge is less than 50. Continue spawning without a Finished state.
Provide Start, Jump, Pause, Resume, and Reset, plus focused Space or Arrow Up controls. Limit each animation frame to ten steps. Hiding or leaving the game region pauses all motion and scheduling.
Add a no-jump inspection using the same updater. It must lose at 2.51 seconds with distance 251. Reset clears the run and invalidates old callbacks. Return only the complete HTML file.
For a clock-and-lifecycle review, NOS can display this prepared HTML runner. Compare active distance before and after Pause, inspect the no-jump loss, and compare those results with the JavaScript update function when adjusting jump or spawn timing.