Skip to content
Techniques & Technology

Tile Maps

Building worlds from blocks

Tile maps constructed game worlds from small reusable graphic blocks, enabling large levels within tight memory constraints while simplifying collision detection and level design.

nintendo-entertainment-systemcommodore-64sega-mega-drivegame-boy graphicslevel-designtechnique 1980–present

Overview

Don't draw a forest — draw one tree and repeat it. Tile maps build game worlds from small graphic blocks (typically 8×8 or 16×16 pixels) arranged in a grid. One set of tiles can compose endless levels. Super Mario Bros. uses around 256 unique tiles to build its entire Mushroom Kingdom. Memory-efficient, collision-friendly, and the foundation for almost every 2D level editor of the era.

For the concept of tile-based rendering and which platforms supported it, see Tile-Based Graphics; this entry focuses on the map data structure.

Fast facts

  • Purpose: Construct levels from reusable blocks.
  • Tile size: Typically 8×8 or 16×16 pixels.
  • Memory saving: ~98% versus a 1-byte-per-pixel bitmap of the same screen.
  • Usage: Nearly universal in 8/16-bit era.

Memory efficiency

Comparison for a single 256×240 NES screen:

MethodMemoryNotes
1-byte-per-pixel bitmap61,440 bytesOne palette index per pixel
Tile map (32×30 cells, 8×8 tiles)960 bytesPlus a shared 4 KB tile set in CHR
Saving~98%Tile set is paid once; map data alone is ~1.5%

Tile map structure

ComponentPurpose
Tile setPixel definitions (CHR-ROM on NES, charset RAM on C64, VRAM on Mega Drive)
Map dataOne byte (or word) per cell, indexing the tile set
AttributesPer-region palette/flip/priority data
Collision flagsSolid, platform, hazard — usually a parallel array keyed by tile index

NES nametables

The NES PPU stores one screen's worth of tile indices in a nametable:

ElementSpecification
Tile size8×8 pixels
Nametable32×30 tiles = 960 bytes
Pattern tables256 tiles each (two 4 KB tables in CHR memory)
Attribute table64 bytes after each nametable; 4×4 tiles per byte, 2×2 tile palette resolution
Hardware nametables4 logical, 2 in PPU VRAM; mirroring (horizontal / vertical / four-screen via mapper) decides how the four logical tables overlap

Nametable address layout

$2000 + (row × 32) + col   ; row 0-29, col 0-31

For example, the bottom-right tile of nametable 0 is at $2000 + (29 × 32) + 31 = $23BF. The 64 attribute bytes for that nametable live at $23C0-$23FF.

Attribute byte layout

Each attribute byte covers a 32×32-pixel block (4×4 tiles), divided into four 2×2-tile palette quadrants:

bits 7-6: bottom-right 2×2 tiles
bits 5-4: bottom-left  2×2 tiles
bits 3-2: top-right    2×2 tiles
bits 1-0: top-left     2×2 tiles

Two tiles in the same 2×2 quadrant are forced to share a palette — a constraint that shapes NES tile design.

Collision detection

AdvantageExplanation
Grid-basedSimple coordinate lookup — tile = map[y >> 3][x >> 3] for 8×8 tiles
Tile propertiesA parallel tile_attrs[] table maps tile index → collision class
EfficientNo per-pixel checking; one shift and one indirect read per query
ConsistentPredictable behaviour, easy to debug

Level design workflow

StepProcess
1Create tile graphics
2Build tile set
3Design levels in editor
4Export map data
5Runtime: draw from map

Common tile types

TypeCollision
EmptyPass through
SolidBlock all
PlatformBlock from above only
HazardDamage on contact
CollectibleTrigger collection

Scrolling with tiles

ChallengeSolution
New tiles needed at edgeUpdate the nametable column/row off-screen each frame
Seam visibilityUpdate during VBlank or under the status bar split
Large levelsStream map data from ROM/disk in chunks

The NES updates one column (30 tiles) per frame as the screen scrolls horizontally — small enough to fit in the VBlank window. The Mega Drive does the same with two BG planes; the C64 typically updates a screen-edge column from a larger off-screen "level map" array.

See also