1 module prova.collision.collider2d;
2
3 import prova.collision,
4 prova.collision.intersects,
5 prova.collision.resolve,
6 prova.core,
7 prova.graphics,
8 prova.math,
9 prova.util;
10
11 package enum Shape { POINT, RECTANGLE, CIRCLE }
12
13 ///
14 abstract class Collider2D
15 {
16 ///
17 Vector2 offset;
18 package LinkedList!(Collider2D) collisions;
19 package LinkedList!(Collider2D) previousCollisions;
20 private LinkedList!(int) tags;
21 private Entity _entity;
22 private Shape _shape;
23
24 ///
25 package this(Shape shape)
26 {
27 _shape = shape;
28 collisions = new LinkedList!(Collider2D);
29 tags = new LinkedList!(int);
30 }
31
32 ///
33 @property Entity entity()
34 {
35 return _entity;
36 }
37
38 ///
39 package(prova) @property void entity(Entity entity)
40 {
41 _entity = entity;
42 }
43
44 ///
45 @property bool collisionOccured()
46 {
47 return collisions.length > 0;
48 }
49
50 ///
51 Vector2 getSize();
52 ///
53 bool intersects(RectCollider collider);
54 ///
55 bool intersects(CircleCollider collider);
56 ///
57 bool intersects(PointCollider collider);
58 ///
59 Vector2 resolve(RectCollider collider);
60 ///
61 Vector2 resolve(CircleCollider collider);
62 ///
63 Vector2 resolve(PointCollider collider);
64
65 ///
66 Vector2 getPosition()
67 {
68 Vector3 position = _entity.getWorldPosition();
69
70 return Vector2(position.x, position.y);
71 }
72
73 ///
74 Rect getBounds()
75 {
76 Vector2 size = getSize();
77 Vector2 position = getPosition();
78
79 return Rect(
80 position.x - size.x / 2,
81 position.y + size.y / 2,
82 size.x,
83 size.y
84 );
85 }
86
87 ///
88 void addTag(int tag)
89 {
90 tags.insertBack(tag);
91 }
92
93 ///
94 void removeTag(int tag)
95 {
96 tags.remove(tag);
97 }
98
99 ///
100 bool hasTag(int tag)
101 {
102 return tags.contains(tag);
103 }
104
105 ///
106 bool intersects(Collider2D collider)
107 {
108 final switch(collider._shape)
109 {
110 case Shape.POINT:
111 return intersects(cast(PointCollider) collider);
112 case Shape.CIRCLE:
113 return intersects(cast(CircleCollider) collider);
114 case Shape.RECTANGLE:
115 return intersects(cast(RectCollider) collider);
116 }
117 }
118
119 /// Returns a vector that can be used to move the entity out of the collider
120 Vector2 resolve(Collider2D collider)
121 {
122 final switch(collider._shape)
123 {
124 case Shape.POINT:
125 return resolve(cast(PointCollider) collider);
126 case Shape.CIRCLE:
127 return resolve(cast(CircleCollider) collider);
128 case Shape.RECTANGLE:
129 return resolve(cast(RectCollider) collider);
130 }
131 }
132 }