← back to jackcoldrick.com
nightcity — project detail
Night City icon

Side projectNight City

An endless pixel-art street at night that you walk along while the city quietly gets on with being alive around you. Built as an experiment in how much life you can give a picture that is mostly standing still — and in getting two dozen separately generated images to look like one place.

The Night City title screen: the words NIGHT CITY over a pixel-art skyline at night, with a moon, lit windows and a neon MOTEL sign.
The title screen sits on the skyline; pressing start pans the camera down to the street.

What it is

You walk right, and the place carries on without you. Windows go dark in towers a mile away, a lamp stutters, a police car tears past, a bus pulls in at a shelter and waits, pigeons scatter off a rooftop, rain lands on the kerb and splashes. None of it is scripted — it is a set of small systems each deciding for itself when to do something.

The target was that roughly a tenth of the screen is changing at any one moment and the rest is perfectly still. That sounds unambitious, and it is the entire difference between a city at night and a screensaver.

Street level in Night City: a character walking past lit shopfronts and neon signs, pedestrians on the pavement, a police car on the road behind railings.
Street level. Pedestrians, traffic, neon, reflections on wet asphalt — and a police car going past, siren and all.

How it's built

Night City is vanilla JavaScript and one canvas. No framework, no build step, no dependencies and nothing to install — the page you load is the source that runs.

The world is painted onto a canvas just 320×180 pixels and then blown up four times with smoothing switched off. That second step is the whole trick: every pixel becomes a crisp block, and nothing can land on half a pixel. Draw straight onto a big canvas instead and everything shimmers the moment it moves.

The city is seven parallax layers, each a handful of tiles repeated forever in both directions. Walk far enough and you meet the same building again — but never the same lit building, because each tile asks a seeded random number generator "what am I?" using its own position as the seed. For any tile to be able to follow any other, the outer eight pixels of every tile are left empty. You cannot see the seams because there is nothing at them.

Nobody marked where the windows are. A tool reads each piece of artwork and finds the rectangles darker than the wall around them — those are windows. The same pass finds rooftop parapets to hang signs from, ledges for pigeons to land on, and shopfronts to spill light onto the pavement. The city's behaviour comes out of its own picture.

Features

  • A city that is alive without being scripted. Traffic, pedestrians, rain, neon, pigeons and lighting all run as separate systems, each deciding for itself when to act — so no two minutes on the same street play out the same way.
  • An endless street in both directions. Seven layers of parallax tiles, each asking a seeded generator what it is from its own position, so the city goes on forever and never repeats the same lit building.
  • True pixel discipline. Everything is painted at 320×180 and scaled up four times with smoothing off, so every pixel is a crisp block and nothing ever lands on a half pixel.
  • Artwork that drives its own behaviour. Windows, parapets, ledges and shopfronts are found by reading the images themselves, so adding a new building automatically gives it lights to switch off and ledges for birds to land on.
  • Weather and reflection. Rain lands and splashes on the kerb, and wet asphalt picks up the neon above it.
  • Layered audio. Streaming beds for music, rain and city ambience, with overlapping one-shots for footsteps, sirens and buses, so the same siren can pass twice without cutting itself off.
  • Built for a phone as well as a monitor. Touch controls with auto-run, and a taller portrait viewport that uses artwork already sitting above the landscape view.

The art pipeline

Every image started as a written prompt, and none of them went straight into the game. Image generators cannot actually produce pixel art — they produce a large picture that resembles it, with blocks roughly square and colours roughly right. "Roughly" is fatal at four times magnification: a block 3.8 pixels wide instead of 4 is a ragged edge.

So everything passes through a conforming tool written in Python. It snaps the art to the pixel grid, forces every colour onto a locked 23-colour palette, hardens the transparency and checks the gutter rule — then prints the numbers, so how well a generation conformed is something you can measure rather than a feeling. The prompt pack is half the project, and it ships with it.

The stack

Engine
Vanilla JavaScript and one canvas — no framework, no build step, no dependencies
Rendering
A 320×180 backbuffer scaled 4× with smoothing off, over seven parallax layers
World
Seeded from tile position, so the city is endless in both directions and identical each time you pass
Art
AI-generated from a written prompt pack, then conformed to the grid and palette by a Python tool
Audio
Streaming beds for music, rain and city ambience; overlapping one-shots for footsteps, sirens and buses
Mobile
Touch controls with auto-run, and a taller portrait viewport using art above the landscape view
Hosting
Vercel

A detail I like

Most of these systems run alongside each other without ever noticing each other; the traffic has no idea the pavement exists. The bus is the exception. It reads the very same data that decides where the shelters go, picks the next one ahead of it, eases to a stop, waits a few seconds, and pulls away. It is a small thing, and it is the moment the city stops being several effects layered on top of one another and starts being a place.