Joint
Present on ctx.joint while the entity's joint component is in force: a hinge, a slide or a weld from this entity's body to another's or to the world.
Null without a joint component, and from the moment the joint is gone — its connected entity despawned, which is how a game breaks a joint on purpose. The coordinate. position is radians about the axis (revolute) or metres along it (prismatic), 0 in the pose the joint was built in — the scene's pose, for a scene's joint — and positive for a right-handed turn about the axis or a slide along it. limits and a position motor's target are in the same coordinate. A fixed joint reads 0. Motors are acceleration-based: stiffness and damping are scaled by the bodies' inertia, so one tuning moves a light door and a heavy gate alike; maxForce is the physical cap. Defaults: velocity mode damping 50, position mode stiffness 100 and damping 20. A motor or limits change is in force from the next physics step (the top of the next tick). Refusals. A NaN or infinite number, a negative maxForce/stiffness/damping, limits with min above max, an unknown mode, or a first motor with no maxForce, throw a RangeError. setMotor, stopMotor and setLimits on a fixed joint, or through a handle kept after its joint went, change nothing, do not throw, and are counted on GET /perf → unwired.joint_ignored. ts // A door that swings to 90° when the player is near and closes when they leave. update(ctx) { const near = ctx.entity.distanceTo(ctx.world.find("player")!) < 2 ctx.joint?.setMotor(near ? Math.PI / 2 : 0, { mode: "position", maxForce: 200 }) }
Signature
export interface Joint {
/**
* Drive the free axis: to a speed (`mode: "velocity"`) or to a place (`mode: "position"`). The mode defaults
* to the current motor's, else velocity; a mode change takes that mode's default stiffness and damping.
*/
setMotor(target: number, options?: JointMotorOptions): void
/** Switch the motor off: the axis is free again, within any limits. */
stopMotor(): void
/** Replace the limits: `[min, max]` in radians or metres from the rest pose, or null for none. */
setLimits(limits: Vec2 | null): void
/** What the joint leaves free; null once the joint is gone. */
readonly kind: JointKind | null
/** The connected entity, or null for a joint to the world (and once the joint is gone). */
readonly connectedTo: EntityHandle | null
/** Radians (revolute) or metres (prismatic) from the pose the joint was built in. */
readonly position: number
/** rad/s or m/s along the free axis. */
readonly velocity: number
/** `[min, max]`, or null for none. */
readonly limits: Vec2 | null
/** The motor, or null for none. */
readonly motor: JointMotorState | null
}
Import: import type { Joint } from "@argus/api"
Members
| Member | Signature | Description |
|---|---|---|
setMotor | setMotor(target: number, options?: JointMotorOptions): void | Drive the free axis: to a speed (mode: "velocity") or to a place (mode: "position"). The mode defaults to the current motor's, else velocity; a mode change takes that mode's default stiffness and damping. |
stopMotor | stopMotor(): void | Switch the motor off: the axis is free again, within any limits. |
setLimits | setLimits(limits: Vec2 | null): void | Replace the limits: [min, max] in radians or metres from the rest pose, or null for none. |
kind | readonly kind: JointKind | null | What the joint leaves free; null once the joint is gone. |
connectedTo | readonly connectedTo: EntityHandle | null | The connected entity, or null for a joint to the world (and once the joint is gone). |
position | readonly position: number | Radians (revolute) or metres (prismatic) from the pose the joint was built in. |
velocity | readonly velocity: number | rad/s or m/s along the free axis. |
limits | readonly limits: Vec2 | null | [min, max], or null for none. |
motor | readonly motor: JointMotorState | null | The motor, or null for none. |
Example
The tested fixture fixtures/host/door.ts.
import type { Behavior } from "@argus/api"
// docs/API.md, "Joints": a door on a hinge that swings open while the player is near and closes
// behind them. Typechecked by packages/api's tests.
export default {
update(ctx) {
const player = ctx.world.find("player")
const near = player !== null && ctx.entity.distanceTo(player) < 2
ctx.joint?.setMotor(near ? Math.PI / 2 : 0, { mode: "position", maxForce: 200 })
},
} satisfies Behavior