five-on-it / apps/client/src/ui/Minimap
apps/client/src/ui/Minimap
The minimap in the bottom-right corner: the city round the player, north-up, about 300 m across (the settings' Minimap zoom: 200, 300 or 500 m), following them on every frame the game draws (follow, the point the game loop publishes each frame; the markers come ten times a second). Under the markers lies the window of the whole city's static layer round the player (minimap-draw.ts: drawn once at about two pixels a metre, its districts tinted by their themes, the ground lighter the higher it stands, the roads, the footprints); over it the markers in CSS px: the player as a yellow arrow at the centre, other players in their colours (in a run of teams, their team's, bigger and ringed: team-colors.ts), pedestrians as faint dots, enemies in orange and chasers in the colour of what they are doing once the server reads them out, the police flashing blue and red, the phone's waypoint as a cyan diamond and, off the map, an arrow at its edge pointing the way to it (a race's next gate too); the mission's targets as gold rings (every one of a parallel group's) and the route line to the nearest over the roads, the other members of the player's party as green rings, the phone's camera frame while its page is out; the guards' view cones (coloured by their alert phase) and the security cameras' cones always, the other NPCs' while the toggle is on. Over everything the labels, at 12 CSS px whatever the map's size (map-labels.ts): the districts' titles, then the streets' names, decluttered. The canvas's backing store follows its size on screen times the screen's pixel ratio (a ResizeObserver), so nothing is stretched. A click opens the full map (FullMap.tsx) and is never a shot. The canvas says what it drew in its data attributes (data-span, data-backing, data-label-px, data-labels, data-streets, data-centre), which the end-to-end tests read.