I've always been fascinated by traffic simulations. There's something deeply satisfying about watching little cars navigate a grid of streets, stopping at intersections, waiting their turn, and flowing through a city like blood through veins. Maybe it's the emergent complexity—simple rules creating surprisingly realistic behavior—or maybe I just like watching tiny cars drive around. Either way, I've wanted to build one for years.

The problem? Building a traffic simulator from scratch is a lot of work. You need to handle road networks, vehicle physics, intersection logic, collision detection, rendering... the list goes on. It's the kind of project that sits in your "someday" folder indefinitely.

Enter AI-assisted development. What used to be a weekend-long project (at minimum) became an iterative conversation. I described what I wanted, refined it step by step, and ended up with a fully functional city traffic simulation—complete with buildings, stoplights, and cars that actually follow traffic laws.

Here's how it works under the hood.

The Road Network

The simulation uses a simple grid-based street system. Roads are laid out at regular intervals (every 120 pixels), creating a Manhattan-style grid that covers the entire screen. Each road is 32 pixels wide, divided into two lanes—one for each direction of travel.

The key insight here is separating the concept of "road position" from "lane position." Each car tracks which road it's on (roadX, roadY) and then applies a lane offset based on its direction of travel:

  • Cars going right drive in the bottom lane
  • Cars going left drive in the top lane
  • Cars going down drive in the left lane
  • Cars going up drive in the right lane

This right-hand traffic system means cars naturally pass each other when traveling in opposite directions. No complex collision avoidance needed—just geometry.

Two Types of Intersections

The simulation features two types of intersections: 4-way stop signs and traffic lights.

Stop Sign Logic

At stop sign intersections, cars follow proper 4-way stop etiquette:

  1. When a car approaches an intersection, it registers its arrival and joins a queue
  2. Each car receives an arrival timestamp and a random tiebreaker value
  3. Cars must come to a complete stop before proceeding
  4. The car that arrived first gets to go first
  5. If two cars arrive simultaneously, the random tiebreaker decides who goes

This creates realistic stop-and-go behavior. You'll see cars politely taking turns, with occasional brief pauses as they "check" that the intersection is clear.

Traffic Light Logic

Seven intersections are randomly selected to become traffic lights instead of stop signs. These cycle through phases:

  • Green phase (3 seconds): North-south traffic flows freely
  • Yellow phase (0.75 seconds): Warning to stop
  • Red phase: Traffic stops while the perpendicular direction gets green

The lights are staggered—they don't all change at the same time—which creates more natural traffic flow and prevents citywide synchronized gridlock.

Cars approaching a green light don't need to stop at all (unless there's a car ahead of them). Red means stop. Yellow means stop if you're not already in the intersection.

Car Behavior

Each car is a simple state machine with the following states:

  • Driving: Moving forward at cruising speed
  • Approaching: Getting close to an intersection
  • Stopping: Coming to a complete stop
  • Waiting: Stopped and waiting for right-of-way
  • Crossing: Actively moving through an intersection

Cars also have individual personality—each one gets a slightly randomized speed (80% to 120% of base speed), so faster cars will eventually catch up to slower ones.

Following Distance

Cars maintain safe following distance using a simple check: if there's another car ahead in the same lane within about 25 pixels, stop. This prevents rear-end collisions and creates natural traffic bunching behavior.

Turning

When cars clear an intersection, they have a 30% chance of turning onto the perpendicular road. When turning, they snap to the correct lane for their new direction. This keeps traffic circulating throughout the city rather than just driving in straight lines forever.

Edge Wrapping

Cars that drive off one edge of the screen wrap around to the opposite side, creating an infinite city illusion. When wrapping, they clear any intersection state to prevent ghost cars from blocking intersections they've left behind.

The Cityscape

What's a city without buildings? The simulation procedurally generates buildings to fill each city block. Each block gets one of four layout types:

  1. Single large building: One structure fills most of the block
  2. 2x2 grid: Four smaller buildings arranged in a grid
  3. Row of buildings: 2-3 buildings side by side
  4. L-shaped arrangement: A large building with smaller ones tucked beside it

Buildings have randomized features:

  • Colors: Browns, grays, tans, greens, reds, and blues
  • Roof colors: Dark browns, blues, grays, and reds
  • Roof details: Some buildings have AC units on top
  • Windows: Three different styles (square, wide, or tall)
  • Doors: Larger buildings get entrance doors

Living Windows

The windows have three states: dark (unlit), blue (reflective/daytime), and yellow (lit from inside). These states are pre-generated when buildings are created, but they slowly change over time—roughly one window per building might change every 25 seconds or so. This creates a subtle "lived-in" effect without the disco-ball flickering of purely random rendering.

Avoiding Gridlock

Traffic simulations are prone to deadlocks. A car waiting for an intersection that's waiting for another car that's waiting for the first car... classic gridlock.

The simulation handles this with a few safety valves:

  1. Timeout recovery: If a car waits more than 300 frames (~5 seconds), it forces the intersection clear and proceeds
  2. Periodic cleanup: Every second, the simulation scrubs intersection queues to remove any stale references
  3. Crossing car exception: Cars won't get stuck behind another car that's actively crossing an intersection

These aren't perfect solutions, but they prevent the simulation from ever getting permanently stuck.

The Power of Iterative Development

What struck me most about building this wasn't the technical details—it was the process. I started with "make a traffic simulator with cars as squares on a grid." Then I refined:

  • "Cars should stay in their lane and pass each other"
  • "Make stop signs work properly—first to arrive goes first"
  • "Add some traffic lights"
  • "Add buildings to make it look like a city"
  • "The window lights are changing too fast"

Each iteration built on the last. Problems were identified and fixed in real-time. Features were added incrementally. The AI handled the boilerplate while I focused on what I actually wanted the simulation to do.

This is the promise of AI-assisted development: not replacing programmers, but amplifying them. I have the domain knowledge (how traffic should flow, what makes a city feel alive) and the AI has the patience to write the rendering code, track down edge cases, and refactor when requirements change.

Try It Yourself

The full simulation runs in a single HTML file—no dependencies, no build step. Click anywhere on a road to add a car. Use the control panel to add multiple cars or clear the simulation. Resize your browser window to regenerate the city layout.

Watch the cars negotiate intersections. Notice how traffic backs up at red lights, then flows freely when the light changes. See if you can spot the moment when a waiting car's brake lights go dark as it starts to move.

It's not a perfect simulation of real traffic—there's no route planning, no pedestrians, no accidents, no road rage. But it captures something essential about the flow of vehicles through a city grid. And it took an afternoon to build instead of a month.

That's the future of creative programming: more time thinking about what you want to build, less time fighting with the how.


The traffic simulator is built with vanilla JavaScript and HTML5 Canvas. No frameworks were harmed in the making of this simulation.