Basic

Arrays

One variable holds one value, but a game is full of collections. Learn arrays, ordered lists you can read, add to, and loop over, the same operations the game does every frame.

What you will see

A, C

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

One variable holds one value, but a game is full of collections, a list of obstacles, a list of coins, a whole level built one piece at a time. Arrays are ordered lists I can read, add to, and loop over, exactly the operations the game performs every frame. I want to build the real build-then-use pattern: push items onto an array, then walk it with a loop.

1

An array is an ordered list in square brackets, and I read items by their index, their position. JavaScript starts counting at 0, so the first item is obstacles[0], not obstacles[1]. I make a list and read the first and last items I know.

const obstacles = ["spike", "pit", "wall", "coin"] console.log(obstacles[0]) console.log(obstacles[3])

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

What it prints
spike coin
Index 0 is the first item, spike; index 3 is the fourth, coin. Starting at 0 is the single most common beginner off-by-one, so count on your fingers: first item is index 0.
2

.length tells me how many items are in the list, which lets me read the LAST item safely as obstacles[length - 1]. A 4-item array has indices 0, 1, 2, 3, there is no index 4, so asking for obstacles[4] quietly returns undefined instead of erroring.

const obstacles = ["spike", "pit", "wall", "coin"] console.log(obstacles.length) console.log(obstacles[obstacles.length - 1])

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

What it prints
4 coin
A 4-item array has highest index 3, which is length (4) minus 1. Asking for obstacles[4] returns undefined, a silent bug, not a crash, which is why loops always guard with i < obstacles.length.
3

.push adds to the end of the list; .pop removes from the end. I start with two items, push one more, then pop it back off and watch the list grow and shrink by one each time. Both act on the end, which is fast, so I keep the end as the active side.

const obstacles = ["spike", "pit"] obstacles.push("wall") console.log(obstacles) obstacles.pop() console.log(obstacles)

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

What it prints
[ "spike", "pit", "wall" ] [ "spike", "pit" ]
.push adds wall to the end; .pop takes it back off the end. The array is now back to its original two items. Both operate on the end, which is fast, so never use them for the front of a list.
4

The pattern every game follows: build a list by pushing, then loop over it to use it. I start with an empty array, push three items one at a time, then loop with for...of to read each item. This build-then-use rhythm is what the level factory uses to grow the world.

const entities = [] entities.push('ground') entities.push('coin') entities.push('spike') for (const item of entities) { console.log('found ' + item) }

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

What it prints
found ground found coin found spike
The empty array grows by one push at a time, then the loop reads every item without ever going out of bounds. This exact build-then-use pattern is the game's whole level factory in miniature.
5

Now the real game recycle logic from app1/js/systems/SpawnController.js: every frame it keeps only the items still on screen, using filter to make a fresh list. An item is on screen if its right edge (x + w) is past the cutoff. I filter a list of obstacles down to the ones still visible.

const obstacles = [ { x: 400, w: 20, name: 'A' }, { x: -30, w: 20, name: 'B' }, { x: 400, w: 20, name: 'C' } ] const cutoff = 350 const visible = obstacles.filter(o => o.x + o.w > cutoff) console.log(visible.map(o => o.name).join(', '))

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

What it prints
A, C
A (400+20=420) and C (400+20=420) are past the cutoff of 350, so they stay. B (-30+20=-10) has scrolled off the left and is dropped. filter returns a NEW array, the original is untouched.

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

Items are pushed into an ordered list, indexed by number, and walked in a loop to be used.
1 Create an empty array with []
↓
2 push() adds each item to the end
↓
3 index into it with name[i] (0-based)
↓
4 length gives the count; last item is length - 1
↓
5 Loop with for...of to use every item
Why this works
Adding and removing items
  • .push(item) adds to the end.
  • .pop() removes from the end.

const obstacles = ["spike", "pit"];
obstacles.push("wall");              // -> ["spike", "pit", "wall"]
obstacles.pop();                     // -> ["spike", "pit"]

You actually used .push() without knowing it, you built strings with + in Group 2, and arrays with .push() here. Both accumulate by repetition. The finished game relies on .push() to grow the level and .filter() (Group 9) to shrink it.

Watch out: .push/.pop act on the end, which is fast. Adding or removing from the front with .unshift/.splice is slower, prefer keeping the end as the "active" side.

The build-then-use pattern

Almost every game in this tutorial follows the same two-phase rhythm:

// Phase 1, build: push items into an array
const entities = [];
entities.push(...);
entities.push(...);

// Phase 2, use: loop over the array
for (const item of entities) {
  // draw it, collide with it, update it
}

The level factory builds a list of ground, spikes, walls, and coins. The render loop draws them. The collision loop checks them. The same array, read many different ways. Mastering this one pattern, build once, use many, is most of the way to thinking like a game programmer.

Examples

Creating and reading arrays

An array is an ordered list. Square brackets [ ] make one; items are separated by commas. Read items by **index*: their position. JavaScript starts counting at 0, not 1.

const obstacles = ["spike", "pit", "wall", "coin"];
console.log(obstacles[0]);   // "spike"   (first)
console.log(obstacles[3]);   // "coin"    (fourth)

Index0123
Valuespikepitwallcoin

The #1 beginner mistake: asking for obstacles[4] when there are only 4 items. The highest valid index is length − 1 (here, 3).

The length of an array

.length tells you how many items are in the list. Now you can safely read the last item:

const obstacles = ["spike", "pit"];
console.log(obstacles.length);      // 2
const last = obstacles[obstacles.length - 1];   // obstacles[1]
console.log(last);                  // "pit"

for (let i = 0; i < obstacles.length; i++) {
  console.log(obstacles[i]);
}

A for loop uses length to visit every item without going out of bounds.

Watch out: arrays hold any values, strings, numbers, booleans, or a mix, so ["player", 56, true] is legal. The type of the items doesn't matter to the array.

A real game loop: building the level

The game builds its level by pushing items onto an array, one piece at a time. Here's the real code from app1/js/generation/LevelFactory.js:

entities.push(this.make(Ground, groundX, groundY, CONFIG.GROUND_HEIGHT, false));
entities.push(this.make(Ground, groundX + first + gap, groundY,
  chunkLen - first - gap, CONFIG.GROUND_HEIGHT, false));
entities.push(hz);                    // a spike
entities.push(wll);                   // a wall
entities.push(this.make(Coin, coinX, coinY));   // a coin

Each entities.push(...) adds one piece of the world. After enough pushes, entities holds the whole level. Then the game loops over that array to check collisions and draw everything.

So the two groups combine into a pattern you'll see again and again:

Build a list by pushing, then loop over the list to use it.

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.

← Functions
Previous Lesson
Functions
Next Lesson
Objects
Objects →