Physics · class

PhysicsWorld

Explained in Your first game, Rigid bodies.

class PhysicsWorld implements IslandSolver
import { PhysicsWorld } from '@driftengine/physics';

Constructor

new

constructor(options?: WorldOptions)
ParameterTypeDescription
options?WorldOptions

Properties

NameTypeDescription
bodiesreadonlyBodySet
jointsreadonlyJointSet
eventsreadonlyContactEventsWhat touched what during the last tick, ordered by pair key. Drain it after step.
substepsreadonlynumber
iterationsreadonlynumber
gravityXnumber
gravityYnumber
gravityZnumber
contactHertznumber
contactDampingnumber
jointHertznumber
jointDampingnumber
linearDampingnumber
angularDampingnumber
speculativeMarginnumber
allowSleepboolean
frictionModelFrictionModelRead at every substep, so a consumer may switch it between ticks. See WorldOptions.
executorExecutorWho runs the islands. Swappable, and a gate asserts two characters agree.
parallelismreadonlyParallelismWhat the island solving is actually doing.
More

Read it rather than assuming the workers option took. A pool needs a cross-origin isolated page and a bundler that understands a worker entry, and when either is missing this says which in a sentence fit to put on a debug overlay. createSplatSortWorker warns once on the console for the same reason; this is the same fact as data, because a console warning is not something a consumer can show a player or assert in a test.

Accessors

NameTypeDescription
solveStategetIslandSolveStateThe flat view of this world an island's solve needs, and the only view a worker could hold.
More

Built fresh because grow replaces the arrays underneath it; the object is five references and one allocation, which the solve that follows dwarfs.

Public because a character off this thread needs it. SerialExecutor calls solveIsland; a staged or pooled character mirrors this state into shared memory and solves that instead, which it cannot do through a method closed over the live arrays.

islandCountgetnumberHow many islands the last step found.

Methods

dispose

dispose(): void

Stop the worker pool, if there is one. Safe to call twice, and safe on a world without one.

More

A world with a pool must be disposed. Its workers hold the staging SharedArrayBuffer, so a consumer replacing a world between levels leaks both the threads and every body's state with them.

addJoint

addJoint(desc: JointDesc): number

Join two bodies. The relative pose they are in now becomes the one the joint holds.

ParameterTypeDescription
descJointDesc

addBody

addBody(desc: BodyDesc): number
ParameterTypeDescription
descBodyDesc

ignorePair

ignorePair(a: number, b: number): void

Never collide these two, whichever order they are given in and whatever their layers say.

ParameterTypeDescription
anumber
bnumber
More

Both indices are followed through removeBody, so an exclusion cannot outlive the body it was made about and cannot be inherited by whatever takes its slot.

allowPair

allowPair(a: number, b: number): void

Undo one ignorePair. Doing it to a pair that was never excluded is not an error.

ParameterTypeDescription
anumber
bnumber

pairIgnored

pairIgnored(a: number, b: number): boolean

Whether these two are excluded.

ParameterTypeDescription
anumber
bnumber

removeBody

removeBody(index: number): number

Remove a body, filling its index with the last body — whose index this returns, or −1 when the removed body was the last. Every index past the removed one can change, so a caller keeping body indices follows the returned one; StaticRegions is the worked example.

ParameterTypeDescription
indexnumber

step

step(dt: number): void

Advance one fixed tick.

ParameterTypeDescription
dtnumber

solveIsland

solveIsland(island: number): void

Advance one island through every substep. The executor calls this; nothing else should.

ParameterTypeDescription
islandnumber
More

Integration is over this island's bodies only, which is what makes the call independent of every other island rather than merely ordered against them.

wakeIsland

wakeIsland(index: number): void

Wake a body and everything sharing its island, which is what an external impulse must do.

ParameterTypeDescription
indexnumber

raycast

raycast(ox: number, oy: number, oz: number, dx: number, dy: number, dz: number, maxDistance: number, out: RayHit, filter?: QueryFilter): boolean

The nearest body a ray meets. Fills out and allocates nothing.

ParameterTypeDescription
oxnumber
oynumber
oznumber
dxnumber
dynumber
dznumber
maxDistancenumber
outRayHit
filter?QueryFilter

shapecast

shapecast(shape: ConvexShape, pose: ShapePose, dx: number, dy: number, dz: number, out: RayHit, filter?: QueryFilter): boolean

The first body a swept shape touches.

ParameterTypeDescription
shapeConvexShape
poseShapePose
dxnumber
dynumber
dznumber
outRayHit
filter?QueryFilter

overlap

overlap(shape: ConvexShape, pose: ShapePose, out: Int32Array, filter?: QueryFilter): number

Every body overlapping a shape, filling out to its length. Returns how many were written.

ParameterTypeDescription
shapeConvexShape
poseShapePose
outInt32Array
filter?QueryFilter

applyImpulse

applyImpulse(body: number, px: number, py: number, pz: number, atX: number, atY: number, atZ: number): void

Apply an impulse at a world-space point.

ParameterTypeDescription
bodynumber
pxnumber
pynumber
pznumber
atXnumber
atYnumber
atZnumber
More

The point is not optional, and bindings/core.ts makes it required at the language boundary for the reason AGENTS.md's step four gives: a caller who omits it gets an impulse through the centre of mass, which produces no rotation at all. That is a wrong result rather than an error, and it reads as a broken impulse rather than as a missing argument.

applyForce

applyForce(body: number, fx: number, fy: number, fz: number, dt: number, atX: number, atY: number, atZ: number): void

A force applied for one tick, which is an impulse of force · dt.

ParameterTypeDescription
bodynumber
fxnumber
fynumber
fznumber
dtnumber
atXnumber
atYnumber
atZnumber

setVelocity

setVelocity(body: number, vx: number, vy: number, vz: number): void

Set a body's velocity outright, waking whatever it was resting against.

ParameterTypeDescription
bodynumber
vxnumber
vynumber
vznumber

setPosition

setPosition(body: number, x: number, y: number, z: number): void

Move a body outright, which is a teleport rather than a push.

ParameterTypeDescription
bodynumber
xnumber
ynumber
znumber
More

The broadphase proxy moves with it, or the body would be found where it used to be until it next drifted out of its own fat bounds.

bodyMass

bodyMass(body: number): number

A body's mass, or zero where it has none because it is static or kinematic.

ParameterTypeDescription
bodynumber

sleeping

sleeping(index: number): boolean

Whether a body is currently asleep, for a caller deciding whether to bother.

ParameterTypeDescription
indexnumber