City Defense

About › Technology

What City Defense runs on: the technology

City Defense is a pure web game: the map, the 3D city, enemy pathfinding, the simulation and the bot test all run in the player's browser. The server only delivers static files. The game is built on MapLibre GL JS (map), three.js (3D), OpenFreeMap vector tiles made from OpenStreetMap data, TypeScript and Vite.

Updated

City Defense is free to play in your browser – no download, no sign-up. First mission: Brno, náměstí Svobody.

Play free

Technology at a glance

PartTechnologyWhat it does
MapMapLibre GL JS 6vector map, camera, tile loading, attribution
Map dataOpenStreetMap → OpenMapTiles schema → hosted by OpenFreeMap (Liberty style)streets, buildings with heights, land cover, water
3D graphicsthree.js (WebGL 2)buildings, ground, trees, rubble, characters, towers and effects
Particlesthree.quarkssmoke, explosions and dust from collapses
3D modelsglTF (.glb) with meshoptimizer compression, prepared with glTF Transformtheme characters and towers (CC0)
TexturesKTX2 / Basis Universalphoto textures for the realistic city style (CC0)
CodeTypeScript, Vite 8, no frameworkthe whole game as a single web app
Parallel workWeb Workersbuilding the 3D city and ground, bot testing of missions
Place searchPhoton (komoot)address search in the mission editor
TestsVitestover a thousand automated tests, regression runs on real map tiles
HostingCloudflare Workers (static assets)serving the game files from a CDN

The map: MapLibre and vector tiles

The map is drawn by MapLibre GL JS, an open-source library for vector maps in the browser. The base map is the Liberty style from OpenFreeMap, which serves vector tiles in the OpenMapTiles schema built from OpenStreetMap data. The most detailed tiles are at zoom level 14.

Nothing is downloaded in advance. The game reads streets, buildings, land cover and water from the tiles the map has already loaded for display (via querySourceFeatures). It hides shop and restaurant icons from the style so the map stays clean and the fight stays readable.

A game world built from map data

3D in the same canvas as the map

three.js draws into the same WebGL context as MapLibre, as custom map layers: the ground, the city with its trees, and the characters. Because they share one depth buffer, buildings correctly hide enemies – and an enemy behind a building shows up as a colored silhouette (an “X-ray”).

Web Workers: heavy lifting off the main thread

City geometry, ruins, rubble heaps and the ground surface mask (1 m cells, 1,400 × 1,400 in Brno) are built in a Web Worker, so the game doesn't stutter while loading. The mission bot test runs in workers too: on a computer with four or more cores, both bots play at the same time.

KTX2 textures

The realistic style uses five texture arrays in KTX2 format (Basis Universal): 11 plasters and walls, 3 high-rise facades, 7 roof coverings, 3 kinds of rubble and 11 ground surfaces – 3.24 MB in total. They are only downloaded if you choose the realistic style, and the graphics card receives them in a format it supports. The transcoder ships with the game; nothing is loaded from third-party CDNs.

Hosting: static files, computation on the player's side

The game is a static site on Cloudflare Workers at citydefense.app. The server computes nothing – the simulation, routing, 3D and bots all run in the player's browser. Only two outside services are called from the browser: OpenFreeMap for map tiles and, in the editor, Photon for place search. There are no accounts and no database of our own; missions are saved in the browser and shared by link.

Tests

The pure game logic is covered by more than a thousand automated tests in Vitest. Regression tests run on four real map tiles of Brno kept in the repository (street network, buildings, ground surfaces). A balance test plays the mission with computer bots and checks that the difficulty stays in the agreed range. Shaders are validated with glslang.

Frequently asked questions

Do I need a powerful computer?

A browser with WebGL 2 is enough. High quality is the default even on a phone; if the game stutters on a slower device, it lowers sharpness and shadows by itself and offers low quality between waves. Low quality can also be chosen on the start screen.

Why does a mission take a moment to load?

The game first waits for the map tiles, then builds the street network, buildings, height map and 3D city from them. The realistic style also downloads 3.24 MB of textures.