@rpgjs/physic
Version:
A deterministic 2D top-down physics library for RPG, sandbox and MMO games
338 lines • 10.1 kB
TypeScript
import { World, WorldConfig } from '../world/World';
import { Entity, EntityConfig } from '../physics/Entity';
import { RegionManager, RegionManagerConfig } from '../region/RegionManager';
import { EventSystem } from '../world/events';
import { Vector2 } from '../core/math/Vector2';
import { AABB } from '../core/math/AABB';
import { PolygonConfig } from '../collision/PolygonCollider';
import { RaycastHit } from '../collision/raycast';
import { SweepResult } from '../collision/sweep';
import { MovementManager } from '../movement/MovementManager';
import { ZoneManager } from './ZoneManager';
/**
* Physics engine configuration
*/
export interface PhysicsEngineConfig extends WorldConfig {
/** Enable region-based simulation (default: false) */
enableRegions?: boolean;
/** Region manager configuration (required if enableRegions is true) */
regionConfig?: RegionManagerConfig;
}
/**
* Main physics engine interface
*
* Provides a high-level, gameplay-oriented API for physics simulation.
* Supports both single-world and multi-region simulation modes.
*
* @example
* ```typescript
* const engine = new PhysicsEngine({ timeStep: 1/60 });
* const entity = engine.createEntity({
* position: { x: 0, y: 0 },
* radius: 10,
* mass: 1
* });
*
* engine.step();
* ```
*/
export declare class PhysicsEngine {
private world;
private regionManager;
private useRegions;
private movementManager;
private zoneManager;
private tick;
/**
* Creates a new physics engine
*
* @param config - Engine configuration
*/
constructor(config?: PhysicsEngineConfig);
/**
* Gets the movement manager bound to this engine.
*
* The manager is lazily created and reused.
*
* @returns Movement manager instance
*/
getMovementManager(): MovementManager;
/**
* Gets the zone manager bound to this engine.
*
* The manager is lazily created and reused. Zones allow detecting entities
* within circular or cone-shaped areas without physical collisions (useful
* for vision, skill ranges, explosions, etc.).
*
* **Important:** Call `zoneManager.update()` after each physics step to
* keep zones synchronized:
*
* ```typescript
* engine.step();
* engine.getZoneManager().update();
* ```
*
* @returns Zone manager instance
*
* @example
* ```typescript
* const zones = engine.getZoneManager();
* const visionZone = zones.createAttachedZone(player, {
* radius: 100,
* angle: 90,
* direction: 'right',
* }, {
* onEnter: (entities) => console.log('Player sees:', entities),
* });
*
* engine.step();
* zones.update();
* ```
*/
getZoneManager(): ZoneManager;
/**
* Updates all registered movement strategies.
*
* @param dt - Time delta in seconds (defaults to the world's time step)
*/
updateMovements(dt?: number): void;
/**
* Updates movements and then steps the simulation.
*
* @param dt - Time delta in seconds (defaults to the world's time step)
*/
stepWithMovements(dt?: number): void;
/**
* Advances the simulation by exactly one fixed tick.
*
* This helper is equivalent to {@link step} but returns the tick index after the step,
* making it convenient for client-side prediction loops.
*
* @returns Current tick index after stepping
*/
stepOneTick(): number;
/**
* Advances the simulation by a fixed number of ticks.
*
* @param ticks - Number of ticks to simulate (>= 1)
* @returns Current tick index after stepping
*/
stepTicks(ticks: number): number;
/**
* Creates a new entity
*
* @param config - Entity configuration
* @returns Created entity
*
* @example
* ```typescript
* const entity = engine.createEntity({
* position: { x: 100, y: 100 },
* radius: 15,
* mass: 1,
* velocity: { x: 5, y: 0 }
* });
* ```
*/
createEntity(config: EntityConfig): Entity;
/**
* Adds an existing entity to the engine
*
* @param entity - Entity to add
* @returns The added entity
*/
addEntity(entity: Entity): Entity;
/**
* Removes an entity from the engine
*
* @param entity - Entity to remove
*/
removeEntity(entity: Entity): void;
/**
* Gets all entities
*
* @returns Array of all entities
*/
getEntities(): Entity[];
/**
* Gets an entity by UUID
*
* @param uuid - Entity UUID
* @returns Entity or undefined
*/
getEntityByUUID(uuid: string): Entity | undefined;
/**
* Steps the physics simulation forward
*
* Updates all entities, detects and resolves collisions.
*/
step(): void;
/**
* Gets the event system
*
* @returns Event system instance
*/
getEvents(): EventSystem;
/**
* Applies a force to an entity
*
* @param entity - Entity to apply force to
* @param force - Force vector
*/
applyForce(entity: Entity, force: Vector2): void;
/**
* Applies an impulse to an entity
*
* @param entity - Entity to apply impulse to
* @param impulse - Impulse vector
*/
applyImpulse(entity: Entity, impulse: Vector2): void;
/**
* Teleports an entity to a new position
*
* @param entity - Entity to teleport
* @param position - New position
*/
teleport(entity: Entity, position: Vector2 | {
x: number;
y: number;
}): void;
/**
* Freezes an entity (makes it static)
*
* @param entity - Entity to freeze
*/
freeze(entity: Entity): void;
/**
* Unfreezes an entity (makes it dynamic)
*
* @param entity - Entity to unfreeze
*/
unfreeze(entity: Entity): void;
/**
* Queries entities in an AABB region
*
* @param bounds - AABB to query
* @returns Array of entities in the region
*/
queryAABB(bounds: AABB): Entity[];
/**
* Clears all entities from the engine
*/
clear(): void;
/**
* Assigns a polygon collider to an entity (supports convex or concave via convex parts).
*
* Design: the collider is attached via a registry and used by the detector on demand.
* This keeps entities lightweight and preserves the separation of detection/resolution.
*
* @param entity - Target entity
* @param config - Polygon configuration
* @example
* ```typescript
* engine.assignPolygonCollider(entity, { vertices: [new Vector2(-1,-1), new Vector2(1,-1), new Vector2(1,1), new Vector2(-1,1)], isConvex: true });
* ```
*/
assignPolygonCollider(entity: Entity, config: PolygonConfig): void;
/**
* Casts a ray in the physics world and returns the nearest hit, if any.
* Uses the world's spatial partition for broad-phase and shape-specific narrow-phase tests.
*
* @param origin - Ray origin
* @param direction - Ray direction (any length)
* @param maxDistance - Maximum cast length
* @param mask - Optional collision mask (layer)
* @param filter - Optional filter function (return true to include entity)
* @returns Raycast hit or null
* @example
* ```typescript
* const hit = engine.raycast(new Vector2(0,0), new Vector2(1,0), 1000);
* ```
*/
raycast(origin: Vector2, direction: Vector2, maxDistance: number, mask?: number, filter?: (entity: Entity) => boolean): RaycastHit | null;
/**
* Computes continuous collision detection (sweep test) time-of-impact between two entities
* over the next step of duration `dt`, using relative motion.
*
* @param a - First entity
* @param b - Second entity
* @param dt - Time step duration
* @returns Sweep result or null if no hit in [0,1]
* @example
* ```typescript
* const toi = engine.sweep(entityA, entityB, 1/60);
* if (toi) {
* // pre-resolve or clamp motion
* }
* ```
*/
sweep(a: Entity, b: Entity, dt: number): SweepResult | null;
/**
* Gets statistics about the engine
*
* @returns Statistics object
*/
getStats(): {
totalEntities: number;
dynamicEntities: number;
staticEntities: number;
sleepingEntities: number;
regions?: {
total: number;
active: number;
};
};
/**
* Gets the underlying world instance
*
* @returns World instance
*/
getWorld(): World;
/**
* Gets the current simulation tick.
*
* @returns Tick counter (starts at 0 and increments after each {@link step})
*/
getTick(): number;
/**
* Captures a lightweight snapshot of the current world state.
*
* The snapshot only stores the minimum data required for client-side prediction:
* position, velocity, rotation, angular velocity and sleeping flag per entity.
*
* @returns Snapshot object
*/
takeSnapshot(): PhysicsSnapshot;
/**
* Restores a snapshot previously produced by {@link takeSnapshot}.
*
* Entities that cannot be found in the current engine are skipped silently.
*
* @param snapshot - Snapshot to restore
*/
restoreSnapshot(snapshot: PhysicsSnapshot): void;
/**
* Gets the region manager (if regions are enabled)
*
* @returns Region manager or null
*/
getRegionManager(): RegionManager | null;
}
export interface PhysicsSnapshot {
tick: number;
entities: Array<{
uuid: string;
position: {
x: number;
y: number;
};
velocity: {
x: number;
y: number;
};
rotation: number;
angularVelocity: number;
sleeping: boolean;
}>;
}
//# sourceMappingURL=PhysicsEngine.d.ts.map