@daneren2005/shared-memory-physics 1.7.0 → 1.7.2
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.
- package/README.md +30 -14
- package/dist/components/interpolation-component.d.ts +9 -1
- package/dist/components/polygon-component.d.ts +3 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +368 -311
- package/dist/index.js.map +1 -1
- package/dist/math/shapes.d.ts +1 -0
- package/dist/systems/interpolation-channels.d.ts +6 -0
- package/dist/systems/interpolation-system.d.ts +3 -1
- package/dist/systems/interpolation-update.d.ts +5 -2
- package/dist/systems/physics-system.d.ts +3 -0
- package/dist/systems/physics-update.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -93,7 +93,7 @@ has a `polygon` component holding its outline:
|
|
|
93
93
|
| ----------------- | ------------------------------------- | ------------------------------------------------------------- |
|
|
94
94
|
| `SHAPE_RECTANGLE` | `width`, `height` | a `width` x `height` box turned to `angle` – the default |
|
|
95
95
|
| `SHAPE_CIRCLE` | `radius` | a circle of diameter `width`, which `angle` does not affect |
|
|
96
|
-
| `SHAPE_CAPSULE` | `width`, `height`, `shape` |
|
|
96
|
+
| `SHAPE_CAPSULE` | `width`, `height`, `shape` | a pill along its longer side, as thick as its shorter side |
|
|
97
97
|
| `SHAPE_POLYGON` | `vertices` | a convex 3-16 vertex outline, scaled and turned by its transform |
|
|
98
98
|
|
|
99
99
|
```ts
|
|
@@ -108,8 +108,18 @@ world.loadEntity({ x: 0, y: 0, vertices: [[-8, -6], [10, 0], [-8, 6]] });
|
|
|
108
108
|
Polygon vertices are local to the entity. They must describe a convex boundary in clockwise or counter-clockwise
|
|
109
109
|
order; concave, collinear, non-finite, and out-of-range outlines throw during loading. Their bounding box becomes
|
|
110
110
|
the transform's initial `width` and `height`, and the stored vertices are normalized around that box's centre.
|
|
111
|
-
Changing the transform size therefore scales the polygon, while `angle` rotates it around that centre.
|
|
112
|
-
|
|
111
|
+
Changing the transform size therefore scales the polygon, while `angle` rotates it around that centre. `vertices`
|
|
112
|
+
cannot be given alongside `radius`.
|
|
113
|
+
|
|
114
|
+
Give `width` and `height` with the `vertices` when the outline should sit tighter than the box the entity is sized
|
|
115
|
+
by - a sprite with the hull drawn inside it, say. The box then stays that size, the vertices are offsets from the
|
|
116
|
+
entity's centre rather than from their own bounds, and every one must lie inside the box (the broadphase indexes
|
|
117
|
+
the box, so an outline poking out of it would miss contacts):
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
// A 40x40 sprite whose triangular hull fills only part of it; x/y and the drawn size stay the sprite's.
|
|
121
|
+
world.loadEntity({ x: 0, y: 0, width: 40, height: 40, vertices: [[-12, -15], [14, 0], [-12, 15]] });
|
|
122
|
+
```
|
|
113
123
|
|
|
114
124
|
`radius` is the same size said differently: it loads as a `width` and a `height` of the diameter, so there is
|
|
115
125
|
still only one size in the block however the config spelled it. Giving both a `radius` and a `width` throws
|
|
@@ -118,9 +128,10 @@ rather than one quietly winning. A config that says nothing about its `shape` is
|
|
|
118
128
|
have to name their shape**, and an
|
|
119
129
|
unrecognised one throws rather than quietly becoming a rectangle.
|
|
120
130
|
|
|
121
|
-
A capsule
|
|
122
|
-
|
|
123
|
-
|
|
131
|
+
A capsule lies along its **longer** side, caps included: a 40x10 capsule is a 30-long core along the way the entity
|
|
132
|
+
faces with a 5 radius cap at each end, the same 10 thick all the way down, and a 10x40 one is that same pill turned
|
|
133
|
+
a quarter, running along the entity's height instead - handy for art drawn nose-up. `capsuleCoreAngle` gives the
|
|
134
|
+
angle the core lies at. One as long as it is wide is a circle.
|
|
124
135
|
|
|
125
136
|
Because a circle is a capsule whose core has no length, the three primitive shapes are *an oriented core grown by a
|
|
126
137
|
radius* - a box with no radius, a point, or a segment - which leaves only three overlap tests rather than one
|
|
@@ -139,7 +150,7 @@ reflects around; a game reaching for its own response can use it the same way.
|
|
|
139
150
|
`shapesOverlap` and `contactNormal` are the allocation-free primitive-shape functions. Their polygon counterparts
|
|
140
151
|
are `polygonShapesOverlap` and `polygonContactNormal`, which additionally take the polygon component blocks.
|
|
141
152
|
`shapeHalfWidth` / `shapeHalfHeight` (the axis-aligned box a shape is
|
|
142
|
-
indexed under), `shapeRadius`, `shapeIsEmpty`, `capsuleHalfLength`, and the distance primitives underneath -
|
|
153
|
+
indexed under), `shapeRadius`, `shapeIsEmpty`, `capsuleHalfLength`, `capsuleCoreAngle`, and the distance primitives underneath -
|
|
143
154
|
`segmentSegmentDistanceSquared`, `segmentBoxDistanceSquared` and `pointSegmentDistanceSquared`, each of which
|
|
144
155
|
takes an optional `out` vector and fills it with the gap it measured. `orientedBoxesOverlap`, `boundsHalfWidth`
|
|
145
156
|
and `boundsHalfHeight` are still there and still rectangle-only.
|
|
@@ -348,10 +359,15 @@ world.addSystem(new InterpolationSystem<Components>(world));
|
|
|
348
359
|
world.loadEntity({ x: 0, y: 0, width: 10, height: 10, velocityX: 100, interpolate: true });
|
|
349
360
|
```
|
|
350
361
|
|
|
351
|
-
It takes no configuration
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
362
|
+
It takes no configuration. Physics publishes the transform, step duration, cumulative simulated time, and a tick
|
|
363
|
+
stamp. Rendering caches each coherent target and its timing. If it catches physics mid-write, it continues
|
|
364
|
+
consuming the cached segment until another complete snapshot is available.
|
|
365
|
+
|
|
366
|
+
A worker publishes a run entity by entity while the main thread renders, so one frame can find some entities of a
|
|
367
|
+
run at its new step and the rest at the old one - two ships flying in formation would then drift apart on screen.
|
|
368
|
+
Each entity therefore keeps the publication it replaced, and `InterpolationSystem` snapshots every
|
|
369
|
+
`PhysicsSystem`'s committed tick once per frame: a publication newer than its run's commit is drawn from the
|
|
370
|
+
previous one until the whole run has landed. Both systems must share the same world object for this to apply.
|
|
355
371
|
A game that retunes `deltaBetweenRuns` mid-flight is followed with nothing told to this system.
|
|
356
372
|
|
|
357
373
|
Then draw from `interpolation` instead of `transform`, keeping the size and facing where they have always been:
|
|
@@ -489,15 +505,15 @@ spot, as above.
|
|
|
489
505
|
|
|
490
506
|
The renderer retains the last coherent target while physics publishes a new step, so an overlapping read can keep advancing without freezing a frame.
|
|
491
507
|
|
|
492
|
-
|
|
508
|
+
68 bytes per interpolated entity, ten publication writes per entity per physics step, and a per-frame pass of one
|
|
493
509
|
lerp per entity on the main thread - order 0.2ms at 10,000 entities. An entity without the component pays
|
|
494
510
|
nothing at all. `forceMainThread: false` plus a `getWorker` moves the pass to a worker for worlds large enough
|
|
495
511
|
that it shows up in a profile, at the price of the render position being one frame stale; because consumers only
|
|
496
512
|
ever read `interpolation.x`, that is a constructor flag rather than a migration.
|
|
497
513
|
|
|
498
514
|
Physics marks the tick dirty before changing timing and position, then publishes the completed tick with
|
|
499
|
-
a release store. The reader accepts a new snapshot only when its tick reads match
|
|
500
|
-
toward the cached target.
|
|
515
|
+
a release store. The reader accepts a new snapshot only when its tick reads match and its run has committed;
|
|
516
|
+
otherwise it reads the previous publication, and failing that continues toward the cached target.
|
|
501
517
|
|
|
502
518
|
## Collisions
|
|
503
519
|
|
|
@@ -14,6 +14,8 @@ export interface InterpolationComponent {
|
|
|
14
14
|
targetX: number;
|
|
15
15
|
targetY: number;
|
|
16
16
|
syncedStepDuration: number;
|
|
17
|
+
previousX: number;
|
|
18
|
+
previousY: number;
|
|
17
19
|
}
|
|
18
20
|
export interface InterpolationConfig {
|
|
19
21
|
interpolate?: boolean;
|
|
@@ -31,7 +33,13 @@ export declare const INTERPOLATION_REMAINING_DURATION_INDEX = 7;
|
|
|
31
33
|
export declare const INTERPOLATION_TARGET_X_INDEX = 8;
|
|
32
34
|
export declare const INTERPOLATION_TARGET_Y_INDEX = 9;
|
|
33
35
|
export declare const INTERPOLATION_SYNCED_STEP_DURATION_INDEX = 10;
|
|
34
|
-
export declare const
|
|
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;
|
|
35
43
|
export declare const interpolationDefinition: ComponentDefinition<InterpolationComponent, Float32Array, InterpolationConfig>;
|
|
36
44
|
export interface SnappableEntity {
|
|
37
45
|
components: {
|
|
@@ -2,6 +2,8 @@ import type { ComponentDefinition } from '@daneren2005/shared-memory-ecs';
|
|
|
2
2
|
export type PolygonVertex = readonly [x: number, y: number];
|
|
3
3
|
export interface PolygonConfig {
|
|
4
4
|
vertices?: ReadonlyArray<PolygonVertex>;
|
|
5
|
+
width?: number;
|
|
6
|
+
height?: number;
|
|
5
7
|
}
|
|
6
8
|
export interface PolygonComponent {
|
|
7
9
|
index: number;
|
|
@@ -18,5 +20,5 @@ export interface PreparedPolygon {
|
|
|
18
20
|
vertices: Array<number>;
|
|
19
21
|
}
|
|
20
22
|
export declare const polygonDefinition: ComponentDefinition<PolygonComponent, Float32Array, PolygonConfig>;
|
|
21
|
-
export declare function preparePolygon(vertices: ReadonlyArray<PolygonVertex> | undefined): PreparedPolygon;
|
|
23
|
+
export declare function preparePolygon(vertices: ReadonlyArray<PolygonVertex> | undefined, boxWidth?: number, boxHeight?: number): PreparedPolygon;
|
|
22
24
|
export default polygonDefinition;
|
package/dist/index.d.ts
CHANGED
|
@@ -17,13 +17,13 @@ export { default as bouncinessDefinition } from './components/bounciness-compone
|
|
|
17
17
|
export { BOUNCINESS_INDEX, BOUNCINESS_SIZE, } from './components/bounciness-component';
|
|
18
18
|
export type { BouncinessComponent, BouncinessConfig, } from './components/bounciness-component';
|
|
19
19
|
export { default as interpolationDefinition, snapEntity, startSpawnInterpolation } from './components/interpolation-component';
|
|
20
|
-
export { INTERPOLATION_X_INDEX, INTERPOLATION_Y_INDEX, INTERPOLATION_SYNCED_TICK_INDEX, INTERPOLATION_DURATION_INDEX, INTERPOLATION_TICK_INDEX, INTERPOLATION_TOTAL_DURATION_INDEX, INTERPOLATION_SYNCED_DURATION_INDEX, INTERPOLATION_REMAINING_DURATION_INDEX, INTERPOLATION_TARGET_X_INDEX, INTERPOLATION_TARGET_Y_INDEX, INTERPOLATION_SYNCED_STEP_DURATION_INDEX, INTERPOLATION_SIZE, } from './components/interpolation-component';
|
|
20
|
+
export { INTERPOLATION_X_INDEX, INTERPOLATION_Y_INDEX, INTERPOLATION_SYNCED_TICK_INDEX, INTERPOLATION_DURATION_INDEX, INTERPOLATION_TICK_INDEX, INTERPOLATION_TOTAL_DURATION_INDEX, INTERPOLATION_SYNCED_DURATION_INDEX, INTERPOLATION_REMAINING_DURATION_INDEX, INTERPOLATION_TARGET_X_INDEX, INTERPOLATION_TARGET_Y_INDEX, INTERPOLATION_SYNCED_STEP_DURATION_INDEX, INTERPOLATION_CHANNEL_INDEX, INTERPOLATION_PREVIOUS_X_INDEX, INTERPOLATION_PREVIOUS_Y_INDEX, INTERPOLATION_PREVIOUS_DURATION_INDEX, INTERPOLATION_PREVIOUS_TOTAL_DURATION_INDEX, INTERPOLATION_PREVIOUS_TICK_INDEX, INTERPOLATION_SIZE, } from './components/interpolation-component';
|
|
21
21
|
export type { InterpolationComponent, InterpolationConfig, SnappableEntity, SpawnableEntity, SpawnInterpolationOptions, } from './components/interpolation-component';
|
|
22
22
|
export { physicsRegistry } from './components/registry';
|
|
23
23
|
export type { PhysicsComponents, PhysicsUpdateComponents, InterpolationComponents, InterpolationUpdateComponents, } from './components/registry';
|
|
24
24
|
export { default as PhysicalWorld, addPhysicalWorldData, getSpatialMap } from './world';
|
|
25
25
|
export type { PhysicalSystemWorld, PhysicalWorldData, PhysicalWorldSource, PhysicalWorldEntity, PhysicalWorldFilter, PhysicalWorldOptions, } from './world';
|
|
26
|
-
export { shapesOverlap, contactNormal, shapeHalfWidth, shapeHalfHeight, shapeIsEmpty, shapeRadius, capsuleHalfLength, boundsHalfWidth, boundsHalfHeight, orientedBoxesOverlap, segmentSegmentDistanceSquared, segmentBoxDistanceSquared, pointSegmentDistanceSquared, } from './math/shapes';
|
|
26
|
+
export { shapesOverlap, contactNormal, shapeHalfWidth, shapeHalfHeight, shapeIsEmpty, shapeRadius, capsuleHalfLength, capsuleCoreAngle, boundsHalfWidth, boundsHalfHeight, orientedBoxesOverlap, segmentSegmentDistanceSquared, segmentBoxDistanceSquared, pointSegmentDistanceSquared, } from './math/shapes';
|
|
27
27
|
export type { Vector } from './math/shapes';
|
|
28
28
|
export { polygonShapesOverlap, polygonContactNormal } from './math/polygons';
|
|
29
29
|
export { default as CollisionBroadphase, COLLIDABLE_QUERY } from './systems/collision';
|
|
@@ -37,5 +37,6 @@ export type { PhysicsSystemConfig, VelocityAssignment } from './systems/physics-
|
|
|
37
37
|
export { default as integrateDynamics } from './systems/dynamics';
|
|
38
38
|
export type { DynamicsCommand, DynamicsCommandBuffer, DynamicsCommandQueue, DynamicsCommands, DynamicsWorld } from './systems/dynamics';
|
|
39
39
|
export { default as interpolationUpdate } from './systems/interpolation-update';
|
|
40
|
+
export type { InterpolationWorld } from './systems/interpolation-update';
|
|
40
41
|
export { default as InterpolationSystem } from './systems/interpolation-system';
|
|
41
42
|
export type { InterpolationSystemConfig } from './systems/interpolation-system';
|