Mamun Labs Learn
JourneyGlossary
esc
  • Try “map”, “flexbox” or “state”.
Log in
Start learning
Phase 7 · 1 / 5The game loop
Phase 7Games
5 topics · 3–4 wks
  1. 1The game loop
  2. 2Touch input
  3. 3Simple animation
  4. 4Collisions and score
  5. 5Sound and saving the best score
JourneyPhase 7The game loop
01 / 10Overview

The game loop

You'll learn how a game moves things by changing numbers many times a second, in a loop.

Why it mattersEvery game, from Ludo on your phone to a car race, is a loop that updates the world and draws it again.
about 90 min·needs: useEffect, Your first Expo app
02 / 10

Watch & read

Start with the required ones. The others are there when you need them.

Article
Anatomy of a video gameMDN Web Docs · 15 min · English
MMamun's noteRead the first part, "Present, accept, interpret, calculate, repeat", and "Building a main loop in JavaScript". That is the whole idea of this topic. The later parts on timing and optimising are for big games; skip them.
Video
Intro to game development with JavaScript (the game loop part)YouTube · freeCodeCamp · 4 min · English
MMamun's noteWatch 11:42–15:47, the chapter "The game loop". He uses a web canvas instead of React Native, but the loop is the same idea. Stop when he starts keyboard input.
ArticleOptional
Scheduling: setTimeout and setIntervaljavascript.info · 15 min · English
MMamun's noteRead "setInterval" and "Canceling with clearTimeout". Then you know exactly what our loop and its cleanup do. Skip the zero-delay parts at the end.
VideoOptional
requestAnimationFrame() - Beau teaches JavaScriptYouTube · freeCodeCamp · 5 min · English
MMamun's noteFour minutes. requestAnimationFrame is the other way to run a loop, once per screen refresh. Our game uses setInterval because it is easier to read, but you will see this one in other game code.
03 / 10

See it step by step

Tick by tick, the obstacle's number goes down and the box moves left.

obstacleX300
playerY0
score0
Screen ■ ▮──────────────────────────────────────────
App.jsx
1function step(game) {
2 let obstacleX = game.obstacleX - SPEED;
3 if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;
4 return { ...game, obstacleX: obstacleX };
5}
6
7useEffect(() => {
8 const id = setInterval(() => {
9 setGame((g) => step(g));
10 }, 50);
11 return () => clearInterval(id);
12}, []);
The screen appears. The effect starts a timer. game is { obstacleX: 300, playerY: 0, score: 0 }. Each character on the screen below is 10 points.
Step 1 / 9
04 / 10

Explanation

You want a box on the screen to slide from right to left by itself, like the boundary rope rushing past on a cricket replay. Nobody taps anything. It just moves.

A game is a flip book. Each page is a little different from the one before. Flip fast and it looks like movement. In code, each page is called a tick. On every tick the game does two things:

  1. Update: change the numbers (the obstacle is now 10 points further left).
  2. Draw: show the screen for those new numbers.

That repeat, update and draw, over and over, is the game loop.

In React Native, React already does the "draw" part. When state changes, it renders again. So your loop only has to change state. setInterval runs a function again and again, here every 50 ms (20 times a second):

useEffect(() => {
const id = setInterval(() => {
setGame((g) => step(g));
}, 50);
return () => clearInterval(id);
}, []);

The whole game lives in one object, game, with obstacleX, playerY and score. step(g) takes this tick's game and returns the next one:

function step(game) {
let obstacleX = game.obstacleX - SPEED;
if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;
return { ...game, obstacleX: obstacleX };
}

When the obstacle has gone off the left edge, it jumps back to the right edge and comes again.

To draw it, the box gets position: "absolute" and left: game.obstacleX. Absolute position means "put it exactly this many points from the left", not "put it after the box before it".

People often forget the cleanup. Without return () => clearInterval(id), the timer keeps running after the screen is gone. In development React runs effects twice, so you get two timers and the obstacle moves twice as fast.

When you read a game loop, find three things: how often it ticks (the 50), what changes on each tick (step), and where the timer is stopped (the cleanup).

Words to recognise
game loopticksetIntervalclearIntervalabsolute positioncleanup
05 / 10

Code tour

Click a line number with a ring to read the note for that line.

App.jsx5 notes
1export default function App() {
2 const [game, setGame] = useState({ obstacleX: 400, playerY: 0, score: 0 });
3
4 useEffect(() => {
const id = setInterval(() => {
Mentor note · line 5
setInterval starts the loop. The 50 means one tick every 50 ms, 20 ticks a second.
setGame((g) => step(g));
7 }, 50);
return () => clearInterval(id);
}, []);
10
11 return (
12 <View style={styles.world}>
<View style={[styles.obstacle, { left: game.obstacleX }]} />
14 </View>
15 );
16}
06 / 10

Practice

Short drills. Take your time and read the code before you answer.

DrillPredict1 / 3
1const SPEED = 10;
2const SCREEN_WIDTH = 400;
3const OBSTACLE_WIDTH = 30;
4
5function step(game) {
6 let obstacleX = game.obstacleX - SPEED;
7 if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;
8 return { ...game, obstacleX: obstacleX };
9}
10
11let game = { obstacleX: 300, playerY: 0, score: 0 };
12game = step(game);
13game = step(game);
14game = step(game);
15console.log(game.obstacleX);
After 3 ticks, what is obstacleX?
DrillFind the bug2 / 3
step(game) should move the obstacle 10 points to the left. When it has gone past the left edge (below -30), it starts again at the right edge, 400. Right now the obstacle runs away to the right. Fix step.
1
2
3
4
5
6
7
8
9
10
11
Try 1 of 3 · solution unlocks after 3
DrillStart the game loop3 / 3
This is the first piece of the tap-to-jump game. The obstacle slides in from the right, forever. Play with the numbers to feel how the loop works.
1import { useEffect, useState } from "react";
2import { StyleSheet, Text, View } from "react-native";
3
4const SPEED = 10;
5const SCREEN_WIDTH = 400;
6const OBSTACLE_WIDTH = 30;

Runs in the browser. Choose “My Device” in Snack to try it on your phone with Expo Go.

Working whenChange SPEED to 20. The obstacle crosses the screen twice as fast.Change the 50 in setInterval to 200. It moves in slow, jerky steps. Put it back to 50.Make the obstacle come from the left instead: start at -30, add SPEED, and wrap back to -30 when it passes 400.
Check each goal yourself, then mark it.
07 / 10

Quick check

3 questions. Each one explains itself after you answer.

  1. 1 / 3In our game, what happens on every tick?
  2. 2 / 3setInterval(tick, 50) runs tick how often?
  3. 3 / 3What goes wrong if the effect does not return () => clearInterval(id)?
08 / 10

Explain it back

Only you can see this. Log in to keep it.0 words
09 / 10

How confident are you with The game loop?

10 / 10

Done

You can now
Read a game loop in React Native and say how far something moves after a few ticks.
Next: Touch input Back to Phase 7
On this page
  1. 01The game loop
  2. 02Watch & read
  3. 03See it step by step
  4. 04Explanation
  5. 05Code tour
  6. 06Practice
  7. 07Quick check
  8. 08Explain it back
  9. 09Confidence
  10. 10Done
Up next · 02 / 10Watch & read
Mamun Labs LearnFound a mistake on this page? Tell Mamun.
Mamun Labs Learn
JourneyGlossary
esc
  • Try “map”, “flexbox” or “state”.
Log in
Start learning
Log in to save your progress. Everything here works without an account.Log in to save progressLog in
Phase 7Games
5 topics · 3–4 wks
  1. 1The game loop
  2. 2Touch input
  3. 3Simple animation
  4. 4Collisions and score
  5. 5Sound and saving the best score
JourneyPhase 7The game loop
01 / 10Overview

The game loop

You'll learn how a game moves things by changing numbers many times a second, in a loop.

Why it mattersEvery game, from Ludo on your phone to a car race, is a loop that updates the world and draws it again.
about 90 min·needs: useEffect, Your first Expo app
02 / 10

Watch & read

Start with the required ones. The others are there when you need them.

Article
Anatomy of a video gameMDN Web Docs · 15 min · English
MMamun's noteRead the first part, "Present, accept, interpret, calculate, repeat", and "Building a main loop in JavaScript". That is the whole idea of this topic. The later parts on timing and optimising are for big games; skip them.
Video
Intro to game development with JavaScript (the game loop part)YouTube · freeCodeCamp · 4 min · English
MMamun's noteWatch 11:42–15:47, the chapter "The game loop". He uses a web canvas instead of React Native, but the loop is the same idea. Stop when he starts keyboard input.
ArticleOptional
Scheduling: setTimeout and setIntervaljavascript.info · 15 min · English
MMamun's noteRead "setInterval" and "Canceling with clearTimeout". Then you know exactly what our loop and its cleanup do. Skip the zero-delay parts at the end.
VideoOptional
requestAnimationFrame() - Beau teaches JavaScriptYouTube · freeCodeCamp · 5 min · English
MMamun's noteFour minutes. requestAnimationFrame is the other way to run a loop, once per screen refresh. Our game uses setInterval because it is easier to read, but you will see this one in other game code.
03 / 10

See it step by step

Tick by tick, the obstacle's number goes down and the box moves left.

obstacleX300
playerY0
score0
Screen ■ ▮──────────────────────────────────────────
App.jsx
1function step(game) {
2 let obstacleX = game.obstacleX - SPEED;
3 if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;
4 return { ...game, obstacleX: obstacleX };
5}
6
7useEffect(() => {
8 const id = setInterval(() => {
9 setGame((g) => step(g));
10 }, 50);
11 return () => clearInterval(id);
12}, []);
The screen appears. The effect starts a timer. game is { obstacleX: 300, playerY: 0, score: 0 }. Each character on the screen below is 10 points.
Step 1 / 9
04 / 10

Explanation

You want a box on the screen to slide from right to left by itself, like the boundary rope rushing past on a cricket replay. Nobody taps anything. It just moves.

A game is a flip book. Each page is a little different from the one before. Flip fast and it looks like movement. In code, each page is called a tick. On every tick the game does two things:

  1. Update: change the numbers (the obstacle is now 10 points further left).
  2. Draw: show the screen for those new numbers.

That repeat, update and draw, over and over, is the game loop.

In React Native, React already does the "draw" part. When state changes, it renders again. So your loop only has to change state. setInterval runs a function again and again, here every 50 ms (20 times a second):

useEffect(() => {
const id = setInterval(() => {
setGame((g) => step(g));
}, 50);
return () => clearInterval(id);
}, []);

The whole game lives in one object, game, with obstacleX, playerY and score. step(g) takes this tick's game and returns the next one:

function step(game) {
let obstacleX = game.obstacleX - SPEED;
if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;
return { ...game, obstacleX: obstacleX };
}

When the obstacle has gone off the left edge, it jumps back to the right edge and comes again.

To draw it, the box gets position: "absolute" and left: game.obstacleX. Absolute position means "put it exactly this many points from the left", not "put it after the box before it".

People often forget the cleanup. Without return () => clearInterval(id), the timer keeps running after the screen is gone. In development React runs effects twice, so you get two timers and the obstacle moves twice as fast.

When you read a game loop, find three things: how often it ticks (the 50), what changes on each tick (step), and where the timer is stopped (the cleanup).

Words to recognise
game loopticksetIntervalclearIntervalabsolute positioncleanup
05 / 10

Code tour

Click a line number with a ring to read the note for that line.

App.jsx5 notes
1export default function App() {
2 const [game, setGame] = useState({ obstacleX: 400, playerY: 0, score: 0 });
3
4 useEffect(() => {
const id = setInterval(() => {
Mentor note · line 5
setInterval starts the loop. The 50 means one tick every 50 ms, 20 ticks a second.
setGame((g) => step(g));
7 }, 50);
return () => clearInterval(id);
}, []);
10
11 return (
12 <View style={styles.world}>
<View style={[styles.obstacle, { left: game.obstacleX }]} />
14 </View>
15 );
16}
06 / 10

Practice

Short drills. Take your time and read the code before you answer.

DrillPredict1 / 3
1const SPEED = 10;
2const SCREEN_WIDTH = 400;
3const OBSTACLE_WIDTH = 30;
4
5function step(game) {
6 let obstacleX = game.obstacleX - SPEED;
7 if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;
8 return { ...game, obstacleX: obstacleX };
9}
10
11let game = { obstacleX: 300, playerY: 0, score: 0 };
12game = step(game);
13game = step(game);
14game = step(game);
15console.log(game.obstacleX);
After 3 ticks, what is obstacleX?
DrillFind the bug2 / 3
step(game) should move the obstacle 10 points to the left. When it has gone past the left edge (below -30), it starts again at the right edge, 400. Right now the obstacle runs away to the right. Fix step.
1
2
3
4
5
6
7
8
9
10
11
Try 1 of 3 · solution unlocks after 3
DrillStart the game loop3 / 3
This is the first piece of the tap-to-jump game. The obstacle slides in from the right, forever. Play with the numbers to feel how the loop works.
1import { useEffect, useState } from "react";
2import { StyleSheet, Text, View } from "react-native";
3
4const SPEED = 10;
5const SCREEN_WIDTH = 400;
6const OBSTACLE_WIDTH = 30;

Runs in the browser. Choose “My Device” in Snack to try it on your phone with Expo Go.

Working whenChange SPEED to 20. The obstacle crosses the screen twice as fast.Change the 50 in setInterval to 200. It moves in slow, jerky steps. Put it back to 50.Make the obstacle come from the left instead: start at -30, add SPEED, and wrap back to -30 when it passes 400.
Check each goal yourself, then mark it.
07 / 10

Quick check

3 questions. Each one explains itself after you answer.

  1. 1 / 3In our game, what happens on every tick?
  2. 2 / 3setInterval(tick, 50) runs tick how often?
  3. 3 / 3What goes wrong if the effect does not return () => clearInterval(id)?
08 / 10

Explain it back

Only you can see this. Log in to keep it.0 words
09 / 10

How confident are you with The game loop?

10 / 10

Done

You can now
Read a game loop in React Native and say how far something moves after a few ticks.
Next: Touch input Back to Phase 7
On this page
  1. 01The game loop
  2. 02Watch & read
  3. 03See it step by step
  4. 04Explanation
  5. 05Code tour
  6. 06Practice
  7. 07Quick check
  8. 08Explain it back
  9. 09Confidence
  10. 10Done
Up next · 02 / 10Watch & read

You want a box on the screen to slide from right to left by itself, like the boundary rope rushing past on a cricket replay. Nobody taps anything. It just moves.

A game is a flip book. Each page is a little different from the one before. Flip fast and it looks like movement. In code, each page is called a tick. On every tick the game does two things:

  1. Update: change the numbers (the obstacle is now 10 points further left).
  2. Draw: show the screen for those new numbers.

That repeat, update and draw, over and over, is the game loop.

In React Native, React already does the "draw" part. When state changes, it renders again. So your loop only has to change state. setInterval runs a function again and again, here every 50 ms (20 times a second):

useEffect(() => {
const id = setInterval(() => {
setGame((g) => step(g));
}, 50);
return () => clearInterval(id);
}, []);

The whole game lives in one object, game, with obstacleX, playerY and score. step(g) takes this tick's game and returns the next one:

function step(game) {
let obstacleX = game.obstacleX - SPEED;
if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;
return { ...game, obstacleX: obstacleX };
}

When the obstacle has gone off the left edge, it jumps back to the right edge and comes again.

To draw it, the box gets position: "absolute" and left: game.obstacleX. Absolute position means "put it exactly this many points from the left", not "put it after the box before it".

People often forget the cleanup. Without return () => clearInterval(id), the timer keeps running after the screen is gone. In development React runs effects twice, so you get two timers and the obstacle moves twice as fast.

When you read a game loop, find three things: how often it ticks (the 50), what changes on each tick (step), and where the timer is stopped (the cleanup).

Words to recognise
game loopticksetIntervalclearIntervalabsolute positioncleanup

You want a box on the screen to slide from right to left by itself, like the boundary rope rushing past on a cricket replay. Nobody taps anything. It just moves.

A game is a flip book. Each page is a little different from the one before. Flip fast and it looks like movement. In code, each page is called a tick. On every tick the game does two things:

  1. Update: change the numbers (the obstacle is now 10 points further left).
  2. Draw: show the screen for those new numbers.

That repeat, update and draw, over and over, is the game loop.

In React Native, React already does the "draw" part. When state changes, it renders again. So your loop only has to change state. setInterval runs a function again and again, here every 50 ms (20 times a second):

useEffect(() => {
const id = setInterval(() => {
setGame((g) => step(g));
}, 50);
return () => clearInterval(id);
}, []);

The whole game lives in one object, game, with obstacleX, playerY and score. step(g) takes this tick's game and returns the next one:

function step(game) {
let obstacleX = game.obstacleX - SPEED;
if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;
return { ...game, obstacleX: obstacleX };
}

When the obstacle has gone off the left edge, it jumps back to the right edge and comes again.

To draw it, the box gets position: "absolute" and left: game.obstacleX. Absolute position means "put it exactly this many points from the left", not "put it after the box before it".

People often forget the cleanup. Without return () => clearInterval(id), the timer keeps running after the screen is gone. In development React runs effects twice, so you get two timers and the obstacle moves twice as fast.

When you read a game loop, find three things: how often it ticks (the 50), what changes on each tick (step), and where the timer is stopped (the cleanup).

Words to recognise
game loopticksetIntervalclearIntervalabsolute positioncleanup