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 }