@rpgjs/physic
Version:
A deterministic 2D top-down physics library for RPG, sandbox and MMO games
211 lines • 6.56 kB
TypeScript
import { Entity, EntityConfig } from '../physics/Entity';
import { IntegrationMethod } from '../physics/integrator';
import { EventSystem } from './events';
import { SpatialPartition } from './SpatialPartition';
import { Vector2 } from '../core/math/Vector2';
import { RaycastHit } from '../collision/Ray';
/**
* World configuration
*/
export interface WorldConfig {
/** Time step for simulation (default: 1/60 for 60 FPS) */
timeStep?: number;
/** Integration method (default: Euler) */
integrationMethod?: IntegrationMethod;
/** Gravity vector (default: zero for top-down) */
gravity?: Vector2;
/** Spatial partition cell size (default: 100) */
spatialCellSize?: number;
/** Spatial partition grid width (default: 100) */
spatialGridWidth?: number;
/** Spatial partition grid height (default: 100) */
spatialGridHeight?: number;
/** Enable sleep for inactive entities (default: true) */
enableSleep?: boolean;
/** Tile width for grid-based logic (default: 32) */
tileWidth?: number;
/** Tile height for grid-based logic (default: 32) */
tileHeight?: number;
/** Sleep threshold in seconds (default: 0.5) */
sleepThreshold?: number;
/** Velocity threshold for sleep detection (default: 0.01) */
sleepVelocityThreshold?: number;
/** Custom spatial partition (optional) */
spatialPartition?: SpatialPartition;
/**
* Optional quantization step (world units) applied to positions after every tick.
* Set to a positive number (e.g. 1/16) to reduce floating point drift for networking.
*/
positionQuantizationStep?: number;
/**
* Optional quantization step (world units / second) applied to velocities after every tick.
* Set to a positive number (e.g. 1/256) to enforce deterministic clamps.
*/
velocityQuantizationStep?: number;
/**
* Number of collision-resolution iterations per tick (default: 3).
* Higher values further reduce interpenetration in crowded scenes.
*/
resolverIterations?: number;
/** Custom collision resolver factor controlling how aggressively overlaps are corrected. */
positionCorrectionFactor?: number;
/** Maximum positional correction applied per iteration (world units). */
maxPositionCorrection?: number;
/** Minimum penetration depth before a collision is resolved. */
minPenetrationDepth?: number;
}
/**
* Physics world
*
* Manages entities, physics simulation, collisions, and events.
*
* @example
* ```typescript
* const world = new World({ timeStep: 1/60 });
* const entity = world.addEntity({ position: { x: 0, y: 0 }, radius: 10 });
* world.step();
* ```
*/
export declare class World {
private entities;
private staticEntities;
private dynamicEntities;
private integrator;
private resolver;
private spatialPartition;
private events;
private timeStep;
private enableSleep;
private tileWidth;
private tileHeight;
private sleepThreshold;
private sleepVelocityThreshold;
private previousCollisions;
private queryResults;
private readonly positionQuantizationStep;
private readonly velocityQuantizationStep;
private readonly resolverIterations;
/**
* Creates a new physics world
*
* @param config - World configuration
*/
constructor(config?: WorldConfig);
/**
* Gets the event system
*
* @returns Event system instance
*/
getEvents(): EventSystem;
/**
* Returns the fixed simulation time step.
*
* @returns Time step in seconds
*/
getTimeStep(): number;
/**
* Adds an entity to the world
*
* @param entity - Entity to add
* @returns The added entity
*/
addEntity(entity: Entity): Entity;
/**
* Performs a raycast against all entities in the world.
*
* @param origin - Starting point of the ray
* @param direction - Direction of the ray (normalized)
* @param length - Maximum length (default: Infinity)
* @param mask - Optional collision mask (layer)
* @param filter - Optional filter function (return true to include entity)
* @returns Raycast hit info if hit, null otherwise
*/
raycast(origin: Vector2, direction: Vector2, length?: number, mask?: number, filter?: (entity: Entity) => boolean): RaycastHit | null;
/**
* Creates and adds a new entity
*
* @param config - Entity configuration
* @returns Created entity
*/
createEntity(config: EntityConfig): Entity;
/**
* Removes an entity from the world
*
* @param entity - Entity to remove
*/
removeEntity(entity: Entity): void;
/**
* Gets all entities in the world
*
* @returns Array of 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;
/**
* Detects collisions using spatial partition
*
* @returns Array of collision infos
*/
/**
* Detects collisions using spatial partition
*
* @returns Array of collision infos
*/
private detectCollisions;
private sortCollisionsForDeterminism;
private getCollisionKey;
/**
* Handles collision enter/exit events
*
* @param collisions - Current frame collisions
*/
private handleCollisionEvents;
/**
* Updates sleep state for entities
*/
private updateSleepState;
/**
* Clears all entities from the world
*/
clear(): void;
private quantizeEntities;
private quantizeValue;
private refreshDynamicEntitiesInPartition;
/**
* Gets statistics about the world
*
* @returns Statistics object
*/
getStats(): {
totalEntities: number;
dynamicEntities: number;
staticEntities: number;
sleepingEntities: number;
};
/**
* Performs Continuous Collision Detection (CCD) for an entity
*
* @param entity - Entity to check
*/
/**
* Updates entity tile position and triggers hooks
*
* @param entity - Entity to update
* @param previousPosition - Position before integration
*/
private updateEntityTile;
private performCCD;
}
//# sourceMappingURL=World.d.ts.map