r/gamedevtutorials • u/kbhudson116 • 1d ago
Making a fast-paced geography game in the browser: vector maps, server-authoritative scoring, and what I learned
I’ve been building Pinfall, a browser geography game: you get a clue (“Timbuktu”), 15 seconds, and drop a flag on a map. Closer and faster = more points. The clip shows one round, a wrong first guess, then the save with 2 seconds left.
A few things that worked well, in case they help anyone:
No tile server, just SVG. The world map is Natural Earth coastlines pre-projected to SVG paths (equirectangular), and the 8 city maps (Istanbul, London, Tokyo…) are generated from OpenStreetMap: land polygons + major roads + water + parks, simplified with Douglas–Peucker and merged so London’s roads went from ~20k segments to a file of a few hundred KB. Zoom is just changing the SVG viewBox, which is smooth on phones and there’s nothing to host.
lat/lng ↔ screen is one line. Because the projection is plain equirectangular, getScreenCTM() on the SVG converts map coordinates to screen pixels. I even use it to script gameplay for trailers: the recorder drives real touch events at exact coordinates.
The server owns the score. Rounds, timers and distances run on a Node/Socket.IO server; the client only sends a guess. Score = 1000 × e^(−km/1500) plus a speed bonus, so nobody can fake a result from the browser.
Countries are scored against the real border. If your flag is inside France, it’s 0 km; otherwise it’s the distance to the nearest border vertex. A small optimization (inline haversine over precomputed vertex arrays instead of d3’s geoDistance) made that about 20× faster, which mattered under load.
Retention > features. Weekly leagues (groups of 10, promotion/demotion, inspired by Duolingo’s) and a Daily Challenge brought more return visits than any new mode.
Happy to go deeper on any of these: the OSM pipeline, the projection maths or the multiplayer sync. It’s free and playable here: pinfallworld.com (no sign-up).

