Basic

Loops (Repetition)

A game can't run instructions just once, it must re-check everything thousands of times per second. Learn the for loop, the while loop, and the exact loop the game uses to scan its ground.

What you will see

Obstacle 0: spike Obstacle 1: pit Obstacle 2: wall wall

About 4 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

A game cannot run instructions just once, it must re-check everything thousands of times per second, which means loops are the engine of every frame. I want to stop guessing what a loop prints and actually watch one count, skip, and stop, then reproduce the exact ground-scan loop the finished game uses so I can read real game code the moment I meet it.

1

A for loop repeats a block a set number of times. Four parts live in the parentheses: start, condition, after, and the block. I print a counter five times and watch it print Line 0 through Line 4, then stop the moment the condition turns false. It stops at 4, not 5, the off-by-one feeling is normal and correct.

for (let i = 0; i < 5; i++) { console.log("Line " + i); }

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

What it prints
Line 0 Line 1 Line 2 Line 3 Line 4
The condition is i < 5, so the loop stops as soon as i reaches 5. That is why the last line printed is Line 4, not Line 5. Every part must be present or the loop never starts or runs forever.
2

A while loop repeats only while a condition stays true, no counter inside the parentheses. I print Try 0, Try 1, Try 2 and increment by hand inside the block. This is the trap the lesson warns about: a while loop has no automatic counter, so if I forget to change something, it runs forever. I never forget, because I keep the increment right there.

let attempts = 0 while (attempts < 3) { console.log("Try " + attempts); attempts++; }

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

What it prints
Try 0 Try 1 Try 2
The increments is what stops the loop, so it lives inside the block. Drop it and the condition stays true forever, an infinite loop. The for loop hides the counter; the while loop forces me to own it.
3

Now the real game pattern: loop over a list of ground segments and find the one beneath the player. I keep a best value that starts at Infinity, skip gaps and inactive segments with continue, and only replace best with a lower ground. This is the exact shape from the finished game's groundUnder scan in app1.

function groundUnder(segments, playerY) { let best = Infinity for (const g of segments) { if (!g.active || g.gap) continue if (g.y >= playerY - 4) best = g.y } return best } const segments = [ { active: true, gap: true, y: 300 }, { active: true, gap: false, y: 400 }, { active: false, gap: false, y: 500 } ] console.log(groundUnder(segments, 396))

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

What it prints
400
The first segment is a gap so continue skips it; the third is inactive and also skipped; the second is active and its y of 400 clears the threshold, so best becomes 400. Infinity is the default only if nothing matches, meaning no ground at all.
4

Inside a loop you often want to skip an item or stop entirely. continue abandons the rest of this round and moves on; break exits the loop completely. I mix both in one loop: skip even numbers with continue, stop at 5 with break, and watch it print just 1 and 3 before quitting.

for (let i = 0; i < 10; i++) { if (i === 5) break if (i % 2 === 0) continue console.log(i) }

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

What it prints
1 3
The break fires before i itself is printed, so 5 never appears. continue skipped 0, 2, and 4, leaving only the odd numbers below 5. Real game loops are full of these guard clauses, skip gaps, skip off-screen objects, stop when done.
5

Arrays are used with loops, not read one by one by hand. I loop the safe way, guarding every access with i < obstacles.length, printing each item with its index, then grab the last item using length - 1. That last index is the #1 beginner trap: there is no item at index length, so the highest valid one is always length minus 1.

const obstacles = ['spike', 'pit', 'wall'] for (let i = 0; i < obstacles.length; i++) { console.log('Obstacle ' + i + ': ' + obstacles[i]) } console.log(obstacles[obstacles.length - 1])

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

What it prints
Obstacle 0: spike Obstacle 1: pit Obstacle 2: wall wall
The loop stops before i reaches length, so it never asks for a missing item. The last line uses length - 1 because a 3-item array has valid indices 0, 1, and 2 only, and asking for obstacles[3] would quietly return undefined.

Put it in order

Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.

Data Flow

A loop counter or condition repeats a block; each pass reads or updates one item until the loop stops.
1 Initialize a counter or check an initial condition
↓
2 Enter the block and process one item
↓
3 Update the counter (i++) or the tracked value
↓
4 Check the condition again, true loops, false exits
↓
5 continue skips the rest of a round; break exits early
Why this works
Looping over collections

Arrays (we meet them in Group 7) live and die by the loop. The classic safe pattern visits every item without running past the end:

const obstacles = ["spike", "pit", "wall"];
for (let i = 0; i < obstacles.length; i++) {
  console.log("Obstacle " + i + ": " + obstacles[i]);
}

i runs from 0 to length - 1. The highest valid index is length − 1, so asking for obstacles[4] on a 3-item array gives undefined: a silent bug, not an error.

A newer, cleaner form does the same thing without touching i:

for (const item of obstacles) {
  console.log(item);
}

This "for each item" form is what the game uses most when it scans coins, hazards, and ground.

Guards, continue, and breaking out

Inside a loop you often want to skip the current item or stop entirely:

  • continue: abandon the rest of this round and move to the next item. The ground loop uses it to skip gaps.
  • break: exit the loop completely, now.

for (let i = 0; i < 100; i++) {
  if (i === 5) break;      // stop at 5
  if (i % 2 === 0) continue; // skip even numbers
  console.log(i);          // prints 1, 3, 5...
}

A guard clause at the top of a loop body (like if (!g.active) continue) keeps the "happy path" code un-nested. Real game loops are full of them, skip inactive objects, skip off-screen objects, skip gaps.

Examples

The for loop

A for loop repeats a block a set number of times. Four parts in the parentheses:

for (let i = 0; i < 5; i++) {
  console.log("Line " + i);
}

PartCodeWhat it does
Startlet i = 0set a counter at 0
Conditioni < 5keep going while true
After roundi++add 1 each round
Block{ ... }code that runs every round

Trace it: prints Line 0 through Line 4, then stops the moment i < 5 is false at i = 5. Notice it prints up to 4, not 5, the off-by-one feeling is normal.

A real game loop: checking every ground segment

The game has many ground segments under the player. Every frame it finds the ground beneath them by looping over every segment:

function groundUnder(entity, groundSegments) {
  let best = Infinity;
  for (const g of groundSegments) {      // look at each segment, one at a time
    if (!g.active || g.gap) continue;    // skip gaps and off segments
    if (entity.x + entity.w > g.x && entity.x < g.x + g.w) {  // player above this one?
      if (g.y < best && g.y >= entity.y - entity.h - 4) best = g.y;
    }
  }
  return best;   // the ground to land on, or "nothing found"
}

  • The for (const g of ...) loop takes each segment in turn.
  • continue skips the rest of this round and jumps to the next segment.
  • && combines two questions (Group 4!).
  • The function keeps the highest ground found so far.

Why it works: a single small block, repeated once per segment, becomes "find the ground under the player." That's the power of loops.

The while loop

A while loop repeats **while a condition stays true*: no counter required. Great for "keep going until something happens."

let attempts = 0;
while (attempts < 3) {
  console.log("Try " + attempts);
  attempts++;              // IMPORTANT: change something or it runs forever!
}

⚠️ The loop trap: a while loop has no automatic counter. If you forget to change the condition, it runs forever (an infinite loop). Always make sure something inside changes the condition.

Loops 1 (for) and 5 (while) have real twins in the game, one counts up, one retries until success.

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.

← Control Flow: Conditionals
Previous Lesson
Control Flow: Conditionals
Next Lesson
Functions
Functions →