Lesson 12 of 22, in world 4: Visuals & Worlds
Tilemaps
Drawing every wall of a level as a separate rectangle would be painful. Most 2D games — Zelda, Mario, Stardew Valley, Celeste — build their worlds from a tilemap: a grid of small square images called tiles, stored as a 2D array of numbers.
A level is just an array
const TILE = 32
const map = [
[1, 1, 1, 1, 1, 1],
[1, 0, 0, 4, 0, 1], // 0 = floor, 1 = wall, 4 = coin
[1, 0, 1, 1, 0, 1],
[1, 1, 1, 1, 1, 1],
]
// Draw: loop over rows and columns
for (let row = 0; row < map.length; row++)
for (let col = 0; col < map[row].length; col++)
drawTile(map[row][col], col * TILE, row * TILE)Click or drag on the map to paint tiles. Walk with the arrow keys / WASD. Walls and water are solid; coins are collected. Toggle "Show the data" to see that the whole level is just a 2D array of numbers.
World ↔ tile coordinates
The single most important tilemap formula converts a pixel position to a grid cell, and back:
const col = Math.floor(worldX / TILE) // which column is this pixel in?
const row = Math.floor(worldY / TILE)
const worldX = col * TILE // top-left pixel of a cellCheap collisions with tiles
Here’s the big win: you don’t need to test against every wall. To check whether the player hits a wall, convert the corners of its hitbox to tile coordinates and look those cells up in the array — an O(1) lookup, no matter how big the level is. The demo moves one axis at a time (lesson 10) and simply refuses steps that would land in a solid tile.
Tilesets and autotiling
The images for each tile id live in a tileset — a sprite sheet of tiles (lesson 11). Autotiling automatically picks the right edge/corner tile by looking at each cell’s neighbours, so painting a blob of “grass” gives you nice borders without placing each piece by hand.
Key takeaways
- A tilemap is a 2D array of tile ids, drawn as a grid of tile images.
- col = floor(x / TILE), row = floor(y / TILE).
- Tile collisions are cheap: look up the cells under the hitbox corners.
- Levels as data are easy to edit, store and generate.
Check yourself
Q1. With 32 px tiles, which column is the pixel x = 100 in?
Q2. Why are tile collisions cheap?
Q3. map[2][5] refers to…
Exercises
- Paint a small maze and collect all coins. Then wall yourself in completely.
- Make water "slow" instead of solid: what would you change in the movement code?
- Write the level above as a list of strings ("1111", "1041", …) and a parser — that is how the demo stores it.