@web-engine-dev/physics2d
2D physics engine with collision detection, rigid body dynamics, and constraints for web-engine-dev.
Features
- Rigid Body Dynamics: Forces, impulses, torque
- Collision Detection: AABB, circles, polygons
- Collision Response: Sequential impulse (basic restitution + friction)
- Constraints: Joint API (reference implementation)
- Continuous Detection: Bullet CCD for fast bodies (swept shapes)
- Raycasting: 2D ray queries
Production backend: For best-in-class performance, CCD, and full solver features, use the Rapier adapter via
@web-engine-dev/physics2d-rapier.
Installation
bash
npm install @web-engine-dev/physics2d
# or
pnpm add @web-engine-dev/physics2dQuick Start
typescript
import { PhysicsWorld2D, RigidBody2D, BoxShape, CircleShape } from '@web-engine-dev/physics2d';
// Create physics world
const world = new PhysicsWorld2D({
gravity: { x: 0, y: -9.81 },
});
// Add ground
const ground = world.createBody({
type: 'static',
position: { x: 0, y: -5 },
shape: new BoxShape(10, 0.5),
});
// Add dynamic body
const ball = world.createBody({
type: 'dynamic',
position: { x: 0, y: 5 },
shape: new CircleShape(0.5),
restitution: 0.8,
});
// Step simulation
world.step(1 / 60);API Overview
Body Types
typescript
// Static - never moves
world.createBody({ type: 'static', ... });
// Kinematic - moved by code, not physics
world.createBody({ type: 'kinematic', ... });
// Dynamic - fully simulated
world.createBody({ type: 'dynamic', ... });Shapes
typescript
// Box
new BoxShape(width, height);
// Circle
new CircleShape(radius);
// Polygon
new PolygonShape([
{ x: 0, y: 1 },
{ x: 1, y: -1 },
{ x: -1, y: -1 },
]);
// Edge (one-sided)
new EdgeShape({ x: -5, y: 0 }, { x: 5, y: 0 });Forces and Impulses
typescript
// Apply force (continuous)
body.applyForce({ x: 100, y: 0 });
// Apply impulse (instant)
body.applyImpulse({ x: 10, y: 0 });
// Apply torque
body.applyTorque(5);
// Set velocity directly
body.setLinearVelocity({ x: 5, y: 0 });
body.setAngularVelocity(2);Constraints
typescript
// Distance joint
world.createJoint({
type: 'distance',
bodyA: ball1,
bodyB: ball2,
length: 2,
});
// Revolute (hinge) joint
world.createJoint({
type: 'revolute',
bodyA: wheel,
bodyB: chassis,
anchor: { x: 0, y: 0 },
});
// Prismatic (slider) joint
world.createJoint({
type: 'prismatic',
bodyA: platform,
bodyB: rail,
axis: { x: 1, y: 0 },
});Collision Events
typescript
world.on('collision-start', (a, b, contact) => {
console.log('Collision started');
});
world.on('collision-end', (a, b) => {
console.log('Collision ended');
});Peer Dependencies
@web-engine-dev/math- Vector math