Guide

Game tilemaps explained

Most 2D games — from platformers and roguelikes to farming sims and tactics maps — store their worlds as tilemaps: regular grids where each cell references a small sprite from a shared tileset. Tilemaps are cheap to author, easy to iterate in tools like Tiled or Godot’s TileMap layer, and efficient to render when batched correctly. This guide covers how tile coordinates map to world space, how layers separate ground from decoration from collision, autotiling rules that paint coherent terrain edges automatically, orthogonal vs isometric projection, hooking tilemaps into pathfinding grids and collision detection, and the production pitfalls that turn a fast prototype into a shipping bottleneck.

What a tilemap stores

At its core, a tilemap is a 2D array (or sparse dictionary) of integer tile IDs. Each ID points to metadata: which region of a sprite sheet to draw, whether the tile is solid, whether it triggers an event, and optional per-tile flags (flip horizontal, rotation, custom properties).

Separating visual tiles from logical data is the first design decision. Many teams keep one render layer for art and a parallel collision layer with simple 0/1 solidity — artists can repaint backgrounds without breaking physics. Others embed collision polygons per tile in the tileset definition; that scales better for non-rectangular shapes but costs more tooling time upfront.

Tile size and coordinate spaces

Common tile sizes are 16×16, 32×32, or 48×48 pixels. Pick one early and build character metrics around it — jump height, door width, and camera dead zones should align to multiples of the tile size so level designers can greybox on-grid without fighting half-pixel gaps.

You will work in three coordinate systems:

  • Tile coordinates — integer (col, row) into the map array.
  • World coordinates — pixel or unit position in the game scene.
  • Local chunk coordinates — when maps are split for streaming.

Conversion is straightforward for orthogonal maps: worldX = tileX × tileWidth. Isometric maps need a shear transform — covered below — and are a common source of off-by-one placement bugs when designers paint in one tool and play in another.

Tilesets, atlases, and draw order

A tileset (or tile atlas) packs many tile sprites into one texture. GPUs draw faster from fewer texture binds, so batching thousands of visible tiles into one draw call is the performance win that makes tilemaps viable on mobile browsers.

Layers stack bottom to top: ground, decoration, objects, overhead canopy. Each layer is its own grid (or shares IDs with different render offsets). Sorting within a layer for pseudo-3D games often uses Y-sort — entities and tall tiles draw in order of their foot Y coordinate so characters walk behind trees but in front of grass.

Animated tiles

Animated water, torches, and conveyor belts cycle through a sequence of tile IDs on a timer. Store animation as an array of frame indices plus milliseconds per frame in tile metadata. Sync animation phase globally (all water tiles on the same frame) for a cohesive look, or offset by tile position for organic variation. Cap simultaneous animated tiles in view — on low-end hardware, animate only tiles within a camera margin.

Autotiling: painting terrain that connects

Hand-placing every grass-to-dirt edge tile is tedious. Autotiling (also called rule tiles or terrain sets) inspects neighboring cells and picks the correct border/corner sprite automatically.

The classic approaches:

  • 47-tile blob set — bitmask of 8 neighbors selects among 47 unique edge combinations; works for organic terrain.
  • Wang tiles — four corner colors define transitions; fewer tiles but stricter art constraints.
  • Rule tiles (engine-native) — Unity Rule Tile, Godot Terrain Set — designers paint a terrain type; the engine resolves sprites.

Autotiling runs at edit time (bake final IDs into the map file) or runtime (recompute when tiles change — needed for destructible terrain). Runtime autotiling is convenient for digging mechanics but costs CPU; rebake neighbors in a small region when a tile breaks, not the whole map.

Procedural generators often output a logical terrain-type grid first, then run autotiling as a post-pass — the same pipeline described in procedural generation for games.

Collision layers and gameplay hooks

Tile collision falls on a spectrum:

  1. Full-tile solid — fast AABB checks; good for retro platformers.
  2. Per-tile collision shapes — polygons for slopes, half-blocks, rounded cave walls.
  3. Object layer — spawn points, triggers, and loot placed as named objects independent of visual tiles.

One-way platforms are a special case: collision only from above. Implement with a flag on the tile plus a check that the entity’s previous frame bottom was above the platform top. Ladders and zones use trigger volumes on a dedicated layer rather than overloading solidity bits.

For combat and interaction, export tile custom properties — damage per second on lava, friction on ice, footstep sound material ID. Gameplay code reads properties at the entity’s current tile coordinate each frame or on enter/exit events, not by scanning the whole map.

Orthogonal, isometric, and hex grids

Orthogonal tilemaps align to screen axes — Mario, Celeste, Stardew Valley. Simple math, easy collision, natural fit for side-scrollers and top-down RPGs.

Isometric tiles are drawn as diamonds to fake 3D depth — classic RTS and city builders. World-to-tile conversion uses rotated axes; depth sorting is harder because a single tall building spans multiple draw-order bands. Artists often author facades as separate stacked layers.

Hex grids appear in tactics games — six neighbors instead of four or eight, no diagonal distance ambiguity. Pathfinding uses cube or axial coordinates; rendering offset-rows or offset-columns layouts must match the coordinate library you use for range calculations.

Performance: culling, chunks, and parallax

Even though tilemaps are efficient, a 10,000×10,000 world array is not. Production maps use chunks (e.g. 32×32 or 64×64 tiles per chunk file). Load/unload chunks around the camera; keep a ring buffer of active chunks in memory. This mirrors chunk streaming in 3D terrain pipelines but with far lower per-chunk cost.

Frustum culling — only submit tiles inside the camera bounds plus one-tile margin. For static maps, precompute visible tile lists per chunk.

Parallax backgrounds are separate tile layers scrolling at fractions of camera speed. They do not need collision; mark them non-interactive and draw before the main playfield.

On the web, prefer one atlas texture under 2048×2048 when possible; split into multiple atlases by biome if needed. Watch overdraw on full-screen ground layers — a single ground fill plus detail decals often beats repainting every cell with a unique grass variant.

Tooling and engine integration

Tiled (mapeditor.org) is the de facto interchange format — .tmx / JSON exports importers exist for Unity, Godot, Phaser, and custom engines. Standardize on:

  • Tile size and layer naming conventions in a style guide.
  • Custom properties documented in a shared enum header (collision type, biome ID).
  • Git-friendly map files — avoid binary unless your pipeline requires it.

At import, validate: no orphan tile IDs, collision layer present, spawn point exists, map bounds within chunk grid. Fail CI on invalid maps rather than discovering a hole in production.

Hook tilemaps to navigation by rasterizing the collision layer into a walkability grid for A* — or mark individual tiles as unwalkable in the graph. Rebuild local nav patches when destructible tiles change; do not recompute the entire world graph for one exploded wall.

Multiplayer and dynamic maps

Server-authoritative games should treat the tilemap as data the server owns. Clients receive chunk diffs when tiles change (building placed, wall destroyed). Serialize tile ID + layer + coordinates; validate that the player is in range and has resources before applying edits.

Desync bugs often come from clients predicting tile changes locally while the server rejects them — show a ghost preview, commit visuals only on ack, or roll back with a brief correction animation.

Production checklist

  1. Lock tile size and character metrics before art finalization.
  2. Separate render layers from collision and trigger layers.
  3. Document tile custom properties; validate on import.
  4. Choose edit-time vs runtime autotiling based on destructibility needs.
  5. Chunk large worlds; cull tiles outside the camera frustum.
  6. Atlas textures; batch draws per layer.
  7. Rasterize or flag walkability for pathfinding; patch locally on changes.
  8. Test one-way platforms, slopes, and spawn points on real hardware.
  9. For multiplayer, server-validate tile edits and diff chunks to clients.
  10. Playtest vertical slice maps before scaling content volume.

Key takeaways

  • Tilemaps are data — grids of IDs referencing a shared tileset, not hand-placed sprites.
  • Layers separate concerns — ground, decor, collision, triggers.
  • Autotiling saves art time — bitmask or rule tiles for terrain edges.
  • Chunk and cull — large worlds need streaming, not one giant array.
  • Import validation — catch missing collision and orphan IDs in CI.

Related reading