@daneren2005/shared-memory-physics 1.7.1 → 1.7.3

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 CHANGED
@@ -19,7 +19,7 @@ npm install @daneren2005/shared-memory-physics @daneren2005/shared-memory-ecs @d
19
19
  | Component | Config | Serialization | Block |
20
20
  | --------------- | -------------------------------------------- | -------------------------- | ---------------------------------------------- |
21
21
  | `dynamics` | - | `accelerationX?`, `accelerationY?`, `mass?` | `Float32Array` - acceleration and inverse mass |
22
- | `transform` | `width`, `height`, `angle?` / `radius` | `x`, `y`, `angle` | `Float32Array` – where, how big, facing |
22
+ | `transform` | `width`, `height`, `angle?` / `radius` | `x`, `y`, `angle?` | `Float32Array` – where, how big, facing |
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 |
@@ -59,8 +59,8 @@ effective mass `1` when a force or impulse is queued for it.
59
59
  The transform is split in two. **Config** is what your entity template says - `width` and `height` are
60
60
  required, `angle` defaults to `0` - and a size is what loads the component at all: a config with neither a
61
61
  width nor a height does not get a transform. **Serialization** is the live state that changes as the world
62
- runs, so `save()` returns `x` / `y` and `angle`, while a reloaded entity gets its size back from your own
63
- template rather than the save.
62
+ runs, so `save()` returns `x` / `y` and includes `angle` only when it is nonzero. An omitted angle defaults
63
+ to `0` on load, while a reloaded entity gets its size back from your own template rather than the save.
64
64
 
65
65
  `x` / `y` are the **centre** of the box, not a corner: the box is rotated about that point and collision
66
66
  projects out from it in both directions. `angle` is in **radians** counter-clockwise from the +x axis, and
@@ -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` | `width` from end to end, `height` thick, lying along `angle` |
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. Give
112
- `vertices` by themselves rather than alongside `radius` or `width`/`height`.
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's `width` is its **whole** length, caps included, and it lies along the way the entity faces: a 40x10
122
- capsule is a 30-long core with a 5 radius cap at each end, and it is the same 10 thick all the way down. One
123
- told it is no longer than it is wide collapses to a circle rather than turning itself inside out.
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.
@@ -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;
@@ -18,7 +18,7 @@ export interface TransformConfig {
18
18
  export interface TransformSerialization {
19
19
  x: number;
20
20
  y: number;
21
- angle: number;
21
+ angle?: number;
22
22
  }
23
23
  export declare const TRANSFORM_X_INDEX = 0;
24
24
  export declare const TRANSFORM_Y_INDEX = 1;
package/dist/index.d.ts CHANGED
@@ -23,7 +23,7 @@ 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';