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   package this(Entity entity, Shape shape)
25   {
26     _entity = entity;
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   @property bool collisionOccured()
40   {
41     return collisions.length > 0;
42   }
43 
44   ///
45   Vector2 getSize();
46   ///
47   bool intersects(RectCollider collider);
48   ///
49   bool intersects(CircleCollider collider);
50   ///
51   bool intersects(PointCollider collider);
52   ///
53   Vector2 resolve(RectCollider collider);
54   ///
55   Vector2 resolve(CircleCollider collider);
56   ///
57   Vector2 resolve(PointCollider collider);
58 
59   ///
60   Vector2 getPosition()
61   {
62     return Vector2(
63       entity.position.x + offset.x,
64       entity.position.y + offset.y
65     );
66   }
67 
68   ///
69   Rect getBounds()
70   {
71     Vector2 size = getSize();
72     Vector2 position = getPosition();
73 
74     return Rect(
75       position.x - size.x / 2,
76       position.y + size.y / 2,
77       size.x,
78       size.y
79     );
80   }
81 
82   ///
83   void addTag(int tag)
84   {
85     tags.insertBack(tag);
86   }
87 
88   ///
89   void removeTag(int tag)
90   {
91     tags.remove(tag);
92   }
93 
94   ///
95   bool hasTag(int tag)
96   {
97     return tags.contains(tag);
98   }
99 
100   ///
101   bool intersects(Collider2D collider)
102   {
103     final switch(collider._shape)
104     {
105       case Shape.POINT:
106         return intersects(cast(PointCollider) collider);
107       case Shape.CIRCLE:
108         return intersects(cast(CircleCollider) collider);
109       case Shape.RECTANGLE:
110         return intersects(cast(RectCollider) collider);
111     }
112   }
113 
114   /// Returns a vector that can be used to move the entity out of the collider
115   Vector2 resolve(Collider2D collider)
116   {
117     final switch(collider._shape)
118     {
119       case Shape.POINT:
120         return resolve(cast(PointCollider) collider);
121       case Shape.CIRCLE:
122         return resolve(cast(CircleCollider) collider);
123       case Shape.RECTANGLE:
124         return resolve(cast(RectCollider) collider);
125     }
126   }
127 }