Basic

Tuning numbers so the game feels right

Feel is numbers, and numbers need a place to live that is not inside the logic. A small table of named values, read by the rules, lets a designer change a value without touching a function, and lets a change be described in one line.

What you will see

Value, judgement, date. The next person knows what was tried and rejected.

About 1 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

Extract and tune one value

1

Move the numbers out

printf 'const TUNE = { runSpeedPxPerSecond: 180, jumpHeightPx: 64, gravityPxPerSecond2: 1400 }; ' | tee game/tune.js

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Named values with units. No number appears bare in a rule after this.
2

Read the table in the rule

printf 'w.player.vx = TUNE.runSpeedPxPerSecond * dt; ' | tee -a game/tune.js

Before you run it, say out loud what it will print. Then open the answer.

What it prints
The rule reads a name. Editing the number needs no edit to the rule.
3

Change one value only

set runSpeedPxPerSecond to 240 and change nothing else, then play the same section

Before you run it, say out loud what it will print. Then open the answer.

What it prints
One judgement about one value. If two values changed, the judgement belongs to neither.
4

Record the judgement

printf 'runSpeedPxPerSecond 240: too fast on the first gap (2026-10) ' | tee -a docs/tune-log.md

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Value, judgement, date. The next person knows what was tried and rejected.
Do not change two values in one pass. The result cannot be attributed, and the tuning becomes a guessing game.

Data Flow

Table to a felt change
1 Pick one value
↓
2 Change it and nothing else
↓
3 Play the same section
↓
4 Record the judgement with the value
Why this works
How to judge a change

Play the same section before and after. If the section is not repeatable, the judgement is not about the number.

Where the table grows

Group by feature, not by value type. A flat list of forty names is a file nobody can find anything in.

Examples

Name every magic number

A number in a rule is a name in the table. The rule reads the name, so the designer edits one file and no logic.

Units in the name

jumpHeightPx and runSpeedPxPerSecond. A name without a unit is a name that lies the moment the code changes.

Change one value at a time

One value, one run, one judgement. Two values changed together cannot be attributed to either, which is the same rule as performance bisection.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Rules that read state and change state only
Previous Lesson
Rules that read state and change state only
Next Lesson
A fixed-step machine for deterministic rules
A fixed-step machine for deterministic rules →