How to Simulate 2D Capsule Shapes with Ammo.js
This article explains what a 2D capsule shape is and demonstrates how to simulate its physics in a 2D plane using the 3D physics engine Ammo.js. You will learn how to define a capsule’s geometry, map it to Ammo.js’s 3D collision shapes, and restrict rigid body movement to achieve realistic 2D physics behavior.
What is a 2D Capsule Shape?
A 2D capsule shape, often called a stadium shape, consists of a rectangle with semi-circular caps at two opposite ends. It is defined by two primary parameters: * Radius (\(r\)): The radius of the semi-circular caps at the ends. * Height (\(h\)): The height of the cylindrical/flat middle section.
In 2D game development, capsule shapes are highly popular for character colliders. Unlike boxes, their rounded bottoms prevent them from getting stuck on the corners of tiles or uneven terrain, allowing for smooth movement across platforms.
Simulating a 2D Capsule in 3D Ammo.js
Ammo.js is a direct port of the Bullet physics engine. Because Ammo.js is a 3D physics engine, it does not have native 2D collision shapes. However, you can perfectly simulate 2D capsule physics by using Ammo’s 3D capsule shape and constraining its physical movement to a single 2D plane.
Step 1: Create the Capsule Shape
To represent a 2D capsule, use the 3D btCapsuleShape
class. By default, Ammo’s standard capsule is aligned along the
Y-axis.
// Define the radius and the height of the middle cylinder
const radius = 0.5;
const height = 1.0; // The total height of the capsule will be height + (2 * radius)
// Create the shape
const capsuleShape = new Ammo.btCapsuleShape(radius, height);Step 2: Restrict Movement to a 2D Plane
To force the 3D rigid body to behave as if it exists in a 2D plane (for example, the X-Y plane), you must restrict its degrees of freedom. You do this by setting the linear and angular factors of the rigid body.
- Linear Factor: Determines which axes the body can move along. To lock movement to the X-Y plane, allow movement only along the X and Y axes and block the Z-axis.
- Angular Factor: Determines which axes the body can rotate around. For 2D physics on the X-Y plane, the body should only rotate around the Z-axis (pointing “out” of the screen).
// Create construction info and the rigid body
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(0, 5, 0)); // Starting position
const localInertia = new Ammo.btVector3(0, 0, 0);
const mass = 1.0;
capsuleShape.calculateLocalInertia(mass, localInertia);
const motionState = new Ammo.btDefaultMotionState(transform);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, capsuleShape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);
// Constrain linear movement to X and Y axes (1 = free, 0 = locked)
const linearFactor = new Ammo.btVector3(1, 1, 0);
body.setLinearFactor(linearFactor);
// Constrain rotation to the Z axis only
const angularFactor = new Ammo.btVector3(0, 0, 1);
body.setAngularFactor(angularFactor);
// Add the body to your physics world
physicsWorld.addRigidBody(body);Summary of the Results
By combining btCapsuleShape with linear and angular
factors, Ammo.js treats the 3D shape as a 2D object. The capsule will
slide, fall, and collide along the X and Y axes, and rotate only when
tipping over or rolling, providing a stable and efficient 2D physics
simulation.