dacha 0.18.0-alpha.8 → 0.18.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.
- package/build/contrib/components/index.d.ts +1 -0
- package/build/contrib/components/index.js +1 -0
- package/build/contrib/components/interpolation/index.d.ts +85 -0
- package/build/contrib/components/interpolation/index.js +101 -0
- package/build/contrib/components/rigid-body/index.d.ts +108 -14
- package/build/contrib/components/rigid-body/index.js +191 -22
- package/build/contrib/systems/animator/index.d.ts +3 -2
- package/build/contrib/systems/animator/index.js +6 -3
- package/build/contrib/systems/behavior-system/system.d.ts +4 -2
- package/build/contrib/systems/behavior-system/system.js +11 -3
- package/build/contrib/systems/behavior-system/types.d.ts +7 -10
- package/build/contrib/systems/character-controller/index.d.ts +4 -2
- package/build/contrib/systems/character-controller/index.js +22 -17
- package/build/contrib/systems/character-controller/one-way-validator.d.ts +15 -0
- package/build/contrib/systems/character-controller/one-way-validator.js +73 -0
- package/build/contrib/systems/game-stats-meter/index.d.ts +4 -3
- package/build/contrib/systems/game-stats-meter/index.js +11 -10
- package/build/contrib/systems/index.d.ts +2 -0
- package/build/contrib/systems/index.js +1 -0
- package/build/contrib/systems/interpolator/api.d.ts +40 -0
- package/build/contrib/systems/interpolator/api.js +70 -0
- package/build/contrib/systems/interpolator/index.d.ts +3 -0
- package/build/contrib/systems/interpolator/index.js +2 -0
- package/build/contrib/systems/interpolator/system.d.ts +31 -0
- package/build/contrib/systems/interpolator/system.js +96 -0
- package/build/contrib/systems/interpolator/tests/helpers.d.ts +13 -0
- package/build/contrib/systems/interpolator/tests/helpers.js +45 -0
- package/build/contrib/systems/interpolator/utils.d.ts +5 -0
- package/build/contrib/systems/interpolator/utils.js +41 -0
- package/build/contrib/systems/physics-system/api.d.ts +45 -1
- package/build/contrib/systems/physics-system/api.js +49 -0
- package/build/contrib/systems/physics-system/consts.d.ts +13 -0
- package/build/contrib/systems/physics-system/consts.js +17 -0
- package/build/contrib/systems/physics-system/physics-system.d.ts +2 -2
- package/build/contrib/systems/physics-system/physics-system.js +24 -4
- package/build/contrib/systems/physics-system/subsystems/collision-detection/dynamic-aabb-tree/index.d.ts +1 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/dynamic-aabb-tree/index.js +21 -15
- package/build/contrib/systems/physics-system/subsystems/collision-detection/index.d.ts +11 -11
- package/build/contrib/systems/physics-system/subsystems/collision-detection/index.js +133 -125
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/check-boxes-intersection.js +5 -3
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/utils.d.ts +1 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/utils.js +2 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-capsule/check-box-and-capsule-intersection.js +4 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/check-box-and-segment-intersection.js +4 -2
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/common/points.d.ts +2 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/common/points.js +16 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/index.js +2 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/tests/helpers.js +3 -14
- package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.d.ts +5 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.js +97 -81
- package/build/contrib/systems/physics-system/subsystems/collision-detection/shape-cast-checkers/tests/helpers.js +2 -7
- package/build/contrib/systems/physics-system/subsystems/collision-detection/tests/assertions.d.ts +1 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/tests/assertions.js +7 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/types.d.ts +0 -15
- package/build/contrib/systems/physics-system/subsystems/collision-detection/utils.d.ts +3 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/utils.js +9 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/contact-state-manager.d.ts +63 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/contact-state-manager.js +170 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/contact-utils.d.ts +5 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/contact-utils.js +41 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/impulse-utils.d.ts +16 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/impulse-utils.js +77 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.d.ts +53 -4
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.js +334 -116
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/one-way-validator.d.ts +11 -0
- package/build/contrib/{utils → systems/physics-system/subsystems/constraint-solver}/one-way-validator.js +22 -25
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/sleep-support-tracker.d.ts +13 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/sleep-support-tracker.js +42 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/tests/helpers.d.ts +4 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/tests/helpers.js +20 -0
- package/build/contrib/systems/physics-system/subsystems/physics/index.d.ts +15 -4
- package/build/contrib/systems/physics-system/subsystems/physics/index.js +131 -53
- package/build/contrib/systems/physics-system/subsystems/physics/mass-properties.d.ts +2 -0
- package/build/contrib/systems/physics-system/subsystems/physics/mass-properties.js +55 -0
- package/build/contrib/systems/physics-system/tests/helpers.d.ts +5 -2
- package/build/contrib/systems/physics-system/tests/helpers.js +11 -2
- package/build/contrib/systems/physics-system/types.d.ts +18 -2
- package/build/contrib/systems/renderer/actor-render-tree.js +15 -6
- package/build/contrib/systems/renderer/filters/index.d.ts +1 -1
- package/build/contrib/systems/renderer/filters/index.js +1 -1
- package/build/contrib/systems/renderer/material/index.d.ts +2 -1
- package/build/contrib/systems/renderer/material/index.js +1 -1
- package/build/contrib/systems/renderer/renderer.d.ts +2 -2
- package/build/contrib/systems/renderer/renderer.js +3 -4
- package/build/contrib/systems/renderer/types.d.ts +0 -3
- package/build/engine/data-lib/index.d.ts +1 -1
- package/build/engine/data-lib/index.js +1 -1
- package/build/engine/data-lib/pool.d.ts +9 -0
- package/build/engine/data-lib/pool.js +19 -0
- package/build/engine/engine.js +4 -1
- package/build/engine/game-loop.d.ts +3 -1
- package/build/engine/game-loop.js +11 -8
- package/build/engine/math-lib/math/ops.d.ts +16 -0
- package/build/engine/math-lib/math/ops.js +25 -0
- package/build/engine/scene/scene-manager.d.ts +4 -1
- package/build/engine/scene/scene-manager.js +5 -1
- package/build/engine/system/index.d.ts +1 -1
- package/build/engine/system/system.d.ts +10 -11
- package/build/engine/system/system.js +5 -2
- package/build/engine/time.d.ts +54 -0
- package/build/engine/time.js +77 -0
- package/build/index.d.ts +2 -1
- package/package.json +1 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/dispersion-calculator/index.d.ts +0 -11
- package/build/contrib/systems/physics-system/subsystems/collision-detection/dispersion-calculator/index.js +0 -41
- package/build/contrib/utils/one-way-validator.d.ts +0 -12
- package/build/engine/data-lib/sort/index.d.ts +0 -1
- package/build/engine/data-lib/sort/index.js +0 -1
- package/build/engine/data-lib/sort/insertion-sort.d.ts +0 -1
- package/build/engine/data-lib/sort/insertion-sort.js +0 -14
|
@@ -3,8 +3,16 @@ import { Vector2 } from '../../../engine/math-lib';
|
|
|
3
3
|
/**
|
|
4
4
|
* RigidBody component for defining rigid body physics.
|
|
5
5
|
*
|
|
6
|
-
* Defines the physics properties for an actor.
|
|
7
|
-
*
|
|
6
|
+
* Defines the physics properties for an actor. Dynamic bodies react to forces,
|
|
7
|
+
* impulses, gravity, collisions, and rotation. Static and kinematic bodies can
|
|
8
|
+
* participate in collisions but are not moved by solver impulses.
|
|
9
|
+
*
|
|
10
|
+
* Physics is simulated in world space.
|
|
11
|
+
*
|
|
12
|
+
* Rigid bodies may be parented only to actors with static transforms. A moving
|
|
13
|
+
* parent (for example, a dynamic or kinematic rigid body) and the physics
|
|
14
|
+
* simulation would both control the child's transform, so the result is
|
|
15
|
+
* undefined.
|
|
8
16
|
*
|
|
9
17
|
* @example
|
|
10
18
|
* ```typescript
|
|
@@ -29,24 +37,54 @@ import { Vector2 } from '../../../engine/math-lib';
|
|
|
29
37
|
export class RigidBody extends Component {
|
|
30
38
|
_mass;
|
|
31
39
|
_inverseMass;
|
|
40
|
+
_inertia;
|
|
41
|
+
_inverseInertia;
|
|
42
|
+
_restitution;
|
|
43
|
+
_friction;
|
|
32
44
|
/** @internal Pending one-step kinematic movement target */
|
|
33
45
|
_movementTarget;
|
|
46
|
+
/** @internal Linear velocity from the start of the current physics step */
|
|
47
|
+
_prevLinearVelocity;
|
|
48
|
+
/** @internal Angular velocity from the start of the current physics step */
|
|
49
|
+
_prevAngularVelocity;
|
|
50
|
+
/** @internal Temporary solver velocity used for contact separation */
|
|
51
|
+
_biasLinearVelocity;
|
|
52
|
+
/** @internal Temporary solver angular velocity used for contact separation */
|
|
53
|
+
_biasAngularVelocity;
|
|
54
|
+
/** @internal Time this body has stayed below automatic sleep thresholds */
|
|
55
|
+
_sleepTime;
|
|
34
56
|
/** Body type that defines how the rigid body participates in simulation */
|
|
35
57
|
type;
|
|
36
|
-
/** Gravity
|
|
58
|
+
/** Gravity multiplier. `0` ignores gravity, `1` uses normal world gravity. */
|
|
37
59
|
gravityScale;
|
|
38
|
-
/** Linear damping
|
|
60
|
+
/** Linear damping used to slow down movement over time */
|
|
39
61
|
linearDamping;
|
|
40
|
-
/**
|
|
62
|
+
/** Angular damping used to slow down rotation over time */
|
|
63
|
+
angularDamping;
|
|
64
|
+
/** Current linear velocity in world units per second */
|
|
41
65
|
linearVelocity;
|
|
66
|
+
/** Current angular velocity of the rigid body in radians per second */
|
|
67
|
+
angularVelocity;
|
|
68
|
+
/** Whether dynamic rotation is locked. Locked bodies do not spin from torque or contacts. */
|
|
69
|
+
lockRotation;
|
|
42
70
|
/** Whether rigid body simulation is disabled */
|
|
43
71
|
disabled;
|
|
44
72
|
/** Whether rigid body is sleeping */
|
|
45
73
|
sleeping;
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
|
|
74
|
+
/** Whether this body may be put to sleep automatically when settled */
|
|
75
|
+
autoSleep;
|
|
76
|
+
/** @internal Force applied at the rigid body center */
|
|
77
|
+
_centralForce;
|
|
78
|
+
/** @internal Impulse applied at the rigid body center */
|
|
79
|
+
_centralImpulse;
|
|
80
|
+
/** @internal Forces applied at world-space positions */
|
|
81
|
+
_pointForces;
|
|
82
|
+
/** @internal Impulses applied at world-space positions */
|
|
83
|
+
_pointImpulses;
|
|
84
|
+
/** @internal Torque applied to the rigid body */
|
|
85
|
+
_torque;
|
|
86
|
+
/** @internal Angular impulse applied to the rigid body */
|
|
87
|
+
_angularImpulse;
|
|
50
88
|
/** Whether contacts should only be resolved from one side */
|
|
51
89
|
oneWay;
|
|
52
90
|
/** Local-space normal that points toward the blocking side */
|
|
@@ -59,16 +97,36 @@ export class RigidBody extends Component {
|
|
|
59
97
|
super();
|
|
60
98
|
this._mass = 0;
|
|
61
99
|
this._inverseMass = 0;
|
|
100
|
+
this._inertia = 0;
|
|
101
|
+
this._inverseInertia = 0;
|
|
102
|
+
this._restitution = 0;
|
|
103
|
+
this._friction = 0;
|
|
62
104
|
this._movementTarget = null;
|
|
105
|
+
this._prevLinearVelocity = new Vector2(0, 0);
|
|
106
|
+
this._prevAngularVelocity = 0;
|
|
107
|
+
this._biasLinearVelocity = new Vector2(0, 0);
|
|
108
|
+
this._biasAngularVelocity = 0;
|
|
109
|
+
this._sleepTime = 0;
|
|
63
110
|
this.type = config.type;
|
|
64
|
-
this.mass = config.mass ?? 0;
|
|
65
|
-
this.gravityScale =
|
|
111
|
+
this.mass = config.mass ?? (this.type === 'dynamic' ? 1 : 0);
|
|
112
|
+
this.gravityScale =
|
|
113
|
+
config.gravityScale ?? (this.type === 'dynamic' ? 1 : 0);
|
|
66
114
|
this.linearDamping = config.linearDamping ?? 0;
|
|
67
|
-
this.
|
|
115
|
+
this.angularDamping = config.angularDamping ?? 0;
|
|
116
|
+
this.restitution = config.restitution ?? 0;
|
|
117
|
+
this.friction = config.friction ?? 0.6;
|
|
118
|
+
this.lockRotation = config.lockRotation ?? false;
|
|
119
|
+
this.autoSleep = config.autoSleep ?? true;
|
|
68
120
|
this.disabled = config.disabled;
|
|
121
|
+
this.linearVelocity = new Vector2(0, 0);
|
|
122
|
+
this.angularVelocity = 0;
|
|
69
123
|
this.sleeping = false;
|
|
70
|
-
this.
|
|
71
|
-
this.
|
|
124
|
+
this._centralForce = new Vector2(0, 0);
|
|
125
|
+
this._centralImpulse = new Vector2(0, 0);
|
|
126
|
+
this._pointForces = [];
|
|
127
|
+
this._pointImpulses = [];
|
|
128
|
+
this._torque = 0;
|
|
129
|
+
this._angularImpulse = 0;
|
|
72
130
|
this.oneWay = config.oneWay ?? false;
|
|
73
131
|
if (this.oneWay) {
|
|
74
132
|
this.oneWayNormal = new Vector2(config.oneWayNormalX ?? 0, config.oneWayNormalY ?? 0).normalize();
|
|
@@ -83,6 +141,7 @@ export class RigidBody extends Component {
|
|
|
83
141
|
/**
|
|
84
142
|
* Sets the mass used by dynamic bodies.
|
|
85
143
|
*
|
|
144
|
+
* Mass is an authored, kilogram-like scalar.
|
|
86
145
|
* Non-positive values make the body immovable by forces and impulses.
|
|
87
146
|
*/
|
|
88
147
|
set mass(value) {
|
|
@@ -95,50 +154,160 @@ export class RigidBody extends Component {
|
|
|
95
154
|
* Bodies with zero or negative mass return `0`.
|
|
96
155
|
*/
|
|
97
156
|
get inverseMass() {
|
|
157
|
+
if (this.type === 'static' || this.type === 'kinematic' || this.sleeping) {
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
98
160
|
return this._inverseMass;
|
|
99
161
|
}
|
|
162
|
+
get inertia() {
|
|
163
|
+
return this._inertia;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Moment of inertia used by dynamic bodies.
|
|
167
|
+
*
|
|
168
|
+
* Inertia is the rotational equivalent of mass: higher values make the body
|
|
169
|
+
* harder to spin. It is automatically computed from the collider shape, mass,
|
|
170
|
+
* and collider offset every physics step, so user code usually should only
|
|
171
|
+
* read this value.
|
|
172
|
+
*/
|
|
173
|
+
set inertia(value) {
|
|
174
|
+
this._inertia = value;
|
|
175
|
+
this._inverseInertia = value > 0 ? 1 / value : 0;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Returns the inverse moment of inertia.
|
|
179
|
+
*
|
|
180
|
+
* This is the solver-friendly form of inertia. Static bodies, kinematic
|
|
181
|
+
* bodies, locked rotation, or non-positive inertia return `0`.
|
|
182
|
+
*/
|
|
183
|
+
get inverseInertia() {
|
|
184
|
+
if (this.type === 'static' ||
|
|
185
|
+
this.type === 'kinematic' ||
|
|
186
|
+
this.sleeping ||
|
|
187
|
+
this.lockRotation) {
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
return this._inverseInertia;
|
|
191
|
+
}
|
|
192
|
+
/** Bounciness used by contact resolution. `0` does not bounce, `1` keeps full bounce speed. */
|
|
193
|
+
get restitution() {
|
|
194
|
+
return this._restitution;
|
|
195
|
+
}
|
|
196
|
+
set restitution(value) {
|
|
197
|
+
this._restitution = Math.max(0, Math.min(value, 1));
|
|
198
|
+
}
|
|
199
|
+
/** Surface friction used by contact resolution. Higher values reduce sliding more strongly. */
|
|
200
|
+
get friction() {
|
|
201
|
+
return this._friction;
|
|
202
|
+
}
|
|
203
|
+
set friction(value) {
|
|
204
|
+
this._friction = Math.max(0, value);
|
|
205
|
+
}
|
|
100
206
|
/**
|
|
101
207
|
* Adds a continuous force to a dynamic body for the next physics step.
|
|
102
208
|
*
|
|
103
|
-
* Affects only active dynamic bodies.
|
|
209
|
+
* Affects only active dynamic bodies. When `position` is provided, it is a
|
|
210
|
+
* world-space point where the force is applied; off-center forces can also
|
|
211
|
+
* rotate the body.
|
|
104
212
|
*/
|
|
105
|
-
applyForce(force) {
|
|
213
|
+
applyForce(force, position) {
|
|
106
214
|
if (this.disabled || this.type !== 'dynamic') {
|
|
107
215
|
return;
|
|
108
216
|
}
|
|
109
217
|
this.wakeUp();
|
|
110
|
-
|
|
218
|
+
if (!position) {
|
|
219
|
+
this._centralForce.add(force);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
this._pointForces.push({
|
|
223
|
+
force: force.clone(),
|
|
224
|
+
position: { x: position.x, y: position.y },
|
|
225
|
+
});
|
|
111
226
|
}
|
|
112
227
|
/**
|
|
113
228
|
* Adds an instantaneous impulse to a dynamic body for the next physics step.
|
|
114
229
|
*
|
|
115
|
-
* Affects only active dynamic bodies.
|
|
230
|
+
* Affects only active dynamic bodies. An impulse is a one-step velocity kick.
|
|
231
|
+
* When `position` is provided, it is a world-space point where the impulse is
|
|
232
|
+
* applied; off-center impulses can also rotate the body.
|
|
116
233
|
*/
|
|
117
|
-
applyImpulse(impulse) {
|
|
234
|
+
applyImpulse(impulse, position) {
|
|
118
235
|
if (this.disabled || this.type !== 'dynamic') {
|
|
119
236
|
return;
|
|
120
237
|
}
|
|
121
238
|
this.wakeUp();
|
|
122
|
-
|
|
239
|
+
if (!position) {
|
|
240
|
+
this._centralImpulse.add(impulse);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
this._pointImpulses.push({
|
|
244
|
+
impulse: impulse.clone(),
|
|
245
|
+
position: { x: position.x, y: position.y },
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Adds a continuous torque to a dynamic body for the next physics step.
|
|
250
|
+
*
|
|
251
|
+
* Torque is rotational force: it changes angular velocity over time. Affects
|
|
252
|
+
* only active dynamic bodies with unlocked rotation.
|
|
253
|
+
*/
|
|
254
|
+
applyTorque(torque) {
|
|
255
|
+
if (this.disabled || this.type !== 'dynamic' || this.lockRotation) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
this.wakeUp();
|
|
259
|
+
this._torque += torque;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Adds an instantaneous angular impulse to a dynamic body for the next physics step.
|
|
263
|
+
*
|
|
264
|
+
* Angular impulse is an immediate rotational kick. Affects only active dynamic
|
|
265
|
+
* bodies with unlocked rotation.
|
|
266
|
+
*/
|
|
267
|
+
applyAngularImpulse(impulse) {
|
|
268
|
+
if (this.disabled || this.type !== 'dynamic' || this.lockRotation) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
this.wakeUp();
|
|
272
|
+
this._angularImpulse += impulse;
|
|
123
273
|
}
|
|
124
274
|
/**
|
|
125
275
|
* Marks the rigid body as awake so it can be simulated.
|
|
126
276
|
*/
|
|
127
277
|
wakeUp() {
|
|
278
|
+
if (this.disabled || this.type !== 'dynamic') {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
128
281
|
this.sleeping = false;
|
|
282
|
+
this._sleepTime = 0;
|
|
129
283
|
}
|
|
130
284
|
/**
|
|
131
285
|
* Marks the rigid body as sleeping so dynamic integration can skip it.
|
|
132
286
|
*/
|
|
133
287
|
sleep() {
|
|
288
|
+
if (this.disabled || this.type !== 'dynamic') {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
134
291
|
this.sleeping = true;
|
|
292
|
+
this._sleepTime = 0;
|
|
293
|
+
this._prevLinearVelocity.multiplyNumber(0);
|
|
294
|
+
this._prevAngularVelocity = 0;
|
|
295
|
+
this.linearVelocity.multiplyNumber(0);
|
|
296
|
+
this.angularVelocity = 0;
|
|
297
|
+
this._biasLinearVelocity.multiplyNumber(0);
|
|
298
|
+
this._biasAngularVelocity = 0;
|
|
299
|
+
this.clearForces();
|
|
135
300
|
}
|
|
136
301
|
/**
|
|
137
302
|
* Clears all accumulated force and impulse values.
|
|
138
303
|
*/
|
|
139
304
|
clearForces() {
|
|
140
|
-
this.
|
|
141
|
-
this.
|
|
305
|
+
this._centralForce.multiplyNumber(0);
|
|
306
|
+
this._centralImpulse.multiplyNumber(0);
|
|
307
|
+
this._pointForces.length = 0;
|
|
308
|
+
this._pointImpulses.length = 0;
|
|
309
|
+
this._torque = 0;
|
|
310
|
+
this._angularImpulse = 0;
|
|
142
311
|
}
|
|
143
312
|
/**
|
|
144
313
|
* Moves a kinematic body to a target position on the next physics step.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SceneSystem } from '../../../engine/system';
|
|
2
|
-
import type {
|
|
2
|
+
import type { SceneSystemOptions } from '../../../engine/system';
|
|
3
3
|
/**
|
|
4
4
|
* Animator system that manages the animation of actors with {@link Animatable} components
|
|
5
5
|
* using the state machine approach
|
|
@@ -10,6 +10,7 @@ import type { UpdateOptions, SceneSystemOptions } from '../../../engine/system';
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class Animator extends SceneSystem {
|
|
12
12
|
private actorQuery;
|
|
13
|
+
private time;
|
|
13
14
|
private substatePickers;
|
|
14
15
|
private actorConditions;
|
|
15
16
|
constructor(options: SceneSystemOptions);
|
|
@@ -18,5 +19,5 @@ export declare class Animator extends SceneSystem {
|
|
|
18
19
|
private setUpConditionControllers;
|
|
19
20
|
private updateFrame;
|
|
20
21
|
private pickSubstate;
|
|
21
|
-
update(
|
|
22
|
+
update(): void;
|
|
22
23
|
}
|
|
@@ -5,7 +5,8 @@ import { RemoveActor } from '../../../engine/events';
|
|
|
5
5
|
import { conditionControllers } from './condition-controllers';
|
|
6
6
|
import { substatePickers } from './substate-pickers';
|
|
7
7
|
import { setValue } from './utils';
|
|
8
|
-
|
|
8
|
+
// Seconds per animation frame at speed 1.
|
|
9
|
+
const FRAME_RATE = 0.1;
|
|
9
10
|
/**
|
|
10
11
|
* Animator system that manages the animation of actors with {@link Animatable} components
|
|
11
12
|
* using the state machine approach
|
|
@@ -16,10 +17,12 @@ const FRAME_RATE = 100;
|
|
|
16
17
|
*/
|
|
17
18
|
export class Animator extends SceneSystem {
|
|
18
19
|
actorQuery;
|
|
20
|
+
time;
|
|
19
21
|
substatePickers;
|
|
20
22
|
actorConditions;
|
|
21
23
|
constructor(options) {
|
|
22
24
|
super();
|
|
25
|
+
this.time = options.time;
|
|
23
26
|
this.actorQuery = new ActorQuery({
|
|
24
27
|
scene: options.scene,
|
|
25
28
|
filter: [Animatable],
|
|
@@ -64,8 +67,8 @@ export class Animator extends SceneSystem {
|
|
|
64
67
|
const substatePicker = this.substatePickers[state.pickMode];
|
|
65
68
|
return substatePicker.getSubstate(actor, state.substates, state.pickProps);
|
|
66
69
|
}
|
|
67
|
-
update(
|
|
68
|
-
const { deltaTime } =
|
|
70
|
+
update() {
|
|
71
|
+
const { deltaTime } = this.time;
|
|
69
72
|
this.actorQuery.getActors().forEach((actor) => {
|
|
70
73
|
const animatable = actor.getComponent(Animatable);
|
|
71
74
|
if (animatable.currentState === void 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SceneSystem } from '../../../engine/system';
|
|
2
|
-
import type { SceneSystemOptions
|
|
2
|
+
import type { SceneSystemOptions } from '../../../engine/system';
|
|
3
3
|
/**
|
|
4
4
|
* Behavior system that manages custom behavior execution for actors
|
|
5
5
|
* with {@link Behaviors} components
|
|
@@ -15,6 +15,7 @@ export declare class BehaviorSystem extends SceneSystem {
|
|
|
15
15
|
private behaviors;
|
|
16
16
|
private world;
|
|
17
17
|
private scene;
|
|
18
|
+
private time;
|
|
18
19
|
private activeBehaviors;
|
|
19
20
|
constructor(options: SceneSystemOptions);
|
|
20
21
|
onSceneEnter(): void;
|
|
@@ -22,5 +23,6 @@ export declare class BehaviorSystem extends SceneSystem {
|
|
|
22
23
|
private handleActorAdd;
|
|
23
24
|
private handleActorRemove;
|
|
24
25
|
private setUpBehavior;
|
|
25
|
-
update(
|
|
26
|
+
update(): void;
|
|
27
|
+
fixedUpdate(): void;
|
|
26
28
|
}
|
|
@@ -17,12 +17,14 @@ export class BehaviorSystem extends SceneSystem {
|
|
|
17
17
|
behaviors;
|
|
18
18
|
world;
|
|
19
19
|
scene;
|
|
20
|
+
time;
|
|
20
21
|
activeBehaviors;
|
|
21
22
|
constructor(options) {
|
|
22
23
|
super();
|
|
23
|
-
const { actorSpawner, world, scene, globalOptions, resources = [], } = options;
|
|
24
|
+
const { actorSpawner, world, scene, globalOptions, time, resources = [], } = options;
|
|
24
25
|
this.world = world;
|
|
25
26
|
this.scene = scene;
|
|
27
|
+
this.time = time;
|
|
26
28
|
this.behaviorQuery = new ActorQuery({
|
|
27
29
|
scene,
|
|
28
30
|
filter: [Behaviors],
|
|
@@ -79,14 +81,20 @@ export class BehaviorSystem extends SceneSystem {
|
|
|
79
81
|
world: this.world,
|
|
80
82
|
scene: this.scene,
|
|
81
83
|
globalOptions: this.globalOptions,
|
|
84
|
+
time: this.time,
|
|
82
85
|
};
|
|
83
86
|
const BehaviorClass = this.behaviors[config.name];
|
|
84
87
|
return new BehaviorClass(options);
|
|
85
88
|
});
|
|
86
89
|
}
|
|
87
|
-
update(
|
|
90
|
+
update() {
|
|
88
91
|
this.behaviorQuery.getActors().forEach((actor) => {
|
|
89
|
-
this.activeBehaviors[actor.id].forEach((behavior) => behavior.update?.(
|
|
92
|
+
this.activeBehaviors[actor.id].forEach((behavior) => behavior.update?.());
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
fixedUpdate() {
|
|
96
|
+
this.behaviorQuery.getActors().forEach((actor) => {
|
|
97
|
+
this.activeBehaviors[actor.id].forEach((behavior) => behavior.fixedUpdate?.());
|
|
90
98
|
});
|
|
91
99
|
}
|
|
92
100
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Actor, ActorSpawner } from '../../../engine/actor';
|
|
2
2
|
import type { World } from '../../../engine/world';
|
|
3
3
|
import type { Scene } from '../../../engine/scene';
|
|
4
|
+
import type { Time } from '../../../engine/time';
|
|
4
5
|
import type { Constructor } from '../../../types/utils';
|
|
5
6
|
/**
|
|
6
7
|
* Options for the behavior
|
|
@@ -16,13 +17,8 @@ export interface BehaviorOptions {
|
|
|
16
17
|
actorSpawner: ActorSpawner;
|
|
17
18
|
/** Global game options */
|
|
18
19
|
globalOptions: Record<string, unknown>;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
* Options for the update method
|
|
22
|
-
*/
|
|
23
|
-
interface UpdateOptions {
|
|
24
|
-
/** Time elapsed since the last update in milliseconds */
|
|
25
|
-
deltaTime: number;
|
|
20
|
+
/** Shared timing state */
|
|
21
|
+
time: Time;
|
|
26
22
|
}
|
|
27
23
|
/**
|
|
28
24
|
* Base class for all behaviors
|
|
@@ -35,8 +31,10 @@ export declare abstract class Behavior {
|
|
|
35
31
|
static behaviorName: string;
|
|
36
32
|
/** Destroy the behavior */
|
|
37
33
|
destroy?(): void;
|
|
38
|
-
/** Update the behavior */
|
|
39
|
-
update?(
|
|
34
|
+
/** Update the behavior every frame with a variable timestep */
|
|
35
|
+
update?(): void;
|
|
36
|
+
/** Update the behavior with a fixed timestep, aligned with physics */
|
|
37
|
+
fixedUpdate?(): void;
|
|
40
38
|
}
|
|
41
39
|
/**
|
|
42
40
|
* Constructor for all behaviors
|
|
@@ -44,4 +42,3 @@ export declare abstract class Behavior {
|
|
|
44
42
|
export type BehaviorConstructor = Constructor<Behavior> & {
|
|
45
43
|
behaviorName: string;
|
|
46
44
|
};
|
|
47
|
-
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SceneSystem } from '../../../engine/system';
|
|
2
|
-
import type { SceneSystemOptions
|
|
2
|
+
import type { SceneSystemOptions } from '../../../engine/system';
|
|
3
3
|
/**
|
|
4
4
|
* Kinematic character controller system with sweep/slide collision movement.
|
|
5
5
|
*
|
|
@@ -13,9 +13,11 @@ import type { SceneSystemOptions, UpdateOptions } from '../../../engine/system';
|
|
|
13
13
|
export declare class CharacterController extends SceneSystem {
|
|
14
14
|
private actorQuery;
|
|
15
15
|
private world;
|
|
16
|
+
private time;
|
|
16
17
|
private oneWayValidator;
|
|
17
18
|
constructor(options: SceneSystemOptions);
|
|
18
19
|
onSceneDestroy(): void;
|
|
20
|
+
private handleRemoveActor;
|
|
19
21
|
private isBlockingHit;
|
|
20
22
|
private isWalkable;
|
|
21
23
|
private isRecoverableOverlap;
|
|
@@ -28,5 +30,5 @@ export declare class CharacterController extends SceneSystem {
|
|
|
28
30
|
private handleHit;
|
|
29
31
|
private move;
|
|
30
32
|
private updateGroundState;
|
|
31
|
-
fixedUpdate(
|
|
33
|
+
fixedUpdate(): void;
|
|
32
34
|
}
|
|
@@ -3,8 +3,9 @@ import { SceneSystem } from '../../../engine/system';
|
|
|
3
3
|
import { Vector2, VectorOps } from '../../../engine/math-lib';
|
|
4
4
|
import { Collider, CharacterBody, RigidBody, Transform, } from '../../components';
|
|
5
5
|
import { PhysicsAPI } from '../physics-system';
|
|
6
|
-
import { OneWayValidator } from '../../utils/one-way-validator';
|
|
7
6
|
import { CharacterHit } from '../../events';
|
|
7
|
+
import { RemoveActor } from '../../../engine/events';
|
|
8
|
+
import { OneWayValidator } from './one-way-validator';
|
|
8
9
|
import { clipAgainstNormal } from './utils';
|
|
9
10
|
const DISTANCE_EPSILON = 0.000001;
|
|
10
11
|
const SNAP_EPSILON = 0.000001;
|
|
@@ -21,19 +22,26 @@ const SNAP_EPSILON = 0.000001;
|
|
|
21
22
|
export class CharacterController extends SceneSystem {
|
|
22
23
|
actorQuery;
|
|
23
24
|
world;
|
|
25
|
+
time;
|
|
24
26
|
oneWayValidator;
|
|
25
27
|
constructor(options) {
|
|
26
28
|
super();
|
|
27
29
|
this.world = options.world;
|
|
30
|
+
this.time = options.time;
|
|
28
31
|
this.actorQuery = new ActorQuery({
|
|
29
32
|
scene: options.scene,
|
|
30
33
|
filter: [CharacterBody, Transform, Collider, RigidBody],
|
|
31
34
|
});
|
|
35
|
+
this.actorQuery.addEventListener(RemoveActor, this.handleRemoveActor);
|
|
32
36
|
this.oneWayValidator = new OneWayValidator();
|
|
33
37
|
}
|
|
34
38
|
onSceneDestroy() {
|
|
39
|
+
this.actorQuery.removeEventListener(RemoveActor, this.handleRemoveActor);
|
|
35
40
|
this.actorQuery.destroy();
|
|
36
41
|
}
|
|
42
|
+
handleRemoveActor = (event) => {
|
|
43
|
+
this.oneWayValidator.delete(event.actor);
|
|
44
|
+
};
|
|
37
45
|
isBlockingHit(actor, hit) {
|
|
38
46
|
const rigidBody = hit.actor.getComponent(RigidBody);
|
|
39
47
|
if (!rigidBody || rigidBody.disabled) {
|
|
@@ -42,22 +50,18 @@ export class CharacterController extends SceneSystem {
|
|
|
42
50
|
if (!rigidBody?.oneWay || !rigidBody.oneWayNormal) {
|
|
43
51
|
return true;
|
|
44
52
|
}
|
|
45
|
-
return this.oneWayValidator.
|
|
53
|
+
return this.oneWayValidator.shouldBlock(hit.actor, actor, hit.normal);
|
|
46
54
|
}
|
|
47
55
|
isWalkable(actor, normal) {
|
|
48
56
|
const character = actor.getComponent(CharacterBody);
|
|
49
57
|
return (VectorOps.dotProduct(normal, character.upDirection) >=
|
|
50
58
|
Math.cos(character.maxSlopeAngle));
|
|
51
59
|
}
|
|
52
|
-
isRecoverableOverlap(
|
|
60
|
+
isRecoverableOverlap(hit) {
|
|
53
61
|
const rigidBody = hit.actor.getComponent(RigidBody);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!rigidBody.oneWay || !rigidBody.oneWayNormal) {
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
return this.oneWayValidator.validate(hit.actor, actor, hit.normal);
|
|
62
|
+
return (rigidBody !== undefined &&
|
|
63
|
+
!rigidBody.disabled &&
|
|
64
|
+
rigidBody.type !== 'dynamic');
|
|
61
65
|
}
|
|
62
66
|
resetGroundState(character) {
|
|
63
67
|
if (character.onGround) {
|
|
@@ -79,6 +83,7 @@ export class CharacterController extends SceneSystem {
|
|
|
79
83
|
const character = actor.getComponent(CharacterBody);
|
|
80
84
|
const transform = actor.getComponent(Transform);
|
|
81
85
|
const distance = displacement.magnitude;
|
|
86
|
+
this.oneWayValidator.touch(actor);
|
|
82
87
|
return physicsApi.castActor({
|
|
83
88
|
actor,
|
|
84
89
|
offset: {
|
|
@@ -87,7 +92,7 @@ export class CharacterController extends SceneSystem {
|
|
|
87
92
|
},
|
|
88
93
|
direction: displacement,
|
|
89
94
|
maxDistance: distance + character.skinWidth,
|
|
90
|
-
hitFilter,
|
|
95
|
+
hitFilter: (hit) => this.isBlockingHit(actor, hit) && hitFilter(hit),
|
|
91
96
|
});
|
|
92
97
|
}
|
|
93
98
|
castMotion(actor, position, displacement) {
|
|
@@ -96,11 +101,11 @@ export class CharacterController extends SceneSystem {
|
|
|
96
101
|
VectorOps.dotProduct(displacement, hit.normal) > DISTANCE_EPSILON) {
|
|
97
102
|
return false;
|
|
98
103
|
}
|
|
99
|
-
return
|
|
104
|
+
return true;
|
|
100
105
|
});
|
|
101
106
|
}
|
|
102
107
|
castGround(actor, position, displacement) {
|
|
103
|
-
return this.cast(actor, position, displacement, (hit) => this.
|
|
108
|
+
return this.cast(actor, position, displacement, (hit) => this.isWalkable(actor, hit.normal));
|
|
104
109
|
}
|
|
105
110
|
recoverOverlaps(actor, position) {
|
|
106
111
|
const character = actor.getComponent(CharacterBody);
|
|
@@ -119,7 +124,7 @@ export class CharacterController extends SceneSystem {
|
|
|
119
124
|
});
|
|
120
125
|
let recovered = false;
|
|
121
126
|
for (const hit of hits) {
|
|
122
|
-
if (!this.isRecoverableOverlap(
|
|
127
|
+
if (!this.isRecoverableOverlap(hit)) {
|
|
123
128
|
continue;
|
|
124
129
|
}
|
|
125
130
|
const correction = hit.penetration + character.skinWidth;
|
|
@@ -220,11 +225,11 @@ export class CharacterController extends SceneSystem {
|
|
|
220
225
|
target.x += snapDirection.x;
|
|
221
226
|
target.y += snapDirection.y;
|
|
222
227
|
}
|
|
223
|
-
fixedUpdate(
|
|
228
|
+
fixedUpdate() {
|
|
224
229
|
if (!this.world.systemApi.has(PhysicsAPI)) {
|
|
225
230
|
return;
|
|
226
231
|
}
|
|
227
|
-
const
|
|
232
|
+
const { fixedDeltaTime } = this.time;
|
|
228
233
|
this.oneWayValidator.update();
|
|
229
234
|
this.actorQuery.getActors().forEach((actor) => {
|
|
230
235
|
const transform = actor.getComponent(Transform);
|
|
@@ -243,7 +248,7 @@ export class CharacterController extends SceneSystem {
|
|
|
243
248
|
this.recoverOverlaps(actor, position);
|
|
244
249
|
const displacement = character.velocity
|
|
245
250
|
.clone()
|
|
246
|
-
.multiplyNumber(
|
|
251
|
+
.multiplyNumber(fixedDeltaTime)
|
|
247
252
|
.add(character._displacement);
|
|
248
253
|
const movingUp = VectorOps.dotProduct(displacement, character.upDirection) >
|
|
249
254
|
SNAP_EPSILON;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Actor } from '../../../engine/actor';
|
|
2
|
+
import { type Point } from '../../../engine/math-lib';
|
|
3
|
+
export declare class OneWayValidator {
|
|
4
|
+
private ignoredOneWayContacts;
|
|
5
|
+
private touchedActors;
|
|
6
|
+
private oneWayContactUpdateIndex;
|
|
7
|
+
constructor();
|
|
8
|
+
private clearOneWayContacts;
|
|
9
|
+
private trackOneWayContact;
|
|
10
|
+
touch(actor: Actor): void;
|
|
11
|
+
shouldBlock(oneWayActor: Actor, otherActor: Actor, normal: Point): boolean;
|
|
12
|
+
delete(actor: Actor): void;
|
|
13
|
+
update(): void;
|
|
14
|
+
lateUpdate(): void;
|
|
15
|
+
}
|