planck.js
repository·master·Indexed 26 days ago
https://github.com/piqnt/planck.jsA high-performance 2D JavaScript/TypeScript physics engine for cross-platform HTML5 game development. As a port of the Box2D engine, it provides an idiomatic API for managing bodies, fixtures, and joints using MKS (Meters-Kilogram-Second) units. Version 1.5.0 includes features for continuous collision detection (CCD), body sleep parameters, and flexible user data attachment for linking physics objects to game logic.
What's inside planck.js
- Planck.js is a JavaScript/TypeScript rewrite of the Box2D physics engine designed for cross-platform HTML5 game development. It aims to provide an idiomatic JavaScript/TypeScript API while optimizing for web and mobile platforms.
Understand Broad-phase vs Narrow-phase collision
masterCollision processing in Planck.js is split into two stages:
- Broad-phase: Uses a
BroadPhaseclass (internally powered by aDynamicTree) to quickly identify potential colliding pairs, reducing the complexity from $O(N^2)$ to a much lower load. - Narrow-phase: Performs the actual computation of contact points between the pairs identified by the broad-phase.
Users typically interact with the
Worldclass rather than managing theBroadPhasedirectly.- Broad-phase: Uses a
Understand Contact terminology
masterContacts manage collisions between two fixtures. Key concepts include:
- Contact Point: A point where two shapes touch.
- Contact Normal: A unit vector pointing from
fixtureAtofixtureB. - Contact Separation: The distance between shapes. Negative values indicate overlap (penetration).
- Contact Manifold: A group of contact points sharing the same normal, approximating a continuous contact region.
- Normal Impulse: The impulse applied to prevent penetration.
- Tangent Impulse: The impulse generated to simulate friction.
- Contact Ids: Used to match contact points across time steps for performance.
Understand Planck.js Shape properties and behavior
masterShapes in Planck.js define collision geometry and are independent of the physics simulation. They are considered immutable.
Key behaviors to note:
- Coordinate Systems: When a shape is not attached to a body, its vertices are in world-space. When attached to a body via a fixture, its vertices are in local coordinates.
- Base Class Capabilities: All shapes implement the
Shapebase class, which provides methods for point testing, ray casting, AABB computation, and mass property computation. - Properties: Every shape has a
typemember and aradius(the radius also applies to polygons).
Understand Planck.js Core Concepts
masterPlanck.js is a 2D physics engine built around several fundamental objects that interact to simulate physical motion:
- World: The container for the entire simulation. It manages all bodies, fixtures, and constraints, and is responsible for running the simulation loop.
- Shape: A 2D geometric primitive (e.g., circle or polygon) that defines the geometry of an object.
- Rigid Body: A physical object with constant mass and volume that responds to forces. In Planck.js, 'body' and 'rigid body' are used interchangeably.
- Fixture: The bridge between geometry and physics. A fixture binds a Shape to a Rigid Body and defines physical properties like density, friction, and restitution. Fixtures are what enable objects to participate in the collision system.
- Constraint: A mechanism that removes degrees of freedom from bodies (e.g., pinning a body to a point to allow only rotation).
- Contact Constraint: Automatically generated constraints that prevent bodies from penetrating each other and simulate friction and restitution.
- Joint: A specific type of constraint used to connect two or more bodies (e.g., revolute, prismatic, or distance joints). Joints can include limits (restricting range of motion) and motors (driving motion).
Manage mass ratios for simulation stability
masterTo maintain simulation stability in Planck.js, avoid stacking heavy bodies on top of much lighter bodies or connecting heavy bodies to light bodies via joint chains. Stability degrades significantly when the mass ratio between connected or stacked bodies exceeds 10:1.Use the Planck.js Testbed for visualization
masterThe Testbed is a simple tool included in the project repository designed to help you visualize and interact with your physics simulations. It is compatible with the Piqnt playground.Use a Friction Joint for 2D friction
masterTheFrictionJointis used to simulate top-down friction. It provides both 2D translational friction and angular friction between two bodies. For low-level implementation details, refer toFrictionJoint.jsandApplyForce.jsin the source.Resolve collisions and prevent tunneling with Continuous Collision
masterBecause the Planck.js solver advances bodies using discrete time steps, fast-moving objects may 'tunnel' through other objects. To prevent this, Planck.js uses two specialized mechanisms:
- Time of Impact (TOI) Interpolation: The collision algorithms interpolate the motion of two bodies to calculate the exact moment they would first collide.
- Sub-stepping Solver: A specialized solver that moves bodies to their calculated Time of Impact and resolves the collision before proceeding with the rest of the simulation step.
Use Planck Testbed via Script Tag (CDN)
masterTo use the testbed via CDN, use the
planck-with-testbed.min.jsdistribution. Note that the testbed typically requires specific HTML elements (like#testbed-info,#testbed-status, and#testbed-play) to function correctly.<html><body> <span id="testbed-info"></span> <span id="testbed-status"></span> <button id="testbed-play">Play</button> <script src="https://cdn.jsdelivr.net/npm/planck/dist/planck-with-testbed.min.js"></script> <script> const { World, Testbed } = planck; const world = new World(); const testbed = Testbed.mount(); testbed.start(world); </script> </body></html>Create and destroy Fixtures
masterA
Fixtureattaches a shape to a body, giving it physical properties. A body with multiple fixtures is known as a compound body.To create a fixture, pass a definition object to
body.createFixture(). You do not need to manually manage the fixture's lifecycle; it is automatically destroyed when the parent body is destroyed. To manually remove a specific fixture (e.g., for breakable objects), usebody.destroyFixture(fixture).let myFixture = myBody.createFixture({ shape: myShape, density: 1, }); // To destroy it manually: myBody.destroyFixture(myFixture);Understand Weld Joint behavior and limitations
masterA
WeldJointattempts to constrain all relative motion between two bodies.Important Limitation: Because the Planck.js solver is iterative, weld joints are 'soft'. If you connect a chain of bodies using weld joints, the structure will flex rather than remaining perfectly rigid.
Best Practice for Breakable Structures: Do not use a chain of weld joints to create breakable structures. Instead, create a single body with multiple fixtures. To simulate breaking, destroy a fixture and recreate it on a new body.