excalibur 0.32.0-alpha.19 → 0.32.0-alpha.20

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/CHANGELOG.md CHANGED
@@ -7,7 +7,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
8
  ### Breaking Changes
9
9
 
10
- -
10
+ - Behavior change: Realistic physics bodies can now sleep by default `canSleepByDefault`
11
+ - Behavior change: The `sleepBias` default is lowered to 0.5 from .9
12
+ - Behavior change: Bodies do not sleep until all bodies in an Island are low motion for at least `sleepTimeThreshold`, default 1000ms
13
+ - Debug: Improve body related information output in the debug draw
11
14
 
12
15
  ### Deprecated
13
16
 
@@ -16,6 +19,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
16
19
 
17
20
  ### Added
18
21
 
22
+ - Added new contact `ex.Island` physics optimization, excalibur physics bodies will now wake or sleep the entire connected graph of bodies,
23
+ this only works in the Realistic solver, but it's a huge perf win.
24
+ - Added new `ex.angleDifference(angle1, angle2)` for calculating differences between angles in [0, 2Pi)
25
+ - Added new debug stats to the frame to measure ECS system durations in milliseconds
26
+ ```typescript
27
+ const stats: Record<string, number> = engine.stats.currFrame.systemDuration;
28
+ // "update:CollisionSystem.update" -> .50
19
29
 
20
30
  - Added new parameter to `ex.Sounds` to schedule start time, this allows you to synchronize playback of multiple audio tracks
21
31
  ```typescript
@@ -102,6 +112,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
102
112
 
103
113
  ### Fixed
104
114
 
115
+ - Fixed possible perf issue in `canonicalizeAngle` if a large angle was provided it could take a long time
116
+ - Fixed issue where physics bodies did not sleep under certain situations, especially when gravity was high.
105
117
  - Fixed issue where Animation fromSpriteSheet was ignoring repeated sprite sheet indices
106
118
  - Fixed issue where setting the width/height of a ScreenElement was incorrectly scaled when supplied with a scale in the ctor
107
119
  - Fixed issue where onRemove would sometimes not be called
@@ -8,9 +8,9 @@ import { CollisionGroup } from './Group/CollisionGroup';
8
8
  import type { Id } from '../Id';
9
9
  import { Transform } from '../Math/transform';
10
10
  import { EventEmitter } from '../EventEmitter';
11
- import type { PhysicsConfig } from './PhysicsConfig';
12
- import type { DeepRequired } from '../Util/Required';
11
+ import type { BodyConfig, PhysicsConfig } from './PhysicsConfig';
13
12
  import type { Entity } from '../EntityComponentSystem';
13
+ import type { Island } from './Island';
14
14
  export interface BodyComponentOptions {
15
15
  type?: CollisionType;
16
16
  group?: CollisionGroup;
@@ -31,6 +31,7 @@ export declare class BodyComponent extends Component implements Clonable<BodyCom
31
31
  static _ID: number;
32
32
  readonly id: Id<'body'>;
33
33
  events: EventEmitter<any>;
34
+ island: Island | null;
34
35
  oldTransform: Transform;
35
36
  /**
36
37
  * Indicates whether the old transform has been captured at least once for interpolation
@@ -44,18 +45,21 @@ export declare class BodyComponent extends Component implements Clonable<BodyCom
44
45
  private _bodyConfig;
45
46
  private static _DEFAULT_CONFIG;
46
47
  wakeThreshold: number;
48
+ sleepTime: number;
47
49
  constructor(options?: BodyComponentOptions);
48
50
  get matrix(): import("..").AffineMatrix;
49
51
  /**
50
52
  * Called by excalibur to update physics config defaults if they change
51
53
  * @param config
52
54
  */
53
- updatePhysicsConfig(config: DeepRequired<Pick<PhysicsConfig, 'bodies'>['bodies']>): void;
55
+ updatePhysicsConfig(config: BodyConfig): void;
56
+ get canFallAsleep(): boolean;
57
+ get canWakeUp(): boolean;
54
58
  /**
55
59
  * Called by excalibur to update defaults
56
60
  * @param config
57
61
  */
58
- static updateDefaultPhysicsConfig(config: DeepRequired<Pick<PhysicsConfig, 'bodies'>['bodies']>): void;
62
+ static updateDefaultPhysicsConfig(config: BodyConfig): void;
59
63
  /**
60
64
  * Collision type for the rigidbody physics simulation, by default {@apilink CollisionType.PreventCollision}
61
65
  */
@@ -98,11 +102,13 @@ export declare class BodyComponent extends Component implements Clonable<BodyCom
98
102
  * @deprecated use isSleeping
99
103
  */
100
104
  setSleeping(sleeping: boolean): void;
105
+ wake(): void;
106
+ sleep(): void;
101
107
  set isSleeping(sleeping: boolean);
102
108
  /**
103
109
  * Update body's {@apilink BodyComponent.sleepMotion} for the purpose of sleeping
104
110
  */
105
- updateMotion(): void;
111
+ updateMotion(duration: number): void;
106
112
  private _cachedInertia;
107
113
  /**
108
114
  * Get the moment of inertia from the {@apilink ColliderComponent}
@@ -6,11 +6,13 @@ import { ColliderComponent } from './ColliderComponent';
6
6
  import type { ExcaliburGraphicsContext } from '../Graphics/Context/ExcaliburGraphicsContext';
7
7
  import type { Scene } from '../Scene';
8
8
  import type { PhysicsWorld } from './PhysicsWorld';
9
+ import { BodyComponent } from './Index';
9
10
  export declare class CollisionSystem extends System {
10
11
  private _physics;
11
12
  static priority: -5;
12
13
  systemType: SystemType;
13
14
  query: Query<ComponentCtor<TransformComponent> | ComponentCtor<ColliderComponent>>;
15
+ bodyQuery: Query<ComponentCtor<BodyComponent>>;
14
16
  private _engine;
15
17
  private _configDirty;
16
18
  private _realisticSolver;
@@ -18,6 +20,7 @@ export declare class CollisionSystem extends System {
18
20
  private _lastFrameContacts;
19
21
  private _currentFrameContacts;
20
22
  private _motionSystem;
23
+ private _bodies;
21
24
  private get _processor();
22
25
  private _trackCollider;
23
26
  private _untrackCollider;
@@ -47,10 +47,6 @@ export declare class CollisionContact {
47
47
  bodyA: BodyComponent | null;
48
48
  bodyB: BodyComponent | null;
49
49
  constructor(colliderA: Collider, colliderB: Collider, mtv: Vector, normal: Vector, tangent: Vector, points: Vector[], localPoints: Vector[], info: SeparationInfo);
50
- /**
51
- * Match contact awake state, except if body's are Fixed
52
- */
53
- matchAwake(): void;
54
50
  isCanceled(): boolean;
55
51
  cancel(): void;
56
52
  /**
@@ -0,0 +1,13 @@
1
+ import type { BodyConfig } from './Index';
2
+ import { type BodyComponent, type CollisionContact } from './Index';
3
+ export declare class Island {
4
+ config: BodyConfig;
5
+ bodies: BodyComponent[];
6
+ contacts: CollisionContact[];
7
+ isSleeping: boolean;
8
+ constructor(config: BodyConfig);
9
+ wake(): void;
10
+ sleep(): void;
11
+ updateSleepState(elapsed: number): void;
12
+ }
13
+ export declare function buildContactIslands(config: BodyConfig, bodies: BodyComponent[], contacts: CollisionContact[]): Island[];
@@ -10,6 +10,7 @@ export declare class MotionSystem extends System {
10
10
  systemType: SystemType;
11
11
  private _physicsConfigDirty;
12
12
  query: Query<typeof TransformComponent | typeof MotionComponent>;
13
+ private _createPhysicsQuery;
13
14
  constructor(world: World, physics: PhysicsWorld);
14
15
  update(elapsed: number): void;
15
16
  captureOldTransformWithChildren(entity: Entity): void;
@@ -119,23 +119,34 @@ export interface PhysicsConfig {
119
119
  */
120
120
  defaultMass?: number;
121
121
  /**
122
- * Sleep epsilon
122
+ * Sleep epsilon - (small number) this is the amount of massless kinetic energy a body needs to be below to fall asleep
123
123
  *
124
124
  * Default 0.07
125
125
  */
126
126
  sleepEpsilon?: number;
127
127
  /**
128
- * Wake Threshold, the amount of "motion" need to wake a body from sleep
128
+ * Wake Threshold - the amount of "motion" or massless kinetic energy need to wake a body from sleep
129
129
  *
130
130
  * Default 0.07 * 3;
131
131
  */
132
132
  wakeThreshold?: number;
133
133
  /**
134
- * Sleep bias
134
+ * Sleep bias - The weighted average to apply to the current frame body motion over one second
135
135
  *
136
- * Default 0.9
136
+ * ```typescript
137
+ * let bias = Math.pos(sleepBias, durationSeconds);
138
+ * let motion = bias * previousAverageMotion + (1 - bias) * currentFrameMotion;
139
+ * ```
140
+ *
141
+ * Default 0.5
137
142
  */
138
143
  sleepBias?: number;
144
+ /**
145
+ * Amount of time that bodies (in contact islands) need to be below the sleepEpsilon
146
+ *
147
+ * Default 1000ms
148
+ */
149
+ sleepTimeThreshold?: number;
139
150
  /**
140
151
  * By default bodies do not sleep, this can be turned on to improve perf if you have a lot of bodies.
141
152
  *
@@ -204,4 +215,5 @@ export interface PhysicsConfig {
204
215
  warmStart?: boolean;
205
216
  };
206
217
  }
218
+ export type BodyConfig = DeepRequired<Pick<PhysicsConfig, 'bodies'>['bodies']>;
207
219
  export declare const getDefaultPhysicsConfig: () => DeepRequired<PhysicsConfig>;
@@ -27,6 +27,7 @@ export declare class PhysicsWorld {
27
27
  sleepEpsilon?: number;
28
28
  wakeThreshold?: number;
29
29
  sleepBias?: number;
30
+ sleepTimeThreshold?: number;
30
31
  canSleepByDefault?: boolean;
31
32
  }>;
32
33
  spatialPartition?: SpatialPartitionStrategy;
@@ -21,5 +21,5 @@ export interface CollisionSolver {
21
21
  * 4. postSolve
22
22
  * @param contacts
23
23
  */
24
- solve(contacts: CollisionContact[]): CollisionContact[];
24
+ solve(contacts: CollisionContact[], duration?: number): CollisionContact[];
25
25
  }
@@ -32,6 +32,10 @@ export interface FrameStatistics {
32
32
  * Duration statistics (in ms)
33
33
  */
34
34
  duration: FrameDurationStats;
35
+ /**
36
+ * Duration statistics (in ms) for ECS systems
37
+ */
38
+ systemDuration: Record<string, number>;
35
39
  /**
36
40
  * Actor statistics
37
41
  */
@@ -296,6 +300,7 @@ export declare class FrameStats implements FrameStatistics {
296
300
  private _durationStats;
297
301
  private _physicsStats;
298
302
  private _graphicsStats;
303
+ systemDuration: Record<string, number>;
299
304
  /**
300
305
  * Zero out values or clone other IFrameStat stats. Allows instance reuse.
301
306
  * @param [otherStats] Optional stats to clone
@@ -24,6 +24,10 @@ export declare function approximatelyEqual(val1: number, val2: number, tolerance
24
24
  * Convert an angle to be the equivalent in the range [0, 2PI)
25
25
  */
26
26
  export declare function canonicalizeAngle(angle: number): number;
27
+ /**
28
+ * Return the different in angles in the range [0, 2PI)
29
+ */
30
+ export declare function angleDifference(angle1: number, angle2: number): number;
27
31
  /**
28
32
  * Convert radians to degrees
29
33
  */