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.
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:
| Method | Memory | Notes |
|---|---|---|
| 1-byte-per-pixel bitmap | 61,440 bytes | One palette index per pixel |
| Tile map (32×30 cells, 8×8 tiles) | 960 bytes | Plus a shared 4 KB tile set in CHR |
| Saving | ~98% | Tile set is paid once; map data alone is ~1.5% |
Tile map structure
| Component | Purpose |
|---|---|
| Tile set | Pixel definitions (CHR-ROM on NES, charset RAM on C64, VRAM on Mega Drive) |
| Map data | One byte (or word) per cell, indexing the tile set |
| Attributes | Per-region palette/flip/priority data |
| Collision flags | Solid, 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:
| Element | Specification |
|---|---|
| Tile size | 8×8 pixels |
| Nametable | 32×30 tiles = 960 bytes |
| Pattern tables | 256 tiles each (two 4 KB tables in CHR memory) |
| Attribute table | 64 bytes after each nametable; 4×4 tiles per byte, 2×2 tile palette resolution |
| Hardware nametables | 4 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
| Advantage | Explanation |
|---|---|
| Grid-based | Simple coordinate lookup — tile = map[y >> 3][x >> 3] for 8×8 tiles |
| Tile properties | A parallel tile_attrs[] table maps tile index → collision class |
| Efficient | No per-pixel checking; one shift and one indirect read per query |
| Consistent | Predictable behaviour, easy to debug |
Level design workflow
| Step | Process |
|---|---|
| 1 | Create tile graphics |
| 2 | Build tile set |
| 3 | Design levels in editor |
| 4 | Export map data |
| 5 | Runtime: draw from map |
Common tile types
| Type | Collision |
|---|---|
| Empty | Pass through |
| Solid | Block all |
| Platform | Block from above only |
| Hazard | Damage on contact |
| Collectible | Trigger collection |
Scrolling with tiles
| Challenge | Solution |
|---|---|
| New tiles needed at edge | Update the nametable column/row off-screen each frame |
| Seam visibility | Update during VBlank or under the status bar split |
| Large levels | Stream 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
- Tile-Based Graphics — the rendering concept and platform support
- Character Graphics
- Hardware Scroll
- PPU
- VIC-II