### Start Testbed Simulation Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Create a new physics world and then start the testbed simulation with the created world. ```javascript // Create a world const world = new World(); // Start simulation const testbed = Testbed.start(world); ``` -------------------------------- ### Load Planck.js Example Dynamically Source: https://github.com/piqnt/planck.js/blob/master/testbed/index.html Dynamically loads a Planck.js example based on URL parameters. Ensure the 'example' query parameter matches a valid example file. ```javascript const url = new URL(document.location.toString()); const file = url.searchParams.get("example"); import('/example/' + file + '.ts'); ``` -------------------------------- ### Mount Testbed Before Starting Simulation Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Mount the testbed instance first to access it before simulation starts, then create a world and start the simulation. ```javascript // Mount testbed const testbed = Testbed.mount(); // Create a world const world = new World(); // Start simulation testbed.start(world); ``` -------------------------------- ### Install Testbed from NPM Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Install the planck package using npm. Then import World and Testbed into your JavaScript code. ```bash npm install planck ``` ```javascript import { World, Testbed } from 'planck/with-testbed'; ``` -------------------------------- ### Testbed Initialization Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Demonstrates how to initialize the Testbed and start a physics simulation. ```APIDOC ## Testbed Initialization ### Description Initializes the Testbed and starts the physics simulation. ### Method `Testbed.start(world)` ### Parameters - **world** (World) - Required - The Planck.js physics world to simulate. ### Request Example ```js const { World, Testbed } = planck; const world = new World(); const testbed = Testbed.start(world); ``` ``` ```APIDOC ## Testbed Mount and Start ### Description Mounts the Testbed first, allowing access to its instance before starting the simulation. ### Method `Testbed.mount()` and `testbed.start(world)` ### Parameters - **world** (World) - Required - The Planck.js physics world to simulate. ### Request Example ```js const { World, Testbed } = planck; const testbed = Testbed.mount(); const world = new World(); testbed.start(world); ``` ``` -------------------------------- ### Initialize Example Navigation Controls Source: https://github.com/piqnt/planck.js/blob/master/testbed/index.html Sets up event listeners for navigation controls (reload, select, next, previous) to manage example loading and browsing. Requires HTML elements with specific IDs. ```javascript import list from '/example/list.json'; { const reloadButton = document.getElementById('testbed-reload'); const listSelect = document.getElementById('testbed-select'); const nextButton = document.getElementById('testbed-next'); const prevButton = document.getElementById('testbed-prev'); reloadButton.addEventListener('click', function () { window.location.reload(); }); listSelect.addEventListener('change', function () { window.location.href = this.options[listSelect.selectedIndex].value; }); for (const example of list) { const option = document.createElement('option'); option.value = '?example=' + example; option.innerHTML = example; option.selected = window.location.search.indexOf("=" + example) > -1; listSelect.appendChild(option); } nextButton.addEventListener('click', function () { playNext(+1); }); prevButton.addEventListener('click', function () { playNext(-1); }); function playNext(step) { const nextIndex = (listSelect.selectedIndex + step + listSelect.options.length) % listSelect.options.length; const nextOption = listSelect.options[nextIndex]; if (nextOption && nextOption.value) { window.location.href = nextOption.value; } } } ``` -------------------------------- ### Install Planck via NPM Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/install.md Install the planck package using npm. This is the first step before importing the library into your project. ```sh npm install planck ``` -------------------------------- ### Import Planck with Testbed via ES Modules Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/install.md Import World and Testbed from 'planck/with-testbed' to use the testing environment. Mount and start the testbed to begin. ```js import { World, Testbed } from 'planck/with-testbed'; const world = new World(); const testbed = Testbed.mount(); testbed.start(world); ``` -------------------------------- ### Run Testbed Locally from Source Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Clone the Planck.js repository, install dependencies, and run the development server to use the testbed locally. This is useful for debugging or modifying the library. ```bash git clone cd planck.js npm install npm run dev ``` -------------------------------- ### Using Planck.js Testbed for Visual Debugging Source: https://context7.com/piqnt/planck.js/llms.txt Mount and start the Testbed for interactive simulation visualization. Configure camera, simulation speed, and background. Handle simulation steps and key events. ```typescript import { World, Box, Circle, Edge, Testbed } from "planck/with-testbed"; // or: import { World, Box, Circle, Edge, Testbed } from "planck"; const testbed = Testbed.mount(); testbed.width = 20; // world units visible horizontally testbed.height = 15; // world units visible vertically testbed.x = 0; // camera center x testbed.y = 0; // camera center y testbed.hz = 60; // simulation steps per second testbed.speed = 1.0; // simulation speed multiplier testbed.background = "#222222"; const world = new World({ gravity: { x: 0, y: -10 } }); const ground = world.createBody({ type: "static" }); ground.createFixture({ shape: new Edge({ x: -10, y: 0 }, { x: 10, y: 0 }) }); const ball = world.createDynamicBody({ position: { x: 0, y: 5 } }); ball.createFixture({ shape: new Circle(0.5), density: 1, restitution: 0.8 }); // Called every simulation step testbed.step = (dt: number, t: number) => { testbed.status("Time", t.toFixed(2)); testbed.status("Bodies", world.getBodyCount()); // Move camera to follow ball const pos = ball.getPosition(); testbed.x = pos.x; }; // Key handling testbed.keydown = (keyCode: number, label: string) => { if (testbed.activeKeys.fire) { ball.applyLinearImpulse({ x: 0, y: 10 }, ball.getPosition()); } }; // Custom drawing testbed.drawPoint({ x: 0, y: 3 }, 5, "red"); testbed.drawCircle({ x: 1, y: 1 }, 0.5, "blue"); testbed.drawSegment({ x: -1, y: 0 }, { x: 1, y: 0 }, "green"); // Body/fixture styling ball.style = { fill: "orange", stroke: "white" }; // Start rendering testbed.start(world); ``` -------------------------------- ### Create Body with Sleep Parameters Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Configure whether a body can sleep and if it starts in a sleeping state. Sleeping bodies have very little CPU overhead. ```javascript world.createBody({ allowSleep: true, awake: true, }); ``` -------------------------------- ### Perform Ray Cast and Capture Closest Hit Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/world/ray-cast.md This example demonstrates how to perform a ray cast and capture the closest fixture hit. By returning the current fraction, the ray is clipped, allowing for the identification of the nearest fixture, though fixtures are not guaranteed to be reported in order. ```javascript let closest = null; myWorld.rayCast(Vec2(-1, 0), Vec2(3, 1), function(fixture, point, normal, fraction) { closest = { fixture: fixture, point: point, // Vec2 normal: normal, // Vec2 fraction: fraction, // number } // By returning the current fraction, we instruct the calling code to clip the ray and // continue the ray-cast to the next fixture. WARNING: do not assume that fixtures // are reported in order. However, by clipping, we can always get the closest fixture. return fraction; }); ``` -------------------------------- ### Get Fixture and Body from Contact Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/contacts.md Access the fixtures involved in a contact and subsequently retrieve their associated bodies and user data. ```javascript let fixtureA = myContact.getFixtureA(); let bodyA = fixtureA.getBody(); let actorA = bodyA.getUserData(); ``` -------------------------------- ### Wake up all bodies in the world Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/world.md Iterate through all bodies in the world and set them to an awake state. This is a basic example of accessing and modifying world objects. ```javascript for (let b = myWorld.getBodyList(); b; b = b.getNext()) { b.setAwake(true); } ``` -------------------------------- ### Set and Get Body Transform Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Set a body's position and angle directly using a `Transform` object, or retrieve its current transform. This is less common than using simulation for movement. ```javascript body.setTransform(position, angle); ``` ```javascript body.getTransform(); // Transform ``` -------------------------------- ### Joints Source: https://context7.com/piqnt/planck.js/llms.txt Details on creating and managing joints, which connect two bodies and constrain their relative motion. Includes RevoluteJoint as an example. ```APIDOC ## Joints All joints are created with `world.createJoint(new JointType(def, bodyA, bodyB, ...))` and destroyed with `world.destroyJoint(joint)`. Common `JointOpt` base fields: `collideConnected` (bool), `userData`. ### RevoluteJoint **`new RevoluteJoint(def, bodyA, bodyB, anchor)`** — Constrains two bodies to share a pivot point. Supports limits and motor. ```typescript import { World, Box, RevoluteJoint } from "planck"; const world = new World({ gravity: { x: 0, y: -10 } }); const ground = world.createBody({ type: "static" }); const wheel = world.createDynamicBody({ position: { x: 0, y: 2 } }); wheel.createFixture({ shape: new Box(0.5, 0.5), density: 1 }); const joint = world.createJoint( new RevoluteJoint( { enableMotor: true, motorSpeed: 2.0, // rad/s maxMotorTorque: 10.0, // N·m enableLimit: true, lowerAngle: -Math.PI / 4, upperAngle: Math.PI / 4, }, ground, wheel, { x: 0, y: 2 }, // world anchor point ), ); // Runtime control joint.setMotorSpeed(5.0); joint.setMaxMotorTorque(20.0); joint.enableMotor(true); joint.enableLimit(false); console.log(joint.getJointAngle()); // current angle (rad) console.log(joint.getJointSpeed()); // angular velocity (rad/s) console.log(joint.getMotorTorque(1/60)); // torque this step ``` ``` -------------------------------- ### Testbed.mount and Testbed.start Source: https://context7.com/piqnt/planck.js/llms.txt Visual debugging and interactive simulation runner. Provides properties for camera control and simulation settings, and callbacks for simulation steps and user input. ```APIDOC ## Testbed **`Testbed.mount(options?): TestbedInterface`** and **`Testbed.start(world): TestbedInterface`** — Visual debugging and interactive simulation runner (requires `planck/with-testbed` bundle). `TestbedInterface` properties: `width`, `height`, `x` (camera offset), `y`, `hz` (simulation frequency), `speed`, `background`, `mouseForce`, `activeKeys`. Callbacks: `step(dt, t)`, `keydown(keyCode, label)`, `keyup(keyCode, label)`. ```typescript import { World, Box, Circle, Edge, Testbed } from "planck/with-testbed"; // or: import { World, Box, Circle, Edge, Testbed } from "planck"; const testbed = Testbed.mount(); testbed.width = 20; // world units visible horizontally testbed.height = 15; // world units visible vertically testbed.x = 0; // camera center x testbed.y = 0; // camera center y testbed.hz = 60; // simulation steps per second testbed.speed = 1.0; // simulation speed multiplier testbed.background = "#222222"; const world = new World({ gravity: { x: 0, y: -10 } }); const ground = world.createBody({ type: "static" }); ground.createFixture({ shape: new Edge({ x: -10, y: 0 }, { x: 10, y: 0 }) }); const ball = world.createDynamicBody({ position: { x: 0, y: 5 } }); ball.createFixture({ shape: new Circle(0.5), density: 1, restitution: 0.8 }); // Called every simulation step testbed.step = (dt: number, t: number) => { testbed.status("Time", t.toFixed(2)); testbed.status("Bodies", world.getBodyCount()); // Move camera to follow ball const pos = ball.getPosition(); testbed.x = pos.x; }; // Key handling testbed.keydown = (keyCode: number, label: string) => { if (testbed.activeKeys.fire) { ball.applyLinearImpulse({ x: 0, y: 10 }, ball.getPosition()); } }; // Custom drawing testbed.drawPoint({ x: 0, y: 3 }, 5, "red"); testbed.drawCircle({ x: 1, y: 1 }, 0.5, "blue"); testbed.drawSegment({ x: -1, y: 0 }, { x: 1, y: 0 }, "green"); // Body/fixture styling ball.style = { fill: "orange", stroke: "white" }; // Start rendering testbed.start(world); ``` ``` -------------------------------- ### Get Raw Contact Manifold Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/contacts.md Retrieve the raw contact manifold from a contact object. This is for advanced usage and direct modification is generally not supported. ```javascript let manifold = contact.getManifold(); ``` -------------------------------- ### Viewbox Configuration Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Explains how to adjust the Testbed's viewbox for rendering. ```APIDOC ## Viewbox Configuration ### Description Adjusts the Testbed's viewbox by setting its center coordinates and dimensions. ### Properties - **testbed.x** (number) - The x-coordinate of the viewbox center. - **testbed.y** (number) - The y-coordinate of the viewbox center. - **testbed.width** (number) - The width of the viewbox. - **testbed.height** (number) - The height of the viewbox. ### Request Example ```js // Set viewbox center testbed.x = 0; testbed.y = 0; // Set viewbox size testbed.width = 30; testbed.height = 20; ``` ``` -------------------------------- ### Display Information on Testbed Screen Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Use the 'info()' method to display general text messages and the 'status()' method to display key-value pairs that persist until changed. These are useful for user guidance and displaying game state. ```javascript // Use info() to print some text on screen testbed.info('Use arrow keys to move player'); testbed.step = function() { // Use status() to print key-values // Testbed will retain value of keys until they are changed testbed.status('score', score); testbed.status('time', time); }; ``` -------------------------------- ### Create and Configure Planck.js World Source: https://context7.com/piqnt/planck.js/llms.txt Initialize a new physics world with custom gravity and simulation settings. Use `world.step()` to advance the simulation and inspect world statistics. ```typescript import { World, Vec2 } from "planck"; // Create world with downward gravity const world = new World({ gravity: { x: 0, y: -10 } }); // Alternatively pass a Vec2 directly // const world = new World(new Vec2(0, -9.8)); // Configure simulation settings world.setAllowSleeping(true); world.setGravity({ x: 0, y: -9.81 }); console.log(world.getGravity()); // Vec2 { x: 0, y: -9.81 } // Advance simulation: 60 Hz, 8 velocity iterations, 3 position iterations world.step(1 / 60, 8, 3); // Inspect body/joint/contact counts console.log(world.getBodyCount()); // number of bodies console.log(world.getJointCount()); // number of joints console.log(world.getContactCount()); // number of active contacts // Iterate all bodies for (let b = world.getBodyList(); b; b = b.getNext()) { console.log(b.getPosition()); } // Iterate all joints for (let j = world.getJointList(); j; j = j.getNext()) { console.log(j.getType()); } // Shift world origin for large worlds world.shiftOrigin({ x: 100, y: 0 }); // Queue deferred update (safe to call inside contact callbacks) world.queueUpdate((w) => { w.destroyBody(someBody); }); ``` -------------------------------- ### Get Body Mass Properties Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Retrieve the mass, rotational inertia, and local center of mass for a body. `getMassData` populates a provided `massData` object. ```javascript body.getMass(); // number ``` ```javascript body.getInertia(); // number ``` ```javascript body.getLocalCenter(); // Vec2 ``` ```javascript body.getMassData(massData); ``` -------------------------------- ### Create a Planck.js World Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/hello-world.md Initialize a new physics world. Optionally configure gravity. ```javascript let world = new World({ gravity: {x: 0, y: -10}, }); ``` -------------------------------- ### Fixture and Collision Filtering Source: https://context7.com/piqnt/planck.js/llms.txt Demonstrates how to create fixtures with collision filtering properties and how to update them at runtime. It also shows how to destroy individual fixtures. ```APIDOC ## Fixture and Collision Filtering **`body.createFixture(def: FixtureDef): Fixture`** — Creates a fixture; `FixtureDef` includes shape, density, friction, restitution, isSensor, and filter bits. Key fixture methods: `getBody()`, `getShape()`, `getType()`, `isSensor()`, `setFriction(v)`, `getFriction()`, `setRestitution(v)`, `getRestitution()`, `setDensity(v)`, `getDensity()`, `setFilterData({groupIndex, categoryBits, maskBits})`, `getFilterData()`, `getUserData()`, `setUserData(data)`. ```typescript import { World, Box, Circle } from "planck"; const world = new World({ gravity: { x: 0, y: -10 } }); const body = world.createDynamicBody({ position: { x: 0, y: 5 } }); // Sensor: detects overlaps but generates no collision response const sensorFixture = body.createFixture({ shape: new Circle(2.0), isSensor: true, userData: { role: "pickup-zone" }, }); // Solid fixture with collision filtering // Bits: player(0x0002) collides with walls(0x0001) and enemies(0x0004) const solidFixture = body.createFixture({ shape: new Box(0.4, 0.8), density: 1.0, friction: 0.5, restitution: 0.0, filterCategoryBits: 0x0002, filterMaskBits: 0x0001 | 0x0004, filterGroupIndex: 0, // 0 = use category/mask bits }); // Update filter at runtime solidFixture.setFilterData({ groupIndex: 0, categoryBits: 0x0002, maskBits: 0x0001, }); // Destroy individual fixture body.destroyFixture(sensorFixture); ``` ``` -------------------------------- ### Get World Manifold Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/contacts.md Compute and retrieve the world positions of contact points using the current body positions. This helper function populates a provided WorldManifold object. ```javascript contact.getWorldManifold(worldManifold); ``` -------------------------------- ### Get Pulley Joint Lengths Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/joint/pulley.md Retrieves the current lengths of the pulley rope segments. These values represent the distance from the ground anchor to the body anchor for each side of the pulley. ```javascript pulleyJoint.getLengthA(); // number pulleyJoint.getLengthB(); // number ``` -------------------------------- ### Create Fixture Shortcut Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/api-conventions/factories-and-definitions.md A convenient shortcut allows creating a fixture directly from a shape and density, bypassing the need for a separate fixture definition object. ```javascript let fixture = body.createFixture(shape, density); ``` -------------------------------- ### Create a Fixture Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/fixture.md Initialize a fixture definition and pass it to the parent body to create a fixture. The fixture is automatically destroyed when the parent body is destroyed. ```javascript let myFixture = myBody.createFixture({ shape: myShape, density: 1, }); ``` -------------------------------- ### Set and Get Body Angle Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Set a body's rotation angle in radians or retrieve its current angle. The simulation usually handles angle updates based on physics. ```javascript body.setAngle(angle); ``` ```javascript body.getAngle(); // number ``` -------------------------------- ### Set and Get Body Position Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Set a body's position using a `Vec2` object or retrieve its current position in world coordinates. Typically, the simulation updates position automatically. ```javascript body.setPosition(position); ``` ```javascript body.getPosition(); // Vec2 ``` -------------------------------- ### Adjust Testbed Viewbox Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Set the viewbox center (x, y) and dimensions (width, height) in physical units to adjust the testbed's visible area. The testbed will automatically calculate the rendering scale and offset. ```javascript // Viewbox center testbed.x = 0; testbed.y = 0; // Viewbox size testbed.width = 30; testbed.height = 20; ``` -------------------------------- ### Displaying Information Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Shows how to use the `info` and `status` methods to display text and key-value pairs on the screen. ```APIDOC ## Displaying Information ### Description Utilizes `info()` for general text display and `status()` for key-value pairs within the Testbed. ### Methods - **testbed.info(text)**: Prints a string of text on the screen. - **testbed.status(key, value)**: Prints a key-value pair on the screen. The value is retained until changed. ### Request Example ```js // Use info() to print some text on screen testbed.info('Use arrow keys to move player'); testbed.step = function() { // Use status() to print key-values testbed.status('score', score); testbed.status('time', time); }; ``` ``` -------------------------------- ### Set and Get Body Type Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Control the body's type (e.g., static, kinematic, dynamic) and retrieve its current type. The type affects how the body responds to forces and simulation. ```javascript body.setType(bodyType); ``` ```javascript body.getType(); // string ``` -------------------------------- ### Get Joint Reaction Force and Torque Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/joint.md Explains how to obtain the reaction force and torque applied to the second body at the anchor point. These values can be useful for implementing game events or breaking joints. ```javascript joint.getReactionForce(inv_dt); // Vec2 joint.getReactionTorque(inv_dt); // number ``` -------------------------------- ### Add Game-Loop Callback to Testbed Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Assign a function to the 'step' property of the testbed instance to execute custom code in each frame of the simulation. ```javascript testbed.step = function() { // Code to run in each game loop }; ``` -------------------------------- ### Get World Manifold Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/collision.md Converts manifold contact points and normal to world coordinates. Requires manifold, shape transforms, and radii. The world manifold uses the point count from the original manifold. ```javascript let worldManifold = manifold.getWorldManifold(null, transformA, shapeA.m_radius, transformB, shapeB.m_radius) for (let i = 0; i < manifold.pointCount; ++i) { let point = worldManifold.points[i]; // Vec2 // ... } ``` -------------------------------- ### Game-loop Callback Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/testbed.md Details on how to define a callback function for the Testbed's game loop. ```APIDOC ## Game-loop Callback ### Description Assigns a function to be executed in each frame of the Testbed's game loop. ### Property - **testbed.step** (function) - The callback function to execute each frame. ### Request Example ```js testbed.step = function() { // Code to run in each game loop }; ``` ``` -------------------------------- ### Create and Filter Fixtures Source: https://context7.com/piqnt/planck.js/llms.txt Demonstrates creating dynamic bodies with sensor and solid fixtures, including collision filtering using categoryBits, maskBits, and groupIndex. Updates filter data at runtime and destroys fixtures. ```typescript import { World, Box, Circle } from "planck"; const world = new World({ gravity: { x: 0, y: -10 } }); const body = world.createDynamicBody({ position: { x: 0, y: 5 } }); // Sensor: detects overlaps but generates no collision response const sensorFixture = body.createFixture({ shape: new Circle(2.0), isSensor: true, userData: { role: "pickup-zone" }, }); // Solid fixture with collision filtering // Bits: player(0x0002) collides with walls(0x0001) and enemies(0x0004) const solidFixture = body.createFixture({ shape: new Box(0.4, 0.8), density: 1.0, friction: 0.5, restitution: 0.0, filterCategoryBits: 0x0002, filterMaskBits: 0x0001 | 0x0004, filterGroupIndex: 0, // 0 = use category/mask bits }); // Update filter at runtime solidFixture.setFilterData({ groupIndex: 0, categoryBits: 0x0002, maskBits: 0x0001, }); // Destroy individual fixture body.destroyFixture(sensorFixture); ``` -------------------------------- ### Process Contact Points After Time Step Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/contacts.md Buffer contact data and process it after the time step to safely alter the physics world. This example shows how to handle orphaned bodies when processing the contact buffer. ```javascript // We are going to destroy some bodies according to contact // points. We must buffer the bodies that should be destroyed // because they may belong to multiple contact points. let nuke = []; // Traverse the contact results. Destroy bodies that // are touching heavier bodies. for (let i = 0; i < points.length && nuke.length < MAX_NUKE; ++i) { let point = points[i]; let body1 = point.fixtureA.getBody(); let body2 = point.fixtureB.getBody(); let mass1 = body1.getMass(); let mass2 = body2.getMass(); if (mass1 > 0.0 && mass2 > 0.0) { if (mass2 > mass1) { nuke.push(body1); } else { nuke.push(body2); } } } for (let i = 0; i < nuke.length; i++) { let b = nuke[i]; world.destroyBody(b); } ``` -------------------------------- ### Ray Cast Against Shape Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/shape.md Casts a ray against a shape to find the first intersection point and normal. A child index is needed for chain shapes. No hit registers if the ray starts inside a convex shape. ```javascript let transform = Transform.identity(); let input = {}; // RayCastInput input.p1 = Vec2(0, 0); input.p2 = Vec2(1, 0); input.maxFraction = 1; let childIndex = 0; let output = {}; // RayCastOutput let hit = shape.RayCast(output, input, transform, childIndex); if (hit) { let hitPoint = Vec2.add( Vec2.mul(1 - output.fraction, input.p1), Vec2.mul(output.fraction, input.p2) ); } ``` -------------------------------- ### Create a Static Platform Body Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/hello-world.md Create a static body to act as a platform. Static bodies are immovable and do not collide with other static bodies. ```javascript let platform = world.createBody({ type: "static", position: {x: 0, y: -10}, angle: Math.PI * 0.1 }); ``` -------------------------------- ### AABB Constructor and Methods Source: https://context7.com/piqnt/planck.js/llms.txt Demonstrates the creation and usage of the AABB (Axis-aligned bounding box) class for spatial queries, including extending, combining, testing overlap, and retrieving geometric properties. ```APIDOC ## AABB **`new AABB(lowerBound?, upperBound?)`** — Axis-aligned bounding box used for spatial queries. ```typescript import { AABB, Vec2 } from "planck"; const aabb = new AABB({ x: -1, y: -1 }, { x: 1, y: 1 }); // Extend by a point or another AABB aabb.extend(0.1); // Combine two AABBs const combined = new AABB(); combined.combine( new AABB({ x: -2, y: -2 }, { x: 0, y: 0 }), new AABB({ x: 0, y: 0 }, { x: 2, y: 2 }), ); // combined = {lower:(-2,-2), upper:(2,2)} // Test overlap const other = new AABB({ x: 0, y: 0 }, { x: 3, y: 3 }); console.log(AABB.testOverlap(aabb, other)); // true // Get center and extents console.log(aabb.getCenter()); // Vec2(0,0) console.log(aabb.getExtents()); // Vec2(1,1) console.log(aabb.isValid()); // true ``` ``` -------------------------------- ### Disabling Contact in Pre-Solve Event Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/contacts.md Use the 'pre-solve' event to conditionally disable contacts. This example disables a contact if the world manifold's normal indicates a downward direction (y < -0.5), useful for one-sided platforms. ```typescript world.on('pre-solve', function(contact: Contact, oldManifold: Manifold) { WorldManifold worldManifold; contact.getWorldManifold(&worldManifold); if (worldManifold.normal.y < -0.5) { contact.setEnabled(false); } }); ``` -------------------------------- ### Get Body Center of Mass in World Coordinates Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Retrieve the body's center of mass position in world coordinates. This is useful for understanding the body's overall position, though often the body's origin is used for transformations. ```javascript body.getWorldCenter(); // Vec2 ``` -------------------------------- ### Basic Rendering Loop with Planck.js Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/rendering.md This class demonstrates a basic game loop for rendering physics objects. It advances the simulation, iterates over bodies, fixtures, and joints, and handles object removal events. Use `requestAnimationFrame` for smooth rendering. ```javascript class Renderer { world = null; started = false; start(world) { this.world = world; // Add listeners world.on('remove-body', this.removeBody); world.on('remove-joint', this.removeJoint); world.on('remove-fixture', this.removeFixture); // Start frame loop this.started = true; this.loop(0); } stop() { // Remove listeners world.off('remove-body', this.removeBody); world.off('remove-joint', this.removeJoint); world.off('remove-fixture', this.removeFixture); // Stop next frame this.started = false; } // Game loop loop = (timeStamp) => { if (!this.started) { return; } // In each frame call world.step with fixed timeStep // This is a simplified implementation, in a more advanced implementation // you need to use elapsed time since last frame and call step more than once if needed. // When called by requestAnimationFrame() you'll get a timestamp as argument, // https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame this.world.step(1 / 60); // Iterate over bodies for (let body = this.world.getBodyList(); body; body = body.getNext()) { this.renderBody(body); // ... and fixtures for (let fixture = body.getFixtureList(); fixture; fixture = fixture.getNext()) { this.renderFixture(fixture); } } // Iterate over joints for (let joint = this.world.getJointList(); joint; joint = joint.getNext()) { this.renderJoint(joint); } // Request a new frame window.requestAnimationFrame(this.loop); } renderBody(body) { // Render or update body rendering } renderFixture(fixture) { // Render or update fixture rendering } renderJoint(joint) { // Render or update joint rendering } removeBody(body) { // Remove body rendering } removeFixture(fixture) { // Remove fixture rendering } removeJoint(joint) { // Remove joint from rendering } } const renderer = new Renderer(); renderer.start(world); ``` -------------------------------- ### Include Planck with Testbed via Script Tag Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/install.md Include the testbed version of Planck.js from a CDN using a script tag. This enables the testbed functionality directly in your HTML. ```html
``` -------------------------------- ### Create a Dynamic Box Body Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/hello-world.md Create a dynamic body that will respond to forces and simulate movement. Ensure the body type is set to 'dynamic'. ```javascript let body = world.createBody({ type: "dynamic", position: {x: 0, y: 4} }); ``` -------------------------------- ### World.queryAABB and World.rayCast Source: https://context7.com/piqnt/planck.js/llms.txt Performs spatial queries on the physics world. `queryAABB` finds all fixtures within a given axis-aligned bounding box, and `rayCast` finds the closest fixture intersected by a ray. ```APIDOC ## World.queryAABB and World.rayCast **`world.queryAABB(aabb, callback)`** and **`world.rayCast(p1, p2, callback)`** — Spatial queries against all fixtures. ```typescript import { World, AABB, Vec2, Fixture } from "planck"; const world = new World({ gravity: { x: 0, y: -10 } }); // AABB overlap query — callback returns false to stop early const queryBox = new AABB({ x: -5, y: -1 }, { x: 5, y: 1 }); world.queryAABB(queryBox, (fixture: Fixture) => { console.log("Fixture in area:", fixture.getBody().getUserData()); return true; // continue; return false to stop }); // Ray cast — find closest hit let closestFraction = 1.0; let closestFixture: Fixture | null = null; world.rayCast( { x: -10, y: 5 }, // ray start { x: 10, y: 5 }, // ray end (fixture, point, normal, fraction) => { if (fraction < closestFraction) { closestFraction = fraction; closestFixture = fixture; } return fraction; // clip ray to this point; return 1 to continue, 0 to stop }, ); if (closestFixture) { console.log("Hit:", closestFixture.getBody().getUserData(), "at fraction:", closestFraction); } ``` ``` -------------------------------- ### Step the World Simulation Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/world/simulation.md Drives the physics simulation forward by one time step. Specify the time step duration, and the number of velocity and position iterations for the constraint solver. ```javascript let timeStep = 1 / 60; let velocityIterations = 10; let positionIterations = 8; myWorld.step(timeStep, velocityIterations, positionIterations); ``` -------------------------------- ### Set Body Position and Angle Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Initialize a body's position and angle at creation for better performance than moving it later. ```javascript world.createBody({ position: {x: 0, y: 2}, // the body's origin position. angle: 0.25 * Math.PI // the body's angle in radians. }) ``` -------------------------------- ### Import Planck Core via ES Modules Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/install.md Import the World class from the planck library using ES module syntax. This is used for basic Planck.js functionality. ```js import { World } from 'planck'; const world = new World(); ``` -------------------------------- ### Run Simulation Loop Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/world/simulation.md Executes the physics simulation for a specified number of steps. This loop updates the world state and logs the position and angle of a dynamic body. ```javascript for (let i = 0; i < 60; ++i) { world.step(timeStep, velocityIterations, positionIterations); let position = body.getPosition(); let angle = body.getAngle(); console.log(position.x, position.y, angle); } ``` -------------------------------- ### Create and Destroy a Revolute Joint Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/joint.md Demonstrates the lifecycle of a revolute joint, including creation using the world factory and subsequent destruction. It's good practice to nullify variables after destruction to prevent accidental reuse. ```javascript let joint = myWorld.createJoint(new RevoluteJoint({ bodyA: myBodyA, bodyB: myBodyB, anchorPoint: myBodyA.getCenterPosition(), })); // ... do stuff ... myWorld.destroyJoint(joint); joint = null; ``` -------------------------------- ### World.createBody / createDynamicBody / createKinematicBody Source: https://context7.com/piqnt/planck.js/llms.txt Creates and registers rigid bodies of different types (static, dynamic, kinematic) with optional definitions. ```APIDOC ## World.createBody / createDynamicBody / createKinematicBody **`world.createBody(def?: BodyDef): Body`** — Creates and registers a rigid body. `BodyDef` fields: `type` (`"static"` | `"kinematic"` | `"dynamic"`, default `"static"`), `position`, `angle`, `linearVelocity`, `angularVelocity`, `linearDamping`, `angularDamping`, `fixedRotation`, `bullet`, `gravityScale`, `allowSleep`, `awake`, `active`, `userData`, `style`. ### Method `createBody`, `createDynamicBody`, `createKinematicBody` ### Parameters - **def** (BodyDef) - Optional - Body definition object. ### Example ```typescript import { World, Box, Circle } from "planck"; const world = new World({ gravity: { x: 0, y: -10 } }); // Static ground body const ground = world.createBody({ type: "static", position: { x: 0, y: 0 }, }); ground.createFixture({ shape: new Box(50, 1), friction: 0.5 }); // Dynamic body using shorthand helper const ball = world.createDynamicBody({ position: { x: 0, y: 10 } }); ball.createFixture({ shape: new Circle(0.5), density: 1.0, restitution: 0.6 }); // Kinematic body (velocity-driven, ignores forces) const platform = world.createKinematicBody({ position: { x: 0, y: 5 } }); platform.setLinearVelocity({ x: 2, y: 0 }); // Destroy a body (also removes its fixtures, joints, contacts) world.destroyBody(ball); ``` ``` -------------------------------- ### Create Body with User Data Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Attach custom application data to a body using the userData property for easy referencing. ```javascript world.createBody({ userData: myActor, }); ``` -------------------------------- ### Create and Extend AABB in TypeScript Source: https://context7.com/piqnt/planck.js/llms.txt Demonstrates creating an Axis-Aligned Bounding Box (AABB) and extending it with a value or another AABB. Ensure AABB and Vec2 are imported from 'planck'. ```typescript import { AABB, Vec2 } from "planck"; const aabb = new AABB({ x: -1, y: -1 }, { x: 1, y: 1 }); // Extend by a point or another AABB aabb.extend(0.1); // Combine two AABBs const combined = new AABB(); combined.combine( new AABB({ x: -2, y: -2 }, { x: 0, y: 0 }), new AABB({ x: 0, y: 0 }, { x: 2, y: 2 }), ); // combined = {lower:(-2,-2), upper:(2,2)} // Test overlap const other = new AABB({ x: 0, y: 0 }, { x: 3, y: 3 }); console.log(AABB.testOverlap(aabb, other)); // true // Get center and extents console.log(aabb.getCenter()); // Vec2(0,0) console.log(aabb.getExtents()); // Vec2(1,1) console.log(aabb.isValid()); // true ``` -------------------------------- ### Combine Friction Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/fixture.md Planck.js combines friction parameters of two fixtures using the geometric mean. If one fixture has zero friction, the contact will have zero friction. ```javascript function mixFriction(friction1, friction2) { return Math.sqrt(friction1 * friction2); } ``` -------------------------------- ### Create a PulleyJoint with a Ratio Source: https://context7.com/piqnt/planck.js/llms.txt Simulate a pulley system using PulleyJoint, where movement on one side affects the other, scaled by a ratio. Configure connected collision, ground anchors, body anchors, and the ratio. ```typescript import { World, Box, PulleyJoint } from "planck"; const world = new World({ gravity: { x: 0, y: -10 } }); const boxA = world.createDynamicBody({ position: { x: -3, y: 5 } }); const boxB = world.createDynamicBody({ position: { x: 3, y: 3 } }); boxA.createFixture({ shape: new Box(0.5, 0.5), density: 1 }); boxB.createFixture({ shape: new Box(0.5, 0.5), density: 1 }); world.createJoint( new PulleyJoint( { collideConnected: true }, boxA, boxB, { x: -3, y: 10 }, // ground anchor A { x: 3, y: 10 }, // ground anchor B boxA.getPosition(), boxB.getPosition(), 1.5, // ratio: 1.5m on B side = 1m on A side ), ); ``` -------------------------------- ### Creating and Manipulating Dynamic Bodies in Planck.js Source: https://context7.com/piqnt/planck.js/llms.txt Create dynamic bodies with various properties like position, angle, damping, and gravity scale. Attach fixtures with specific shapes, densities, and physical properties. Apply forces, torques, and impulses to bodies, and read their state and transform between world and local coordinates. ```typescript import { World, Circle, Box, Vec2 } from "planck"; const world = new World({ gravity: { x: 0, y: -10 } }); const body = world.createDynamicBody({ position: { x: 0, y: 5 }, angle: Math.PI / 4, linearDamping: 0.1, angularDamping: 0.1, fixedRotation: false, bullet: true, // CCD for fast-moving objects gravityScale: 1.5, userData: { id: "player" }, }); // Attach a circle fixture body.createFixture({ shape: new Circle(0.5), density: 2.0, friction: 0.4, restitution: 0.3, isSensor: false, filterCategoryBits: 0x0002, filterMaskBits: 0x0001, }); // Apply forces and impulses body.applyForce({ x: 10, y: 0 }, body.getPosition()); body.applyForceToCenter({ x: 0, y: 20 }); body.applyTorque(5.0); body.applyLinearImpulse({ x: 3, y: 0 }, body.getPosition()); body.applyAngularImpulse(1.0); // Read state console.log(body.getPosition()); // Vec2 console.log(body.getLinearVelocity()); // Vec2 console.log(body.getMass()); // kg console.log(body.getInertia()); // kg·m² // Convert between local and world coordinates const worldPt = body.getWorldPoint({ x: 0.5, y: 0 }); const localPt = body.getLocalPoint(worldPt); // Iterate fixtures for (let f = body.getFixtureList(); f; f = f.getNext()) { console.log(f.getShape().getType()); } ``` -------------------------------- ### Create a new World instance Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/world.md Instantiate a World object with a gravity vector and a boolean to enable or disable body sleeping. ```javascript let myWorld = new World({ gravity: {x: 0, y: -10}, allowSleep: true, }); ``` -------------------------------- ### Create and Destroy a Body Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/body.md Use the World's body factory to create and destroy bodies. Avoid direct instantiation with 'new'. ```javascript let dynamicBody = myWorld.createBody(bodyDef); // ... do stuff ... myWorld.destroyBody(dynamicBody); ``` -------------------------------- ### Body Fixture Factories Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/api-conventions/factories-and-definitions.md Use these factory functions on a `Body` object to create and destroy fixtures. ```APIDOC ## Body Fixture Factories ### Description Fixtures are attached to bodies and define their physical properties. These functions manage fixture creation and destruction. ### Create Fixture from Definition ```js body.createFixture(fixtureDef) ``` ### Create Fixture from Shape and Density ```js body.createFixture(shape, density) ``` ### Destroy Fixture ```js body.destroyFixture(fixture) ``` ``` -------------------------------- ### Create a Gear Joint Source: https://github.com/piqnt/planck.js/blob/master/docs/pages/joint/gear-joint.md Instantiate a GearJoint by providing the two bodies involved and the two joints it connects. The ratio determines the gear's mechanical advantage. Ensure that `joint1` and `joint2` are valid revolute or prismatic joints. ```javascript new GearJoint({ bodyA: myBodyA, bodyB: myBodyB, joint1: myRevoluteJoint, joint2: myPrismaticJoint, ratio: 2 * Math.PI / myLength, }) ```