How to Change Shape Size Dynamically in planck.js?
In planck.js (the 2-D physics engine for JavaScript games), shapes attached to rigid bodies are generally considered immutable once created. However, you can dynamically change the size or radius of a shape after it has been added to the simulation by directly modifying the shape’s internal properties and manually updating the body’s mass properties to reflect the change. This article will guide you through the process of altering a shape’s dimensions—specifically circles and polygons—without needing to completely destroy and recreate the fixture.
Understanding Fixtures and Shapes
When you create a body in planck.js, you attach a Fixture to it, which pairs a geometric Shape with physical properties like density and friction. Because the physics engine pre-calculates structural data for performance, simply changing a number on a shape won’t immediately alert the engine that the physics world has changed.
Modifying a Circle Radius
For a circular shape, the radius is stored directly in the shape object. You can access the fixture from the body, mutate the radius, and then force the engine to recalculate.
// Assuming you already have a body and a fixture
const fixture = body.getFixtureList();
const shape = fixture.getShape();
// 1. Update the radius directly
shape.m_radius = 2.5;
// 2. Reset the mass properties of the body
body.resetMassData();Modifying Polygon Dimensions (Boxes)
Polygons are slightly more complex because they rely on an array of vertices. To change the size of a box or a custom polygon, you must re-initialize the vertices using the shape’s setter methods.
const fixture = body.getFixtureList();
const shape = fixture.getShape();
// 1. Redefine the box vertices with new width and height
// planck.Box takes (hx, hy) which are half-width and half-height
shape.setAsBox(3.0, 1.5);
// 2. Reset the mass properties of the body
body.resetMassData();Crucial Step: Broad-Phase Re-synchronization
Modifying the shape and resetting the mass data updates the physics math, but the collision detection system (broad-phase) might still use the old bounding box (AABB) until the body moves. If your object is static or sleeping, nearby objects won’t realize the shape has expanded.
To fix this, you can force the contact manager to update by temporarily flagging the fixture, or more simply, by slightly nudging or waking up the body:
// Wake up the body to force the physics engine to re-evaluate collisions
body.setAwake(true);For absolute precision in dense simulations, destroying the old
fixture and creating a new one using
body.destroyFixture(fixture) and
body.createFixture(newShape) remains the safest
API-supported method, but the direct mutation steps above offer a
high-performance alternative when handled carefully.