Intermediate / Game state & scoring

Separate Racing Distance from Coin Bonuses

Screenshot of a source excerpt explained in this article.
Screenshot of a source excerpt explained in this article.

Lane Racer's counter is labeled progress rather than pure distance because collecting a coin increases the same value that grows with driving time. Calling that number meters would imply a measurement the model does not actually make.

What you'll build

We will trace the existing combined counter, calculate its two sources, and design an optional split between distance and bonus score. The shipped demo keeps the combined progress target described by its controls.

Working example · Open Lane Racer and source

Prerequisites

Know the racer state and its update loop. Progress begins at zero, grows by 30 times elapsed simulation seconds, and receives a 50-point bonus on coin contact. Difficulty changes the required target.

Read both sources of progress

At the beginning of each update, the racer adds dt * 30. Later in that update, a coin collision adds 50. A barrier collision removes a life instead. The final goal check sees the total after both continuous and contact-based changes.

In a hypothetical run without coins, a target of 1,500 would require 50 active simulation seconds. One coin contributes the equivalent of roughly 1.67 seconds of continuous progress. This is a comparison of the current scoring arithmetic, not a claim about real-world distance or guaranteed round length.

The active-time loop can discard long gaps, and coin availability depends on spawning and input. Those factors are why a score target should not be presented as a fixed wall-clock duration.

Keep labels faithful to the model

The status text says progress and the instructions explain that it combines distance and coin bonuses. This is clearer than borrowing a realistic unit such as meters without a world-speed model that supports it.

A tutorial should use the same terminology. Describing coins as “extra points” while silently allowing them to advance a distance-based victory condition creates two conflicting mental models. Read the update arithmetic before choosing the HUD label.

Split the fields for a different design

If you want coins to affect score but not completion distance, introduce separate fields and decide which one controls victory:

javascript
state.distance += dt * 30;
if (caughtCoin) state.bonus += 50;
state.score = state.distance + state.bonus;
state.won = state.distance >= distanceGoal;

This is a proposed alternative, not the current engine. It changes incentives: taking a risk for a coin no longer shortens the distance required to finish. The UI should display distance and bonus distinctly rather than showing a combined number beside a distance-only target.

Avoid storing a derived score unless another requirement needs it. A getter or status calculation can add distance and bonus when displaying them. Fewer stored fields mean fewer opportunities for them to disagree after restart or a future scoring change.

Define contact effects once

The racer consumes a caught object by moving it below the playfield and filtering it out. That protects both coin bonuses and barrier penalties from repeating across overlapping frames. Splitting score fields should preserve that lifecycle rule.

It should also preserve the lane-based contact condition unless you are intentionally changing collision. A scoring refactor becomes difficult to assess if it simultaneously changes obstacle geometry, movement, and target calculations.

Compare incentives with controlled scenarios

Test a run segment with no coins and another with one forced coin contact. Under the existing model, the second scenario should have 50 more progress at the same active time. Under the split model, distance should be equal while bonus differs.

Then test completion at a target boundary with a coin. The result reveals which field actually controls victory. This is more useful than verifying only that a coin changes some number on screen.

Restart after earning a bonus and inspect every new field. A split design adds initialization responsibilities; failing to reset bonus can make the second round begin with unexplained progress or score.

Next steps

Inspect Lane Racer's source and write down what each displayed number measures. If you implement the split, update status text, instructions, completion tests, and tutorial terminology together. Numerical accuracy is not only about arithmetic; it also depends on whether the label tells readers what the number means.