Physics2D
APJS Script API reference for the Physics2D class.
| Type | Name | Interface Description |
|---|---|---|
| Variables | gravity: Vector2f | • Function: Global 2D gravity acceleration in m/s^2. Default is (0, -9.8), simulating Earth-like gravity pulling downward. Set to to disable global gravity. Per-body gravity can be controlled via and . Not reset on record start — retains the value you set. |
| Variables | timeSpeed: number | • Function: Scales how fast the 2D physics simulation steps forward. 1.0 runs at normal simulation speed, 0.5 runs in slow motion, and 0.0 stops physics updates. Not reset on record start. |
| Static Functions | raycast2D(ray: Ray, maxDistance: number, nearest: boolean, layerMask?: LayerSet): RaycastHit2D[] | • Function: Casts a ray through the 2D physics world and returns the matching hits. Parameters • • • • Returns Array of . Empty array if nothing was hit. |
Examples
raycast2D(ray: Ray, maxDistance: number, nearest: boolean, layerMask?: LayerSet): RaycastHit2D[]
// Shoot a ray downward from (100, 200) to detect what's below
const ray = new APJS.Ray(new APJS.Vector3f(100, 200, 0), new APJS.Vector3f(0, -1, 0));
const hits = APJS.Physics2D.raycast2D(ray, 50, true);
if (hits.length > 0) {
console.log("Hit at:", hits[0].point);
}
Use Case
Example 1 — Tap-triggered global slow-motion for 2D physics. Sets APJS.Physics2D.timeSpeed = 0.3 for 0.5 s real-time on Touch.Began, then restores to 1.0.
@component()
export class SlowmoController extends APJS.BasicScriptComponent {
@serializeProperty
slowFactor: number = 0.3;
@serializeProperty
durationSeconds: number = 0.5;
@serializeProperty
oneShot: boolean = true;
private touchHandler: ((event: APJS.IEvent) => void) | null = null;
private elapsed: number = 0;
private slowmoActive: boolean = false;
private slowmoEnd: number = 0;
private done: boolean = false;
onStart(): void {
this.touchHandler = (event: APJS.IEvent) => {
const td = event.args[0] as APJS.TouchData;
const canTrigger = td.phase === APJS.TouchPhase.Began
&& !this.slowmoActive
&& (!this.oneShot || !this.done);
if (canTrigger) {
APJS.Physics2D.timeSpeed = this.slowFactor;
this.slowmoActive = true;
this.slowmoEnd = this.elapsed + this.durationSeconds;
}
};
APJS.EventManager.getGlobalEmitter().on(APJS.EventType.Touch, this.touchHandler);
}
onUpdate(dt: number): void {
this.elapsed += dt;
if (this.slowmoActive && this.elapsed >= this.slowmoEnd) {
APJS.Physics2D.timeSpeed = 1.0;
this.slowmoActive = false;
if (this.oneShot) this.done = true;
}
}
onDestroy(): void {
if (this.touchHandler) APJS.EventManager.getGlobalEmitter().off(APJS.EventType.Touch, this.touchHandler);
APJS.Physics2D.timeSpeed = 1.0;
}
}
Example 2 — Play a sound effect when a 2D physics object collides — uses CollisionEvent2D.Enter on collider's object emitter
@component()
export class CollisionSoundEffect extends APJS.BasicScriptComponent {
@serializeProperty
sfxPlayer!: APJS.SceneObject;
private sfxAudio!: APJS.AudioComponent;
private collider!: APJS.BoxCollider2D;
private initialized = false;
private collisionCallback!: (event: APJS.IEvent) => void;
onUpdate(dt: number): void {
if (this.initialized) return;
if (!this.sfxPlayer) return;
this.sfxAudio = this.sfxPlayer.getComponent("AudioComponent") as APJS.AudioComponent;
// Get any 2D collider on this object (BoxCollider2D or CircleCollider2D)
this.collider = this.getSceneObject().getComponent("BoxCollider2D") as APJS.BoxCollider2D;
if (!this.sfxAudio || !this.collider) return;
// CRITICAL: enable collision events before registering listener
this.collider.emitCollisionEvent = true;
this.collisionCallback = (event: APJS.IEvent) => {
// Play SFX on each collision
this.sfxAudio.stop();
this.sfxAudio.loopCount = 1;
this.sfxAudio.play();
};
// Use object emitter on the COLLIDER (not global emitter)
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.on(APJS.CollisionEvent2D.Enter, this.collisionCallback, this);
this.initialized = true;
}
onDestroy(): void {
if (this.collider && this.collisionCallback) {
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.off(APJS.CollisionEvent2D.Enter, this.collisionCallback, this);
}
}
}