How a run works
Inside a run
What exactly happens between pushing the throttle and pulling it back. This page is for teachers who want to explain surprising behaviour, and for developers working on the engine. The rules are deterministic: the same program, with the same random numbers, always does the same thing.
Design and run are separate
A project is a design: characters, their placements and their trains. Pressing ▶ takes a snapshot of the design and runs that. Nothing a running program does is ever written back to the project. Stopping throws the run away and shows the design again:
- every character returns to its designed position, angle, size, costume, colour, hearts and body;
- clones disappear, and removed characters come back;
- variables, gravity, magnets, joints, the pen drawing and shown variable tiles are reset.
While a run is on, editing is locked (undo, redo and all edits are ignored), so the run and the design never get out of step.
Runners and threads
Two words explain almost everything:
- A runner is one character on the stage during a run. Every placement becomes a runner when ▶ is pressed, and every clone is a new runner. Each runner keeps its own state: hearts, size, opacity, costume, colour, body, weight, pen and every timers.
- A thread is one train running on one runner. When an event fires for a runner, every train of that character whose locomotive matches starts a thread on that runner. A thread remembers where it is in the train (including inside nested loops), how many loop passes are left, and what it is waiting for.
Because all of this state lives in the thread and the runner, never in the wagons themselves, the same train can run on five bricks at once without the bricks interfering with each other.
The 60 Hz clock
The engine simulates in fixed steps of 1/60 of a second. Each screen frame, the real time that passed is added to an accumulator, and as many whole steps as fit are run. A run therefore behaves the same on a fast Mac and a slow iPad. If the device stalls, at most 5 steps are caught up per frame and the rest of the lost time is dropped, so the program slows down rather than jumping ahead.
One step does this, always in the same order:
- Fire timers. Every few seconds trains whose time has come are started (if they are not still running).
- Run threads in a stable order. Threads are sorted by runner (placements in character order first, then clones in the order they were made), then by the train’s position in the character’s list. Each thread runs until it reaches a wagon that takes time, or until it finishes.
- Publish activity. The set of running trains and wagons per runner is handed to the editor, which lights them up.
After the step, the stage lets SpriteKit simulate physics, then checks which characters started touching each other or a wall, and turns those into bump events. Trains started by events, messages and clones begin on the next step.
Instant wagons and wagons that take time
Wagons come in two kinds:
| Kind | Wagons | Behaviour |
|---|---|---|
| takes time | Move, Turn, Say, Size, Fade, Wait, Wait until | The thread parks on the wagon. The animation advances a little on each step, and the thread moves on in the step where it completes. Wait until checks its condition once per step. |
| instant | All others | Done immediately. The thread carries on to the next wagon within the same step. |
So a train of Set A = 0 · Change A + 1 · Show A · Move 1 does the first three in the same 1/60 s and then spends a quarter of a second on the move.
Loops can’t freeze the app
Two safety rules keep runaway programs harmless:
- A thread may run at most 256 instant wagons per step. After that it waits for the next step.
- If one pass of a Repeat or Forever contains no wagon that takes time, the loop still pauses until the next step after that pass. A Forever made of instant wagons therefore runs 60 times a second, never thousands of times per frame.
Events in detail
No double starts
If an event fires for a runner while that very train is already running on it, the event is ignored. Tapping a character five times while its When tapped train is still turning starts nothing new. Every train that listens to the event starts, not only the first one.
Messages restart
The one exception is When a message arrives. A message restarts the train from its first wagon if it is already running, as Scratch broadcasts do. A speech bubble the old run was showing is removed. This is what makes message ping-pong between characters work (see the Ping-pong sample).
Broadcast events
Buttons, tilts and messages go to every runner, in runner order. Taps go only to the tapped character. Bumps go to both characters involved: if the cat bumps the banana, the cat’s When bumping Banana and the banana’s When bumping Cat both fire.
Contacts
Touching is measured geometrically from each character’s shape, independently of the physics engine. That is why ghosts, which pass through others, still detect touches. A contact begins when the shapes come within 1 pixel of each other and ends once they are more than 2.5 pixels apart. The gap between the two numbers stops a character resting on the floor from bumping it again and again.
Values at run time
- Variables A–D are global and start at 0 on every run.
- Random draws a fresh whole number every time it is read. The engine uses a seeded generator, so tests can replay a run exactly.
- x and y are read in tiles, angle in 0–359, size in percent, and the timer in seconds since the start (it advances in 1/60 s steps).
- A value that would not be a valid number (for example from a huge multiplication) reads as 0. Variables only ever store finite numbers.
- Two numbers within one millionth of each other compare as equal.
Clones and removal
- Clone makes a new runner with a copy of the current state. It runs When I start as a clone trains and also has its own every timers. It does not run When ▶ is pressed.
- There can be at most 128 runners at once. Further clones are skipped, so a cloning loop cannot flood the stage.
- Remove stops all of the runner’s threads immediately and takes its sprite away.
Winning and losing
The moment a Win or Lose wagon runs, the engine records the outcome and stops every thread. No further wagons run, even later ones in the same step. Physics freezes, the celebration plays, and the outcome card appears. Choosing Play again resets and runs again; Edit goes back to the design.
Physics
Physics uses SpriteKit, tuned for the 256-pixel world. The numbers below are what the app uses.
| Quantity | Value |
|---|---|
| Gravity (when on) | About 400 px/s² downward (25 tiles/s²). Falling across the stage takes about a second. |
| Weights | light 0.5 · normal 1 · heavy 2.5 |
| Kick | An impulse giving a normal-weight body 50 px/s per point of strength. Strength 5 ≈ 250 px/s ≈ a 5-tile jump with gravity on. |
| Magnet | A radial field reaching 128 px (8 tiles), about 200 px/s² at 4 tiles, weakening with distance. It never pulls its owner. |
| Bounciness | restitution 0.45, friction 0.3 |
| Air drag | 0.2 for physics bodies, 0.6 for ghosts (they drift to a stop) |
| Rotation | Bodies don’t spin from collisions; only hinge joints let them rotate freely. |
| Player drag | Pulled at up to 900 px/s; released at up to 500 px/s. |
| Walls | Static slabs 64 px thick just outside each edge, so fast bodies cannot tunnel through. |
Body types
| Body | Shape | Moves? | Gravity | Collides with | Detects touches |
|---|---|---|---|---|---|
| Physics | circle (80 % of the sprite) | yes | yes | characters and walls | yes |
| Fixed | square (80 % of the sprite) | only by wagons or dragging | no | is collided with | yes |
| Ghost | circle | yes | no | walls only | yes |
Move and Go to place the character directly, frame by frame, and clear its speed. This is the same behaviour as the original app: a moving character stays on course, and other physics bodies still bump into it.
Sound during a run
The GAME music plays while the program runs. The two GAME tracks alternate, and the music crossfades from and back to the coding music. Effects are synthesised on the fly as square, triangle and noise chiptune blips: run and stop, bumps (at most one every 0.08 s), messages, the puff of a removal, hearts, and the win and lose jingles. The music ducks briefly under each effect.
