v0.5.0

Syncromesh integrates Box2D for 2D rigid-body physics. Physics bodies are created at spawn time via Simulation.spawn() or by adding fixtures post-spawn with Entity.createFixture(). Constraints (joints) are created with Simulation.createConstraint(). The simulation steps the physics world automatically each frame.

Body types #

ValueBehaviour
staticDoes not move. Collides with dynamic bodies. Default.
dynamicFully simulated: forces, velocity, gravity, collisions.
kinematicMoves via velocity only; not affected by forces or other bodies.

Set body.bullet: true in Simulation.spawn() to enable Box2D bullet mode for fast dynamic bodies. Bullet mode improves continuous collision detection against other moving bodies, but costs more CPU and should be used sparingly. Scripts can toggle it later with Entity.setBodyBullet(id, enabled).

Fixture shapes #

Fixtures define the collision geometry attached to a body. Each fixture has a type and shape-specific properties, plus optional density, friction, restitution, isSensor, and Box2D collision filtering.

Common Fixture Options #

FixtureOptions
Properties accepted by every fixture shape.
  • density number optional — Defaults to 1.0.
  • friction number optional — Defaults to 0.3.
  • restitution number optional — Bounciness from 0 (no bounce) to 1 (fully elastic). Defaults to 0.0.
  • isSensor boolean optional — If true, the fixture reports overlap contacts but does not create a physical collision response.
  • filter FixtureFilter optional — Box2D collision filter. The same fields can also be supplied directly on the fixture for convenience.
  • collision FixtureFilter optional — Alias for filter.
  • categoryBits number|string optional — 64-bit collision category bitfield. Use a decimal or 0x string outside JavaScript's safe integer range. Defaults to 0x0001.
  • maskBits number|string optional — 64-bit collision mask bitfield. Use a decimal or 0x string outside JavaScript's safe integer range. Defaults to all bits set.
  • groupIndex number optional — Signed collision group. Matching positive groups always collide; matching negative groups never collide.
FixtureFilter
Box2D fixture collision filtering.
  • categoryBits number|string optional — 64-bit collision category bitfield. Strings preserve all 64 bits.
  • maskBits number|string optional — 64-bit collision mask bitfield. Strings preserve all 64 bits.
  • groupIndex number optional — Signed collision group override.

Box #

BoxFixture
Axis-aligned rectangle.
  • type string "box"
  • size Point optional — Full extents { x, y }. Mutually exclusive with aabb.
  • aabb AABB optional — Positioned rectangle with centre and half-extents. Mutually exclusive with size.
  • density number optional — Defaults to 1.0.
  • friction number optional — Defaults to 0.3.
  • restitution number optional — Bounciness from 0 (no bounce) to 1 (fully elastic). Defaults to 0.0.

Circle #

CircleFixture
Circle shape.
  • type string "circle"
  • radius number optional — Circle radius. Defaults to 1.0.
  • position Point optional — Local offset from the body origin.
  • density number optional — Defaults to 1.0.
  • friction number optional — Defaults to 0.3.
  • restitution number optional — Bounciness from 0 (no bounce) to 1 (fully elastic). Defaults to 0.0.

Polygon #

PolygonFixture
Convex polygon (up to 8 vertices).
  • type string "polygon"
  • vertices Point[] — Array of 3-8 vertices defining a convex hull.
  • density number optional — Defaults to 1.0.
  • friction number optional — Defaults to 0.3.
  • restitution number optional — Bounciness from 0 (no bounce) to 1 (fully elastic). Defaults to 0.0.

Edge #

EdgeFixture
A line segment between two points.
  • type string "edge"
  • start Point — Start vertex.
  • end Point — End vertex.
  • density number optional — Defaults to 1.0.
  • friction number optional — Defaults to 0.3.
  • restitution number optional — Bounciness from 0 (no bounce) to 1 (fully elastic). Defaults to 0.0.

Chain #

ChainFixture
A chain of connected line segments (up to 8 vertices).
  • type string "chain"
  • vertices Point[] — Array of 2+ vertices forming a chain.
  • density number optional — Defaults to 1.0.
  • friction number optional — Defaults to 0.3.
  • restitution number optional — Bounciness from 0 (no bounce) to 1 (fully elastic). Defaults to 0.0.

Constraints (joints) #

Create constraints between two entity bodies with Simulation.createConstraint(options). Every constraint requires entityA, entityB, and a type.

TypePurposeKey options
distanceKeeps two anchor points separated by a target distance (spring/rope-like).anchorA, anchorB, length, minLength, maxLength, stiffness, damping
weldRigidly attaches two bodies around a shared anchor.anchor, referenceAngle, stiffness, damping
prismaticConstrain relative motion to a single axis (slider).anchor, axis, enableLimit, lowerTranslation, upperTranslation, enableMotor, motorSpeed, maxMotorForce
revoluteHinge constraint around a shared anchor.anchor, enableLimit, lowerAngle, upperAngle, enableMotor, motorSpeed, maxMotorTorque

Collision detection #

Use Entity.getContacts(id) to retrieve the IDs of entities currently in contact. Use Simulation.query(aabb) for broad-phase spatial queries.

Examples #

import * as Simulation from 'Syncromesh/Simulation';
import * as Entity from 'Syncromesh/Entity';

// Spawn two dynamic bodies
const ballA = await Simulation.spawn({
    position: { x: -4, y: 0 },
    body: {
        type: 'dynamic',
        fixture: [{ type: 'circle', radius: 0.5, density: 1.0, friction: 0.0, restitution: 1.0 }]
    }
});

const ballB = await Simulation.spawn({
    position: { x: 0, y: 0 },
    body: {
        type: 'dynamic',
        fixture: [{ type: 'circle', radius: 0.5, density: 1.0, friction: 0.0, restitution: 1.0 }]
    }
});

// Connect them with a distance constraint
const tether = await Simulation.createConstraint({
    type: 'distance',
    entityA: ballA,
    entityB: ballB,
    length: 4.0,
    stiffness: 3.0,
    damping: 0.6
});

// Set initial velocity (physics-driven movement)
await Entity.setLinearVelocity(ballA, { x: 6, y: 0 });

// Check contacts and constraints
const contacts = await Entity.getContacts(ballA);
const constraints = await Simulation.getEntityConstraints(ballA);

// Cleanup
await Simulation.destroyConstraint(tether);