@daneren2005/shared-memory-physics 1.7.3 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +125 -2
  2. package/dist/actions/add-physical-world-data.d.ts +2 -0
  3. package/dist/actions/combine-dynamics-commands.d.ts +2 -0
  4. package/dist/{systems/dynamics.d.ts → actions/dynamics-commands.d.ts} +1 -7
  5. package/dist/actions/find-dynamics-command-offset.d.ts +2 -0
  6. package/dist/actions/find-dynamics-command.d.ts +2 -0
  7. package/dist/actions/get-spatial-map.d.ts +3 -0
  8. package/dist/actions/integrate-dynamics.d.ts +3 -0
  9. package/dist/actions/queue-dynamics-vector.d.ts +2 -0
  10. package/dist/actions/queue-velocity-assignment.d.ts +2 -0
  11. package/dist/actions/set-entity-position.d.ts +7 -0
  12. package/dist/actions/snap-entity.d.ts +9 -0
  13. package/dist/actions/start-spawn-interpolation.d.ts +16 -0
  14. package/dist/actions/update-spatial-map.d.ts +3 -0
  15. package/dist/components/body-component-constants.d.ts +15 -0
  16. package/dist/components/body-component.d.ts +0 -15
  17. package/dist/components/bounciness-component-constants.d.ts +2 -0
  18. package/dist/components/bounciness-component.d.ts +0 -2
  19. package/dist/components/dynamics-component-constants.d.ts +4 -0
  20. package/dist/components/dynamics-component.d.ts +0 -4
  21. package/dist/components/interpolation-component-constants.d.ts +18 -0
  22. package/dist/components/interpolation-component.d.ts +0 -40
  23. package/dist/components/navigation-component-constants.d.ts +11 -0
  24. package/dist/components/navigation-component.d.ts +31 -0
  25. package/dist/components/polygon-component-constants.d.ts +4 -0
  26. package/dist/components/polygon-component.d.ts +0 -4
  27. package/dist/components/registry.d.ts +9 -0
  28. package/dist/components/transform-component-constants.d.ts +6 -0
  29. package/dist/components/transform-component.d.ts +0 -6
  30. package/dist/components/velocity-component-constants.d.ts +4 -0
  31. package/dist/components/velocity-component.d.ts +0 -4
  32. package/dist/constants.d.ts +5 -0
  33. package/dist/index.d.ts +48 -17
  34. package/dist/index.js +1156 -420
  35. package/dist/index.js.map +1 -1
  36. package/dist/pathfinding/follow-path.d.ts +9 -0
  37. package/dist/pathfinding/grid-a-star.d.ts +29 -0
  38. package/dist/pathfinding/line-of-sight.d.ts +2 -0
  39. package/dist/pathfinding/min-heap.d.ts +14 -0
  40. package/dist/pathfinding/nav-grid.d.ts +42 -0
  41. package/dist/pathfinding/navigation-state.d.ts +20 -0
  42. package/dist/pathfinding/path-blockers.d.ts +29 -0
  43. package/dist/pathfinding/path-search.d.ts +27 -0
  44. package/dist/pathfinding/pathfinding-system.d.ts +27 -0
  45. package/dist/pathfinding/pathfinding-update.d.ts +36 -0
  46. package/dist/pathfinding/smooth-path.d.ts +3 -0
  47. package/dist/systems/collision.d.ts +1 -2
  48. package/dist/systems/interpolation-update.d.ts +0 -2
  49. package/dist/systems/physics-system.d.ts +4 -5
  50. package/dist/systems/physics-update.d.ts +2 -5
  51. package/dist/world.d.ts +0 -2
  52. package/package.json +3 -3
package/README.md CHANGED
@@ -7,7 +7,7 @@ reads positions straight off its entities.
7
7
 
8
8
  Examples at https://daneren2005.github.io/shared-memory-physics/
9
9
 
10
- The ECS (`>=1.1.1`) and the shared-memory primitives it is built on are **peer dependencies**: a game must
10
+ The ECS (`>=1.10.0`) and the shared-memory primitives it is built on are **peer dependencies**: a game must
11
11
  register these components against the same copy of the ECS it builds its world with.
12
12
 
13
13
  ```sh
@@ -23,6 +23,7 @@ npm install @daneren2005/shared-memory-physics @daneren2005/shared-memory-ecs @d
23
23
  | `velocity` | – | `velocityX?`, `velocityY?`, `damping?` | `Float32Array` – world units per second |
24
24
  | `body` | `shape?`, `collideCategory?`, `collideMask?`, `sensor?`, `continuousCollisionDetection?`, `blocksPath?` | – | `Uint32Array` – what shape, what collides with |
25
25
  | `interpolation` | `interpolate` | – | `Float32Array` – where to *draw* it |
26
+ | `navigation` | `navigate` | – | `Int32Array` – a goal and the path to it ([Pathfinding](#pathfinding)) |
26
27
 
27
28
  Entity configs are flat and shared across every component, so velocity is keyed as `velocityX` / `velocityY`
28
29
  rather than `x` / `y` (which already belong to the transform). Either velocity axis on its own is enough to
@@ -844,6 +845,21 @@ box around their actual outline. A direct transform/body edit outside the physic
844
845
  `world.updateSpatialEntity(entity)`. A custom physics wrapper that changes a transform after calling the library
845
846
  update can call `updateSpatialMap(workerWorld, entityId, components)` instead.
846
847
 
848
+ For absolute placement from a worker update or an in-process update, `setEntityPosition` writes both coordinates
849
+ and refreshes the shared index immediately on the calling thread:
850
+
851
+ ```ts
852
+ import { setEntityPosition } from '@daneren2005/shared-memory-physics';
853
+
854
+ setEntityPosition(workerWorld, { entityId, components }, { x: 300, y: 400 });
855
+ ```
856
+
857
+ It accepts raw query/update blocks, ignores entities without a transform, and uses the optional body for
858
+ shape-aware bounds. Each coordinate is stored atomically; the position and index update are not one transaction.
859
+ It performs no collision sweep and does not change velocity or interpolation. For an interpolated teleport,
860
+ reset the render state separately with `snapEntity` on the entity wrapper. Without a spatial map in the run
861
+ world, it only writes the transform. Share the map with custom workers as described below.
862
+
847
863
  Games with registered ECS wrapper classes can pass their entity union as `PhysicalWorld`'s second generic. The
848
864
  world's entity map, lifecycle callbacks, and spatial-query results then retain that union instead of widening to
849
865
  `BaseEntity`.
@@ -895,9 +911,111 @@ ask it directly rather than building the sort yourself - it settles as soon as t
895
911
  measured to an entity's **box**, not to its centre, so a large target is as near as its nearest edge and
896
912
  `maxDistance` reads as a range past the hull.
897
913
 
914
+ ## Pathfinding
915
+
916
+ Grid pathfinding for movers that need to walk around walls and buildings: an A* over tiles, run on a worker,
917
+ answering requests written into a `navigation` component. Bodies flagged `blocksPath` are the walls. The physics
918
+ still does the moving; the game reads the path back and steers velocity along it.
919
+
920
+ Register `navigationRegistry` beside `physicsRegistry`, and give movers a `navigate: true` tag:
921
+
922
+ ```ts
923
+ import { navigationRegistry, physicsRegistry, PathfindingSystem } from '@daneren2005/shared-memory-physics';
924
+
925
+ const world = new PhysicalWorld({ ...physicsRegistry, ...navigationRegistry, ...gameRegistry });
926
+ world.addSystem(new PathfindingSystem(world, {
927
+ getInitData: () => ({ tilesWide: 128, tilesHigh: 128, cellSize: 32 }),
928
+ getWorker: () => new Worker(new URL('./pathfinding.worker.ts', import.meta.url), { type: 'module' }),
929
+ }));
930
+
931
+ world.loadEntity({ x: 48, y: 48, width: 32, height: 32, blocksPath: true }); // a wall
932
+ const villager = world.loadEntity({ x: 16, y: 16, width: 24, height: 24, navigate: true });
933
+ villager.components.navigation!.navigateTo(400, 300);
934
+ ```
935
+
936
+ The grid's `(0, 0)` is the world's top-left corner and anything off it is blocked. A worker file is the same two
937
+ lines as physics', handing `createEntitySystemWorker` the update the system was given (`pathfindingUpdate` by default).
938
+
939
+ ### The navigation block
940
+
941
+ Everything is in the mover's `navigation` block (an `Int32Array`), so any thread can set a goal or read a path:
942
+
943
+ | Call | Does |
944
+ | --- | --- |
945
+ | `navigateTo(block, x, y)` | Sets the goal, marks the mover active and asks for a path |
946
+ | `setNavigationGoal(block, x, y)` | Moves the goal without searching again; the last leg bends to it |
947
+ | `requestPath(block)` | Searches again for the current goal |
948
+ | `stopNavigating(block)` | Marks the mover inactive, so it is neither searched for nor rechecked |
949
+ | `isPathPending(block)` / `isUnreachable(block)` | Whether an answer is still coming / settled as no way there |
950
+ | `followPath(block, x, y, arriveDistance, target)` | Follower bookkeeping, below |
951
+
952
+ A request is pending while its request id is ahead of its result id; the update writes waypoints and outcome
953
+ first and the result id last, so a settled path is never read half written. Up to `NAVIGATION_MAX_WAYPOINTS` (32)
954
+ waypoints fit; a longer path is cut short and marked `PathStatus.Incomplete`. Goals and paths are transient: whoever
955
+ set a goal sets it again after a load.
956
+
957
+ `followPath` is what a movement system calls each step. It skips waypoints within `arriveDistance`, writes the next
958
+ point to head for into `target` (no allocation) and says what kind it is:
959
+
960
+ ```ts
961
+ const step = followPath(navigation, x, y, 1, target);
962
+ if(step === FollowStep.Waypoint || step === FollowStep.Goal) {
963
+ steerToward(target);
964
+ } else {
965
+ halt(); // Waiting for a path, or Stuck at the closest reachable spot
966
+ }
967
+ ```
968
+
969
+ At the end of an incomplete path it asks for the rest itself and reports `Waiting`.
970
+
971
+ ### What the update does
972
+
973
+ - Only **active** movers with a pending request are searched. Searching is budgeted per run in A* tiles
974
+ (`iterationBudget`, default `DEFAULT_PATH_SEARCH_ITERATION_BUDGET`), not wall-clock time, so a run plays out the
975
+ same on any machine; the first search of a run always goes ahead and the rest wait for the next run. The
976
+ budget is fixed when the update is built, but `PathfindingSystem`'s `iterationBudget` (a config option and a live
977
+ field) overrides it from the next run on - say, a larger one when the system is on a worker, where searching
978
+ costs no frame time. In-process, every tile of budget is main-thread time inside `world.update`.
979
+ - Blockers are assumed never to move. Each is rasterised into the grid when it joins the `pathBlockers` query and
980
+ cleared when it leaves, and a new one re-paths only movers whose remaining path it crosses.
981
+ - A mover standing inside a blocker (a bed built around a sleeper) searches as if that blocker were not there, so it
982
+ walks out rather than being relocated past a wall.
983
+ - Paths are smoothed (string pulled) where the straight line is clear and no slower. A mover is placed by its
984
+ footprint, so one bigger than a tile only fits gaps its whole box fits.
985
+
986
+ ### Configuring it
987
+
988
+ `createPathfindingUpdate` builds the update both backends run. Hooks are baked in because functions do not
989
+ survive `postMessage`:
990
+
991
+ ```ts
992
+ export const pathfindingUpdate = createPathfindingUpdate<Components, PathfindingUpdateComponents, GameWorld>({
993
+ search: new GridAStar({ diagonal: true }),
994
+ // Bodies in these categories stop only movers whose collide mask takes them in, e.g. doors animals cannot open.
995
+ gateCategories: DOOR,
996
+ init(navigation, data, queries) {
997
+ // Feed terrain in: 1.5 for a road, 0.5 for mud.
998
+ setNavigationTerrainSpeed(navigation, 3, 4, 1.5);
999
+ },
1000
+ queryChanged(world, queryName, delta) { /* the game's extra queries */ },
1001
+ preRun(world) { /* per-run upkeep */ },
1002
+ });
1003
+ ```
1004
+
1005
+ Pass it to `PathfindingSystem` as `updateFunction`, along with `blockers: { not: ['construction'] }` (or a `filter`)
1006
+ to narrow what counts as a blocker, `queries` for the hooks' own data, and `optional` for extra mover components.
1007
+ Another system wanting the same view of the world (say, finding enclosed pens) can build matching queries with
1008
+ `pathBlockerQueries` and keep its own `NavGrid` with `applyRectChanges`.
1009
+
1010
+ Gates get a grid per set of gate categories a mover's mask takes in, cloned from the blockers grid the first time
1011
+ such a mover searches, so gates nobody collides with cost nothing.
1012
+
1013
+ The search itself is swappable: anything implementing `PathSearch` (`findPath(grid, request)`) can be passed as
1014
+ `search`. `NavGrid`, `GridAStar`, `sweepCost` and `smoothPath` are exported for use on their own too.
1015
+
898
1016
  ## Examples
899
1017
 
900
- Three runnable examples live in [`examples/`](./examples), rendered with [Phaser](https://phaser.io) (a dev
1018
+ Runnable examples live in [`examples/`](./examples), rendered with [Phaser](https://phaser.io) (a dev
901
1019
  dependency - it is not part of the library) and driven by plain HTML controls beside the canvas:
902
1020
 
903
1021
  ```sh
@@ -912,6 +1030,11 @@ npm start # http://127.0.0.1:8080
912
1030
  them in turn. It starts on a deliberately long 100ms physics step, so turning **interpolate rendering** off is
913
1031
  a direct before-and-after on the same running scene: the same simulation, drawn six frames at a time instead
914
1032
  of one.
1033
+ - **Pathfinding** - click to send a square through a scene built to show each pathfinding case: a U-shaped trap,
1034
+ a gap only small movers fit, mud and road terrain, round and angled blockers, and a door only some movers can
1035
+ open. Toggle diagonal movement and smoothing, resize the mover, and add walls or paint terrain while it walks.
1036
+ - **Pathfinding stress** - thousands of movers wandering between random goals through hundreds of obstacles, with
1037
+ obstacle churn re-pathing whoever a new wall crosses, and per-worker timings in the stats panel.
915
1038
 
916
1039
  Every page has a **physics step** slider (starting at the library's own 50ms) and an **interpolate rendering**
917
1040
  toggle, so the trade the [interpolation section](#interpolation) describes can be looked at rather than
@@ -0,0 +1,2 @@
1
+ import type { PhysicalWorldSource, PhysicalWorldData } from '../world';
2
+ export declare function addPhysicalWorldData(source: PhysicalWorldSource, target: PhysicalWorldData): void;
@@ -0,0 +1,2 @@
1
+ import type { DynamicsCommand, DynamicsCommands } from './dynamics-commands';
2
+ export declare function combineDynamicsCommands(queued: ReadonlyMap<number, Omit<DynamicsCommand, 'entityId'>>, incoming: DynamicsCommands | undefined): DynamicsCommands | undefined;
@@ -34,10 +34,4 @@ export interface DynamicsWorld {
34
34
  elapsedTime: number;
35
35
  dynamicsCommands?: DynamicsCommands;
36
36
  }
37
- export declare function queueDynamicsVector(commands: PendingDynamicsCommands, entityId: number, forceX: number, forceY: number, impulseX: number, impulseY: number): void;
38
- export declare function queueVelocityAssignment(commands: PendingDynamicsCommands, entityId: number, velocity: VelocityAssignment): void;
39
- export declare function combineDynamicsCommands(queued: ReadonlyMap<number, Omit<DynamicsCommand, 'entityId'>>, incoming: DynamicsCommands | undefined): DynamicsCommands | undefined;
40
- export declare function integrateDynamics(world: DynamicsWorld, entityId: number, velocity: Float32Array, dynamics?: Float32Array): void;
41
- export declare function findDynamicsCommand(commands: ReadonlyArray<DynamicsCommand> | undefined, entityId: number): DynamicsCommand | undefined;
42
- export declare function findDynamicsCommandOffset(commands: DynamicsCommandBuffer, entityId: number): number;
43
- export default integrateDynamics;
37
+ export declare function emptyCommand(): Omit<DynamicsCommand, 'entityId'>;
@@ -0,0 +1,2 @@
1
+ import type { DynamicsCommandBuffer } from './dynamics-commands';
2
+ export declare function findDynamicsCommandOffset(commands: DynamicsCommandBuffer, entityId: number): number;
@@ -0,0 +1,2 @@
1
+ import type { DynamicsCommand } from './dynamics-commands';
2
+ export declare function findDynamicsCommand(commands: ReadonlyArray<DynamicsCommand> | undefined, entityId: number): DynamicsCommand | undefined;
@@ -0,0 +1,3 @@
1
+ import SharedSpatialMap from '@daneren2005/shared-memory-objects/spatial/shared-spatial-map';
2
+ import type { PhysicalSystemWorld } from '../world';
3
+ export declare function getSpatialMap(world: PhysicalSystemWorld): SharedSpatialMap;
@@ -0,0 +1,3 @@
1
+ import type { DynamicsWorld } from './dynamics-commands';
2
+ export declare function integrateDynamics(world: DynamicsWorld, entityId: number, velocity: Float32Array, dynamics?: Float32Array): void;
3
+ export default integrateDynamics;
@@ -0,0 +1,2 @@
1
+ import type { PendingDynamicsCommands } from './dynamics-commands';
2
+ export declare function queueDynamicsVector(commands: PendingDynamicsCommands, entityId: number, forceX: number, forceY: number, impulseX: number, impulseY: number): void;
@@ -0,0 +1,2 @@
1
+ import type { PendingDynamicsCommands, VelocityAssignment } from './dynamics-commands';
2
+ export declare function queueVelocityAssignment(commands: PendingDynamicsCommands, entityId: number, velocity: VelocityAssignment): void;
@@ -0,0 +1,7 @@
1
+ import type { EntityUpdateComponents } from '@daneren2005/shared-memory-ecs/worker';
2
+ import type { Vector } from '../math/shapes';
3
+ import type { PhysicalSystemWorld } from '../world';
4
+ export declare function setEntityPosition(world: PhysicalSystemWorld, entity: {
5
+ entityId: number;
6
+ components: EntityUpdateComponents;
7
+ }, position: Vector): void;
@@ -0,0 +1,9 @@
1
+ import type { TransformComponent } from '../components/transform-component';
2
+ import type { InterpolationComponent } from '../components/interpolation-component';
3
+ export interface SnappableEntity {
4
+ components: {
5
+ transform?: TransformComponent;
6
+ interpolation?: InterpolationComponent;
7
+ };
8
+ }
9
+ export declare function snapEntity(entity: SnappableEntity): void;
@@ -0,0 +1,16 @@
1
+ import type { TransformComponent } from '../components/transform-component';
2
+ import type { VelocityComponent } from '../components/velocity-component';
3
+ import type { InterpolationComponent } from '../components/interpolation-component';
4
+ export interface SpawnableEntity {
5
+ components: {
6
+ transform?: TransformComponent;
7
+ velocity?: VelocityComponent;
8
+ interpolation?: InterpolationComponent;
9
+ };
10
+ }
11
+ export interface SpawnInterpolationOptions {
12
+ stepMs: number;
13
+ stepFraction: number;
14
+ tick: number;
15
+ }
16
+ export declare function startSpawnInterpolation(entity: SpawnableEntity, options: SpawnInterpolationOptions): void;
@@ -0,0 +1,3 @@
1
+ import { type SpatialBlockComponents } from '../systems/spatial-bounds';
2
+ import type { PhysicalSystemWorld } from '../world';
3
+ export declare function updateSpatialMap(world: PhysicalSystemWorld, entityId: number, components: SpatialBlockComponents): void;
@@ -0,0 +1,15 @@
1
+ export declare const SHAPE_RECTANGLE = 1;
2
+ export declare const SHAPE_CIRCLE = 2;
3
+ export declare const SHAPE_CAPSULE = 3;
4
+ export declare const SHAPE_POLYGON = 4;
5
+ export declare const DEFAULT_COLLIDE_CATEGORY = 1;
6
+ export declare const DEFAULT_COLLIDE_MASK = 4294967295;
7
+ export declare const BODY_FLAGS_INDEX = 0;
8
+ export declare const BODY_CATEGORY_INDEX = 1;
9
+ export declare const BODY_MASK_INDEX = 2;
10
+ export declare const BODY_SIZE = 3;
11
+ export declare const BODY_SHAPE_MASK = 7;
12
+ export declare const BODY_SENSOR_FLAG = 8;
13
+ export declare const BODY_CCD_FLAG = 16;
14
+ export declare const BODY_DYING_FLAG = 32;
15
+ export declare const BODY_BLOCKS_PATH_FLAG = 64;
@@ -9,12 +9,6 @@ export interface BodyComponent {
9
9
  continuousCollisionDetection: boolean;
10
10
  blocksPath: boolean;
11
11
  }
12
- export declare const SHAPE_RECTANGLE = 1;
13
- export declare const SHAPE_CIRCLE = 2;
14
- export declare const SHAPE_CAPSULE = 3;
15
- export declare const SHAPE_POLYGON = 4;
16
- export declare const DEFAULT_COLLIDE_CATEGORY = 1;
17
- export declare const DEFAULT_COLLIDE_MASK = 4294967295;
18
12
  export declare function canCollide(categoryA: number, maskA: number, categoryB: number, maskB: number): boolean;
19
13
  export interface BodyConfig {
20
14
  width?: number;
@@ -28,15 +22,6 @@ export interface BodyConfig {
28
22
  continuousCollisionDetection?: boolean;
29
23
  blocksPath?: boolean;
30
24
  }
31
- export declare const BODY_FLAGS_INDEX = 0;
32
- export declare const BODY_CATEGORY_INDEX = 1;
33
- export declare const BODY_MASK_INDEX = 2;
34
- export declare const BODY_SIZE = 3;
35
- export declare const BODY_SHAPE_MASK = 7;
36
- export declare const BODY_SENSOR_FLAG = 8;
37
- export declare const BODY_CCD_FLAG = 16;
38
- export declare const BODY_DYING_FLAG = 32;
39
- export declare const BODY_BLOCKS_PATH_FLAG = 64;
40
25
  export declare function bodyShape(body: Uint32Array): number;
41
26
  export declare function isSensor(body: Uint32Array): boolean;
42
27
  export declare function isContinuous(body: Uint32Array): boolean;
@@ -0,0 +1,2 @@
1
+ export declare const BOUNCINESS_INDEX = 0;
2
+ export declare const BOUNCINESS_SIZE = 1;
@@ -6,7 +6,5 @@ export interface BouncinessComponent {
6
6
  export interface BouncinessConfig {
7
7
  bounciness?: number;
8
8
  }
9
- export declare const BOUNCINESS_INDEX = 0;
10
- export declare const BOUNCINESS_SIZE = 1;
11
9
  export declare const bouncinessDefinition: ComponentDefinition<BouncinessComponent, Float32Array, BouncinessConfig>;
12
10
  export default bouncinessDefinition;
@@ -0,0 +1,4 @@
1
+ export declare const DYNAMICS_ACCELERATION_X_INDEX = 0;
2
+ export declare const DYNAMICS_ACCELERATION_Y_INDEX = 1;
3
+ export declare const DYNAMICS_INVERSE_MASS_INDEX = 2;
4
+ export declare const DYNAMICS_SIZE = 3;
@@ -11,9 +11,5 @@ export interface DynamicsConfig {
11
11
  mass?: number;
12
12
  }
13
13
  export type DynamicsSerialization = DynamicsConfig;
14
- export declare const DYNAMICS_ACCELERATION_X_INDEX = 0;
15
- export declare const DYNAMICS_ACCELERATION_Y_INDEX = 1;
16
- export declare const DYNAMICS_INVERSE_MASS_INDEX = 2;
17
- export declare const DYNAMICS_SIZE = 3;
18
14
  export declare const dynamicsDefinition: ComponentDefinition<DynamicsComponent, Float32Array, DynamicsConfig, DynamicsSerialization>;
19
15
  export default dynamicsDefinition;
@@ -0,0 +1,18 @@
1
+ export declare const INTERPOLATION_X_INDEX = 0;
2
+ export declare const INTERPOLATION_Y_INDEX = 1;
3
+ export declare const INTERPOLATION_SYNCED_TICK_INDEX = 2;
4
+ export declare const INTERPOLATION_DURATION_INDEX = 3;
5
+ export declare const INTERPOLATION_TICK_INDEX = 4;
6
+ export declare const INTERPOLATION_TOTAL_DURATION_INDEX = 5;
7
+ export declare const INTERPOLATION_SYNCED_DURATION_INDEX = 6;
8
+ export declare const INTERPOLATION_REMAINING_DURATION_INDEX = 7;
9
+ export declare const INTERPOLATION_TARGET_X_INDEX = 8;
10
+ export declare const INTERPOLATION_TARGET_Y_INDEX = 9;
11
+ export declare const INTERPOLATION_SYNCED_STEP_DURATION_INDEX = 10;
12
+ export declare const INTERPOLATION_CHANNEL_INDEX = 11;
13
+ export declare const INTERPOLATION_PREVIOUS_X_INDEX = 12;
14
+ export declare const INTERPOLATION_PREVIOUS_Y_INDEX = 13;
15
+ export declare const INTERPOLATION_PREVIOUS_DURATION_INDEX = 14;
16
+ export declare const INTERPOLATION_PREVIOUS_TOTAL_DURATION_INDEX = 15;
17
+ export declare const INTERPOLATION_PREVIOUS_TICK_INDEX = 16;
18
+ export declare const INTERPOLATION_SIZE = 17;
@@ -1,6 +1,4 @@
1
1
  import type { ComponentDefinition } from '@daneren2005/shared-memory-ecs';
2
- import type { TransformComponent } from './transform-component';
3
- import type { VelocityComponent } from './velocity-component';
4
2
  export interface InterpolationComponent {
5
3
  index: number;
6
4
  x: number;
@@ -22,43 +20,5 @@ export interface InterpolationConfig {
22
20
  x?: number;
23
21
  y?: number;
24
22
  }
25
- export declare const INTERPOLATION_X_INDEX = 0;
26
- export declare const INTERPOLATION_Y_INDEX = 1;
27
- export declare const INTERPOLATION_SYNCED_TICK_INDEX = 2;
28
- export declare const INTERPOLATION_DURATION_INDEX = 3;
29
- export declare const INTERPOLATION_TICK_INDEX = 4;
30
- export declare const INTERPOLATION_TOTAL_DURATION_INDEX = 5;
31
- export declare const INTERPOLATION_SYNCED_DURATION_INDEX = 6;
32
- export declare const INTERPOLATION_REMAINING_DURATION_INDEX = 7;
33
- export declare const INTERPOLATION_TARGET_X_INDEX = 8;
34
- export declare const INTERPOLATION_TARGET_Y_INDEX = 9;
35
- export declare const INTERPOLATION_SYNCED_STEP_DURATION_INDEX = 10;
36
- export declare const INTERPOLATION_CHANNEL_INDEX = 11;
37
- export declare const INTERPOLATION_PREVIOUS_X_INDEX = 12;
38
- export declare const INTERPOLATION_PREVIOUS_Y_INDEX = 13;
39
- export declare const INTERPOLATION_PREVIOUS_DURATION_INDEX = 14;
40
- export declare const INTERPOLATION_PREVIOUS_TOTAL_DURATION_INDEX = 15;
41
- export declare const INTERPOLATION_PREVIOUS_TICK_INDEX = 16;
42
- export declare const INTERPOLATION_SIZE = 17;
43
23
  export declare const interpolationDefinition: ComponentDefinition<InterpolationComponent, Float32Array, InterpolationConfig>;
44
- export interface SnappableEntity {
45
- components: {
46
- transform?: TransformComponent;
47
- interpolation?: InterpolationComponent;
48
- };
49
- }
50
- export declare function snapEntity(entity: SnappableEntity): void;
51
- export interface SpawnableEntity {
52
- components: {
53
- transform?: TransformComponent;
54
- velocity?: VelocityComponent;
55
- interpolation?: InterpolationComponent;
56
- };
57
- }
58
- export interface SpawnInterpolationOptions {
59
- stepMs: number;
60
- stepFraction: number;
61
- tick: number;
62
- }
63
- export declare function startSpawnInterpolation(entity: SpawnableEntity, options: SpawnInterpolationOptions): void;
64
24
  export default interpolationDefinition;
@@ -0,0 +1,11 @@
1
+ export declare const NAVIGATION_REQUEST_INDEX = 0;
2
+ export declare const NAVIGATION_RESULT_INDEX = 1;
3
+ export declare const NAVIGATION_OUTCOME_INDEX = 2;
4
+ export declare const NAVIGATION_WAYPOINT_INDEX = 3;
5
+ export declare const NAVIGATION_WAYPOINT_COUNT_INDEX = 4;
6
+ export declare const NAVIGATION_ACTIVE_INDEX = 5;
7
+ export declare const NAVIGATION_GOAL_X_INDEX = 6;
8
+ export declare const NAVIGATION_GOAL_Y_INDEX = 7;
9
+ export declare const NAVIGATION_WAYPOINTS_INDEX = 8;
10
+ export declare const NAVIGATION_MAX_WAYPOINTS = 32;
11
+ export declare const NAVIGATION_SIZE: number;
@@ -0,0 +1,31 @@
1
+ import type { ComponentDefinition } from '@daneren2005/shared-memory-ecs';
2
+ import { type Point } from '../pathfinding/path-search';
3
+ export interface NavigationComponent {
4
+ index: number;
5
+ readonly active: boolean;
6
+ readonly goalX: number;
7
+ readonly goalY: number;
8
+ readonly pending: boolean;
9
+ readonly outcome: number;
10
+ readonly waypointIndex: number;
11
+ readonly waypoints: Array<Point>;
12
+ navigateTo(x: number, y: number): void;
13
+ stop(): void;
14
+ }
15
+ export interface NavigationConfig {
16
+ navigate: boolean;
17
+ }
18
+ export declare const navigationDefinition: ComponentDefinition<NavigationComponent, Int32Array, NavigationConfig>;
19
+ export declare function navigateTo(navigation: Int32Array, x: number, y: number): void;
20
+ export declare function setNavigationGoal(navigation: Int32Array, x: number, y: number): void;
21
+ export declare function stopNavigating(navigation: Int32Array): void;
22
+ export declare function isNavigating(navigation: Int32Array): boolean;
23
+ export declare function requestPath(navigation: Int32Array): void;
24
+ export declare function isPathPending(navigation: Int32Array): boolean;
25
+ export declare function isUnreachable(navigation: Int32Array): boolean;
26
+ export declare function navigationGoal(navigation: Int32Array): Point;
27
+ export declare function waypoint(navigation: Int32Array, i: number): Point;
28
+ export declare function waypointX(navigation: Int32Array, i: number): number;
29
+ export declare function waypointY(navigation: Int32Array, i: number): number;
30
+ export declare function writePath(navigation: Int32Array, status: number, points: ReadonlyArray<Point>): void;
31
+ export default navigationDefinition;
@@ -0,0 +1,4 @@
1
+ export declare const MAX_POLYGON_VERTICES = 16;
2
+ export declare const POLYGON_VERTEX_COUNT_INDEX = 0;
3
+ export declare const POLYGON_VERTICES_INDEX = 1;
4
+ export declare const POLYGON_SIZE: number;
@@ -10,10 +10,6 @@ export interface PolygonComponent {
10
10
  readonly block: Float32Array;
11
11
  readonly vertexCount: number;
12
12
  }
13
- export declare const MAX_POLYGON_VERTICES = 16;
14
- export declare const POLYGON_VERTEX_COUNT_INDEX = 0;
15
- export declare const POLYGON_VERTICES_INDEX = 1;
16
- export declare const POLYGON_SIZE: number;
17
13
  export interface PreparedPolygon {
18
14
  width: number;
19
15
  height: number;
@@ -2,6 +2,7 @@ import { type BodyComponent } from './body-component';
2
2
  import { type BouncinessComponent } from './bounciness-component';
3
3
  import { type DynamicsComponent } from './dynamics-component';
4
4
  import { type InterpolationComponent } from './interpolation-component';
5
+ import { type NavigationComponent } from './navigation-component';
5
6
  import { type PolygonComponent } from './polygon-component';
6
7
  import { type TransformComponent } from './transform-component';
7
8
  import { type VelocityComponent } from './velocity-component';
@@ -14,6 +15,9 @@ export declare const physicsRegistry: {
14
15
  dynamics: import("@daneren2005/shared-memory-ecs").ComponentDefinition<DynamicsComponent, Float32Array<ArrayBufferLike>, import("./dynamics-component").DynamicsConfig, import("./dynamics-component").DynamicsConfig>;
15
16
  interpolation: import("@daneren2005/shared-memory-ecs").ComponentDefinition<InterpolationComponent, Float32Array<ArrayBufferLike>, import("./interpolation-component").InterpolationConfig, object>;
16
17
  };
18
+ export declare const navigationRegistry: {
19
+ navigation: import("@daneren2005/shared-memory-ecs").ComponentDefinition<NavigationComponent, Int32Array<ArrayBufferLike>, import("./navigation-component").NavigationConfig, object>;
20
+ };
17
21
  export type PhysicsComponents = {
18
22
  transform: TransformComponent;
19
23
  velocity: VelocityComponent;
@@ -27,6 +31,11 @@ export type InterpolationComponents = {
27
31
  transform: TransformComponent;
28
32
  interpolation: InterpolationComponent;
29
33
  };
34
+ export type NavigationComponents = {
35
+ navigation: NavigationComponent;
36
+ transform: TransformComponent;
37
+ body: BodyComponent;
38
+ };
30
39
  export type PhysicsUpdateComponents = {
31
40
  transform: Float32Array;
32
41
  velocity: Float32Array;
@@ -0,0 +1,6 @@
1
+ export declare const TRANSFORM_X_INDEX = 0;
2
+ export declare const TRANSFORM_Y_INDEX = 1;
3
+ export declare const TRANSFORM_WIDTH_INDEX = 2;
4
+ export declare const TRANSFORM_HEIGHT_INDEX = 3;
5
+ export declare const TRANSFORM_ANGLE_INDEX = 4;
6
+ export declare const TRANSFORM_SIZE = 5;
@@ -20,11 +20,5 @@ export interface TransformSerialization {
20
20
  y: number;
21
21
  angle?: number;
22
22
  }
23
- export declare const TRANSFORM_X_INDEX = 0;
24
- export declare const TRANSFORM_Y_INDEX = 1;
25
- export declare const TRANSFORM_WIDTH_INDEX = 2;
26
- export declare const TRANSFORM_HEIGHT_INDEX = 3;
27
- export declare const TRANSFORM_ANGLE_INDEX = 4;
28
- export declare const TRANSFORM_SIZE = 5;
29
23
  export declare const transformDefinition: ComponentDefinition<TransformComponent, Float32Array, TransformConfig, TransformSerialization>;
30
24
  export default transformDefinition;
@@ -0,0 +1,4 @@
1
+ export declare const VELOCITY_X_INDEX = 0;
2
+ export declare const VELOCITY_Y_INDEX = 1;
3
+ export declare const VELOCITY_DAMPING_INDEX = 2;
4
+ export declare const VELOCITY_SIZE = 3;
@@ -11,9 +11,5 @@ export interface VelocityConfig {
11
11
  damping?: number;
12
12
  }
13
13
  export type VelocitySerialization = VelocityConfig;
14
- export declare const VELOCITY_X_INDEX = 0;
15
- export declare const VELOCITY_Y_INDEX = 1;
16
- export declare const VELOCITY_DAMPING_INDEX = 2;
17
- export declare const VELOCITY_SIZE = 3;
18
14
  export declare const velocityDefinition: ComponentDefinition<VelocityComponent, Float32Array, VelocityConfig, VelocitySerialization>;
19
15
  export default velocityDefinition;
@@ -0,0 +1,5 @@
1
+ export declare const POSITION_UPDATED_EVENT = "position-updated";
2
+ export declare const COLLIDABLE_QUERY = "collidable";
3
+ export declare const DEFAULT_PHYSICS_STEP_MS = 50;
4
+ export declare const BACKLOG_TARGET_STEPS = 1.5;
5
+ export declare const BACKLOG_CATCHUP_RATE = 0.5;