1
+ import { EntityList } from "./Entities.js" ;
2
+ import { vector2D } from "../Types/Types" ;
3
+ import { Entity } from "./Entity.js" ;
4
+
5
+ /**
6
+ * Gets the list of Entities with the given tag(s) that are overlapping the specified Entity.
7
+ * @param self The main Entity we are testing against.
8
+ * @param tags The tags that are used for filtering. Only one must apply to an Entity in order to be tested.
9
+ */
10
+ export function GetCollisionsByTag ( self : Entity , tags : string [ ] ) : Array < Entity > {
11
+ let collisionObjects = [ ] ;
12
+ for ( const target of EntityList ) {
13
+ const isMatching = tags . some ( tag => target . Tags . includes ( tag ) ) ;
14
+ if ( isMatching ) {
15
+ // We need to check both self -> target, and target -> self
16
+ // because in some cases (target is bigger than self) it's possible for vertices not be inside self or target
17
+ if ( isOverlapping ( self , target ) || isOverlapping ( target , self ) )
18
+ {
19
+ collisionObjects . push ( target ) ;
20
+ }
21
+ }
22
+ }
23
+ return collisionObjects ;
24
+ }
25
+
26
+ /**
27
+ * Checks if two Entities are overlapping eachother.
28
+ * @param entityA
29
+ * @param entityB
30
+ */
31
+ export function GetCollision ( entityA : Entity , entityB : Entity ) : boolean {
32
+ if ( isOverlapping ( entityA , entityB ) || isOverlapping ( entityB , entityA ) )
33
+ {
34
+ return true ;
35
+ }
36
+ return false ;
37
+ }
38
+
39
+ /**
40
+ * Gets the list of every Entity that is colliding with the target. Note that this tests against every registered Entity, which can be extremely slow.
41
+ * @param target
42
+ */
43
+ export function GetCollisions ( target : Entity ) : Array < Entity > {
44
+ let collisionObjects = [ ] ;
45
+ for ( const target of EntityList ) {
46
+ if ( isOverlapping ( target , target ) || isOverlapping ( target , target ) )
47
+ {
48
+ collisionObjects . push ( target ) ;
49
+ }
50
+ }
51
+ return collisionObjects ;
52
+ }
53
+
54
+
55
+ function isOverlapping ( self : Entity , target : Entity ) : boolean {
56
+ let overlap = false ;
57
+ for ( let testVertexIndex = 0 ; testVertexIndex < target . Vertices . length ; testVertexIndex ++ ) {
58
+ // Assume we have a collision
59
+ let isTestVertexInsideSelf = true ;
60
+ let isTestEdgeIntersect = false ;
61
+ // Get the vertex, whose orientation we want to check relative to the line
62
+ const target_pointA_index = testVertexIndex ;
63
+ const target_pointA = target . Vertices [ target_pointA_index ] ;
64
+ const target_pointB_index = ( testVertexIndex + 1 < self . Vertices . length ) ? ( testVertexIndex + 1 ) : ( 0 ) ;
65
+ const target_pointB = target . Vertices [ target_pointB_index ] ;
66
+ // Check vertex against self's every edge
67
+ for ( let selfVertexIndex = 0 ; selfVertexIndex < self . Vertices . length ; selfVertexIndex ++ ) {
68
+ const self_pointA_index = selfVertexIndex ;
69
+ // Wrap-around for the final edge
70
+ const self_pointB_index = ( selfVertexIndex + 1 < self . Vertices . length ) ? ( selfVertexIndex + 1 ) : ( 0 ) ;
71
+ const self_pointA = self . Vertices [ self_pointA_index ] ;
72
+ const self_pointB = self . Vertices [ self_pointB_index ] ;
73
+ // Check if testVertex is to the right of self's edge (counter-clockwise)
74
+ const doEdgesIntersect = ( ( isLeft ( self_pointA , self_pointB , target_pointB ) . edge != isLeft ( self_pointA , self_pointB , target_pointA ) . edge ) && ( isLeft ( target_pointA , target_pointB , self_pointA ) . edge != isLeft ( target_pointA , target_pointB , self_pointB ) . edge ) ) ;
75
+ const isPointWithinSelf = isLeft ( self_pointA , self_pointB , target_pointA ) . point ;
76
+ if ( doEdgesIntersect ) {
77
+ // If true, we can ignore the rest of the edges, since one intersecting edge means collision
78
+ isTestEdgeIntersect = true ;
79
+ break ;
80
+ }
81
+ else if ( isPointWithinSelf == false ) {
82
+ // If false, we can ignore the rest of the edges, since this MUST be true to ALL edges
83
+ isTestVertexInsideSelf = false ;
84
+ break ;
85
+ }
86
+ }
87
+ if ( isTestEdgeIntersect == true || isTestVertexInsideSelf == true ) {
88
+ // testVertex is inside self
89
+ overlap = true ;
90
+ break ;
91
+ }
92
+ }
93
+ return overlap ;
94
+ }
95
+
96
+ function isLeft ( pointA : vector2D , pointB : vector2D , pointF : vector2D ) {
97
+ const BAx = pointB . x - pointA . x ;
98
+ const FAy = pointF . y - pointA . y ;
99
+ const BAy = pointB . y - pointA . y ;
100
+ const FAx = pointF . x - pointA . x ;
101
+ //
102
+ const first = BAx * FAy ;
103
+ const second = BAy * FAx ;
104
+ //
105
+ return {
106
+ edge : ( first > second ) ,
107
+ point : ( first - second > 0 ) ,
108
+ } ;
109
+ }
0 commit comments