2D Vehicles
2D Vehicles: A Project Retrospective (1996–2026)
During a single weekend in late August 1996, I developed a 2D physics simulation. This experiment eventually served as the foundation for the vehicle mechanics in the globally recognized title Grand Theft Auto (GTA).
The project originated as a simple wireframe demonstration coded in GFA BASIC on an Atari ST. For the commercial release of the game, this logic was ported to C. To celebrate the 30th anniversary of this system, I have created a remastered version using JavaScript, allowing anyone to experience the original logic in a polished format.
🎮 User Guide
The simulation is playable via the browser, featuring touch-screen support for mobile users.
Mode Selection
You can toggle between three distinct vehicle types using the Settings menu or the following keyboard shortcuts:
- Car: The standard vehicle mode.
- Ship: A technically simpler model.
- Brick: The most basic physics object.
Control Mapping
| Key | Action | Description |
|---|---|---|
B | Barriers | Toggles the collision walls around the play area. |
G | Gravity | Toggles vertical gravity (best experienced in Ship or Brick modes). |
Z | Dead Zone | Toggles the camera's "dead zone" (the distance a vehicle moves before the camera follows). |
X | Dynamic Zoom | Toggles speed-based zooming, where the camera pulls back as velocity increases. |
VOLUNTARY DISCLAIMER: This recreation is a wholly independent work. It is not affiliated with, endorsed by, or connected to the "Grand Theft Auto" franchise, its publisher "Take-Two", or the developer "Rockstar Games".
🛠️ Technical Evolution
The prototype was built by combining a general 2D rigid body with a simplified car model. The development progressed in stages:
Brick Ship (inspired by the 1986 classic Thrust) Car.
The Physics Core
At its heart, the system utilizes a classical 2D rigid body dynamics simulation. At the time, this was an uncommon approach in game development; most titles relied on basic high-school "point physics": These older methods often used "wonky hacks" to simulate rotation. By implementing proper rigid-body physics—specifically including torques—rotation is handled with far more coherence.
The Vehicle Layer
On top of the core physics, I implemented a "novel" simulation layer to mimic tyre behavior. While I recognized that my model was technically incorrect and physically approximate, it was good enough to create the desired feel.
⚙️ System Architecture
The JavaScript recreation separates concerns to ensure clarity between input, logic, and visuals.
One Body, Three Behaviors
A vehicle is composed of three elements: a Rigid Body, a Shell (defining shape and collision), and a Dynamics Object (defining behavior).
- The Brick: Responds to forces generated by pointer dragging.
- The Ship: Applies thrust from a specific attachment point.
- The Car: Implements engine force and steering, with resistance calculated at four distinct tyre points.
When the user switches modes, the system swaps the shell and behavior while maintaining the current position and momentum of the body.
📐 Mechanics of Motion
The rigid body tracks four primary variables:
- Position & Velocity
- Angle & Angular Velocity
A force applied directly through the center of mass alters linear motion, whereas a force applied offset from the center generates torque, causing the body to spin.
Collision Handling
The simulation uses a simple barrier solver rather than a complex general collision system.
- If a shape crosses a boundary, it is pushed back inside.
- A contact impulse is applied based on the entry velocity.
- Because edges are frictionless, an off-center hit will change both the vehicle's trajectory and its spin.
// Conceptual Physics Update Loop
function update(dt) {
let totalForce = dynamics.calculateForces();
let totalTorque = dynamics.calculateTorque();
velocity += (totalForce / mass) * dt;
angularVelocity += (totalTorque / inertia) * dt;
position += velocity * dt;
angle += angularVelocity * dt;
}
🏎️ The Approximate Tyre Model
The "Car" mode calculates the velocity at each tyre's position and splits it into two vectors:
- Longitudinal: Along the wheel's heading.
- Lateral: Sideways across the wheel.
The simulation then applies resistance:
- Rolling: Low resistance.
- Sideways: High resistance (simulating grip).
Special Behaviors:
- Steering: Rotates the front wheels' headings, redirecting the resulting forces to turn the car.
- Handbrake: Increases rear rolling resistance while simultaneously reducing rear lateral grip.
These forces are proportional to velocity without a maximum cap. This is effectively a damping model rather than a realistic simulation of friction or slip, but it successfully mimics the feeling of tyres resisting sideways slides.
🏁 Final Integration
The Vehicle Coordinator manages the lifecycle of the simulation:
- Request forces from the active dynamics object.
- Advance the rigid body state.
- Transform shell local points into world coordinates for the renderer.
- Resolve barrier contacts.
To prevent "artificial spin" (which occurs when a single corner hits a wall), the system identifies the flat face touching the barrier and calculates the impulse based on the midpoint of the contacting points.