-
-
Notifications
You must be signed in to change notification settings - Fork 189
/
CollisionContact.ts
113 lines (99 loc) · 2.87 KB
/
CollisionContact.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { Vector } from '../../Math/vector';
import { Physics } from '../Physics';
import { Collider } from '../Colliders/Collider';
import { CollisionType } from '../CollisionType';
import { Pair } from './Pair';
import { SeparationInfo } from '../Colliders/SeparatingAxis';
import { BodyComponent } from '../BodyComponent';
/**
* Collision contacts are used internally by Excalibur to resolve collision between colliders. This
* Pair prevents collisions from being evaluated more than one time
*/
export class CollisionContact {
private _canceled = false;
/**
* Currently the ids between colliders
*/
readonly id: string;
/**
* The first collider in the collision
*/
colliderA: Collider;
/**
* The second collider in the collision
*/
colliderB: Collider;
/**
* The minimum translation vector to resolve overlap, pointing away from colliderA
*/
mtv: Vector;
/**
* World space contact points between colliderA and colliderB
*/
points: Vector[];
/**
* Local space contact points between colliderA and colliderB
*/
localPoints: Vector[];
/**
* The collision normal, pointing away from colliderA
*/
normal: Vector;
/**
* The collision tangent
*/
tangent: Vector;
/**
* Information about the specifics of the collision contact separation
*/
info: SeparationInfo;
constructor(
colliderA: Collider,
colliderB: Collider,
mtv: Vector,
normal: Vector,
tangent: Vector,
points: Vector[],
localPoints: Vector[],
info: SeparationInfo
) {
this.colliderA = colliderA;
this.colliderB = colliderB;
this.mtv = mtv;
this.normal = normal;
this.tangent = tangent;
this.points = points;
this.localPoints = localPoints;
this.info = info;
this.id = Pair.calculatePairHash(colliderA.id, colliderB.id);
if (colliderA.__compositeColliderId || colliderB.__compositeColliderId) {
// Add on the parent composite pair for start/end contact
this.id += '|' + Pair.calculatePairHash(
colliderA.__compositeColliderId ?? colliderA.id,
colliderB.__compositeColliderId ?? colliderB.id);
}
}
/**
* Match contact awake state, except if body's are Fixed
*/
public matchAwake(): void {
const bodyA = this.colliderA.owner.get(BodyComponent);
const bodyB = this.colliderB.owner.get(BodyComponent);
if (bodyA && bodyB) {
if (bodyA.sleeping !== bodyB.sleeping) {
if (bodyA.sleeping && bodyA.collisionType !== CollisionType.Fixed && bodyB.sleepMotion >= Physics.wakeThreshold) {
bodyA.setSleeping(false);
}
if (bodyB.sleeping && bodyB.collisionType !== CollisionType.Fixed && bodyA.sleepMotion >= Physics.wakeThreshold) {
bodyB.setSleeping(false);
}
}
}
}
public isCanceled() {
return this._canceled;
}
public cancel(): void {
this._canceled = true;
}
}