The game loop
You'll learn how a game moves things by changing numbers many times a second, in a loop.
Watch & read
Start with the required ones. The others are there when you need them.
See it step by step
Tick by tick, the obstacle's number goes down and the box moves left.
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:
- Update: change the numbers (the obstacle is now 10 points further left).
- 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).
Code tour
Click a line number with a ring to read the note for that line.
Practice
Short drills. Take your time and read the code before you answer.
1const SPEED = 10;2const SCREEN_WIDTH = 400;3const OBSTACLE_WIDTH = 30;45function step(game) {6 let obstacleX = game.obstacleX - SPEED;7 if (obstacleX < -OBSTACLE_WIDTH) obstacleX = SCREEN_WIDTH;8 return { ...game, obstacleX: obstacleX };9}1011let game = { obstacleX: 300, playerY: 0, score: 0 };12game = step(game);13game = step(game);14game = step(game);15console.log(game.obstacleX);
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.1import { useEffect, useState } from "react";2import { StyleSheet, Text, View } from "react-native";34const 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.
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.Quick check
3 questions. Each one explains itself after you answer.
- 1 / 3In our game, what happens on every tick?
- 2 / 3
setInterval(tick, 50)runstickhow often? - 3 / 3What goes wrong if the effect does not return
() => clearInterval(id)?