Dev log · BuildCity Dev Log

Designing a new map: what it takes to ship White Sands Coast and the Grand Canyon

Logical tile grids, 3D terrain masks, resource placement, and the background-horizon rule we now apply to every map.

Articles are currently available in English.

Two maps in two weeks, and a process that came out of them

For most of its life BuildCity had one map: a 70 by 70 grid with a coastline and a mountain, the same for every mayor. In October 2026 we shipped two more in quick succession. White Sands Coast is a 112 by 112 map of white beaches, shallow blue water, and small islands that hide oil reserves. The Grand Canyon map followed on October 14 with dry plateaus, a river gorge cutting through the playable area, and steel arch bridges that let roads cross it. Both are unlocked once per account with gems, White Sands Coast at 300 and the canyon at 500, and both are now listed in the map shop with a preview.

Making the first new map taught us that "add a map" is two very different jobs depending on what the map needs, and the second one turned those lessons into a written workflow. This entry is a tour of that workflow: what a map actually consists of, where the traps are, and the rule about horizons that we now apply to everything.

Two kinds of map

The simplest kind is a tile map built with the in-game map editor. It reuses the existing terrain renderer, becomes a template in the database, and appears in the city creation list. It cannot change the grid size or the terrain rules, and it does not automatically appear in the shop; that is a separate registration step. The second kind has its own 3D terrain model, possibly a new grid size, and sometimes new terrain rules. There is no generic pipeline where you drop in a JSON file and a model and the game picks it up; each of these maps extends the terrain adapter, the editor's size and terrain allow-lists, and the server's validation together.

White Sands Coast and the canyon are both the second kind. The 112 by 112 grid alone meant teaching the editor, the renderer, and the save validation about a size that was not 70, and the canyon added a terrain where large parts of the interior are unbuildable gorge rather than unbuildable sea.

Decide the identity first, because it never changes

Before any terrain work, a new map gets a specification table that fixes everything other systems will depend on: the internal name that cities store as their template, the shop slug used in URLs and in the server's purchase allow-list, the display name and translation keys, grid size and terrain id, price, resource deposits, vehicle and ship entry points, pre-built bridges, images, and how existing cities will be protected if the template is edited later. The reason for the ceremony is that a released map is never renamed or deleted and recreated. Cities reference it by name, purchases reference it by id, and the first new map left us with a couple of legacy identifiers that exist only for compatibility. The workflow now says plainly: do not reuse those, and do not copy an old price or version number into a new map as a default.

The logical grid

A map's gameplay is a grid of integer tile codes stored column-major, with sea, beach, waterway, and rail tiles distinguished by code. Resource deposits are not painted onto that grid; they are a separate list of coordinates per resource type, stored as strings in the form x,y. That detail turned out to matter: mining and the deposit gauges read those coordinates, so an older marker format that only recorded minerals produces a mine that reports zero reserves. Coordinates with spaces, leading zeros, duplicates, or positions outside the grid are rejected rather than silently accepted.

Around the playable area the editor keeps a six-tile margin, so a 70 map is stored as an 82 by 82 extended array and a 112 map as 124 by 124. New sizes have to validate that offset and the crop back to the playable area. The editor's full export, including entry points and the logical data for ocean bridges, is the starting point for the template; hand-assembling a subset is how bridges end up visible but not functional after a reload.

Resources are placed with a road in mind, not just a number. An oil field on an island is only interesting if a bridge or a port can reach it, and the island, the terrain image, the deposit list, and the shop description all have to agree that it is there.

The 3D terrain and the mask problem

The visual terrain is a GLB model aligned to the grid origin and tile size. From it we derive masks: which tiles are buildable, which are mountain or gorge, which are coast. The first version of the White Sands masks tested only the center point of each tile against the terrain, and the result was houses whose corners were buried in a sand dune while their centers sat on flat ground. The rule now is to intersect the entire tile rectangle with the terrain surface, then to place real building footprints, port water frontage, and road connections on the candidate map before approving it.

Every GLB also goes through a checklist: valid normals and UVs, no degenerate faces, no stray cameras or lights, a recorded triangle and material count, and a check of the water mesh naming because the water material and sea level are swapped in by name. One more lesson that sounds obvious in hindsight: painting tiles in the editor does not move the 3D mesh. Changing a tile from beach to sea changes gameplay, not the picture, and both have to be edited for the map to be honest.

The horizon rule

The canyon map produced the rule we now apply to every map: the playable grid is not the edge of the world. A player who tilts the camera or zooms out sees whatever is beyond the buildable area, and a map whose terrain stops in a clean square at the grid boundary looks like a diorama on a table. The workflow breaks the problem into three distances.

  1. Near: cliffs, rivers, and roads must continue across the grid boundary at the same height and material, with no open mesh edges visible.
  2. Middle: rotating or panning the camera should always show terrain that plausibly continues the map. A gorge does not end abruptly at the boundary; it carries on into the background or disappears behind terrain.
  3. Far: distant ridges meet the sky in every direction, with no gaps at the screen corners at maximum zoom-out or from a low viewpoint.

Two constraints keep this from becoming expensive. The background is purely visual: it never changes the buildable area, resource positions, entry points, or saved data, and it must not intercept building placement or pathfinding. And it has a budget set before modeling begins, with the triangle count and draw calls of the existing map and the finished map recorded side by side. A wide horizon is not an excuse to grow the simulation.

The last item in the checklist is a human one. A new map is reviewed in the actual editor and the actual game, not just a model viewer, from the default view, all four rotations, the edges, nearest and furthest zoom, and both desktop and mobile aspect ratios, and it waits for explicit approval before release.

From template to shop

Release is its own sequence. The template is registered, the shop entry and price are added separately, the preview image and loading screen are produced, patch notes are written in every supported language, and existing cities on older templates are verified to still load with their stored terrain. Because the shop price lives in the database and the game code lives in the deployed jar, a map can be fully implemented and still not be purchasable, which is why "the files exist" is never treated as "the map shipped."

If you want to see the result rather than read about it, the map shop shows White Sands Coast and the Grand Canyon with previews, and the patch notes record what changed in each release along the way.