Getting started
This guide takes you from an empty project to a bouncing ball rendered on screen.
Install
Section titled “Install”pnpm add jolt-ts# or: npm install jolt-ts / yarn add jolt-tsjolt-ts ships the compiled Jolt WASM builds inside the package, so there is nothing else to download. The default wasm-compat build embeds the WASM binary directly in its JavaScript, which means it works without any asset copying or locateFile configuration — ideal for bundlers and static sites. See Loading & WASM builds for the other variants.
Create a world
Section titled “Create a world”Everything starts with a World. Creating one is asynchronous because it initializes the WASM runtime the first time.
import { World, Body, Shape } from "jolt-ts";
const world = await World.create({ gravity: [0, -9.81, 0],});World.create() loads the default wasm-compat build for you. To reuse one runtime across many worlds (recommended if you create more than one), load it once and pass it in:
import { loadJolt, World } from "jolt-ts";
const runtime = await loadJolt(); // wasm-compat by defaultconst world = await World.create({ runtime });Add bodies
Section titled “Add bodies”A Body is a rigid body with a Shape. Create bodies from a plain options object…
const floor = world.createBody({ type: "static", shape: Shape.box({ halfExtents: [50, 0.5, 50] }), position: [0, -0.5, 0], layer: "static",});…or with the fluent Body descriptor builder, whichever reads better:
const ball = world.createBody( Body.dynamic() .shape(Shape.sphere(0.5)) .translation(0, 8, 0) .layer("moving") .restitution(0.5),);Both styles accept the same fields. Object literals are easy to serialize and generate; the builder is nice for handwritten code. See Bodies & motion.
Step the simulation
Section titled “Step the simulation”Advance the world by a fixed timestep. A real app runs this from a fixed-timestep loop; for a quick test, just call it:
for (let i = 0; i < 120; i++) { world.step(1 / 60);}
console.log(ball.translation()); // → { x, y, z }, now resting on the floorstep(deltaTime, collisionSteps?) runs Jolt’s update. Use a fixed deltaTime (e.g. 1/60) for stable, reproducible physics — don’t feed it a variable frame delta directly.
Read transforms back
Section titled “Read transforms back”Bodies expose plain-JS getters, plus zero-allocation …Into() variants for hot loops:
const p = ball.translation(); // { x, y, z }const r = ball.rotation(); // { x, y, z, w }
// Hot-loop friendly: write into a buffer you own.const position = new Float32Array(3);ball.translationInto(position);Render with three.js
Section titled “Render with three.js”jolt-ts is renderer-agnostic — it only computes physics. To draw a frame, copy each body’s transform onto a mesh. Here is the essence of what every demo on this site does:
import * as THREE from "three";import { World, Shape } from "jolt-ts";
const world = await World.create({ gravity: [0, -9.81, 0] });world.createBody({ type: "static", shape: Shape.box({ halfExtents: [25, 0.5, 25] }), position: [0, -0.5, 0], layer: "static" });const ball = world.createBody({ type: "dynamic", shape: Shape.sphere(0.5), position: [0, 6, 0], layer: "moving" });
const mesh = new THREE.Mesh(new THREE.SphereGeometry(0.5), new THREE.MeshStandardMaterial());scene.add(mesh);
const position: [number, number, number] = [0, 0, 0];const rotation: [number, number, number, number] = [0, 0, 0, 1];
function frame() { world.step(1 / 60); ball.translationInto(position); ball.rotationInto(rotation); mesh.position.set(...position); mesh.quaternion.set(...rotation); renderer.render(scene, camera); requestAnimationFrame(frame);}frame();Clean up
Section titled “Clean up”When you’re done with a world, dispose it. That releases every native object it owns — bodies, shapes, query collectors, and the Jolt interface itself.
world.dispose();There is no per-body or per-shape bookkeeping to remember: world.dispose() cleans up everything the world created. If you use using, World also implements Symbol.dispose:
{ using world = await World.create(); // …} // world.dispose() runs automatically hereNext steps
Section titled “Next steps”- Core concepts — how worlds, bodies, shapes, and layers fit together.
- Shapes — spheres, boxes, capsules, hulls, meshes, and compounds.
- Queries — raycasts and shape casts.
- Determinism & networking — snapshots and rollback.
- Character & vehicle controllers — drop-in movement with the
jolt-ts-character-controllercompanion.