1 module prova.attachables.colliders.collider2d;
2 
3 import prova;
4 
5 package(prova) enum Shape { POINT, RECTANGLE, CIRCLE }
6 
7 ///
8 abstract class Collider2D
9 {
10   ///
11   Vector2 offset;
12   package(prova) LinkedList!(Collider2D) collisions;
13   package(prova) LinkedList!(Collider2D) previousCollisions;
14   package(prova) SpacialMap2D spacialMap;
15   private LinkedList!(int) tags;
16   private Entity _entity;
17   private Shape _shape;
18 
19   ///
20   package this(Shape shape)
21   {
22     _shape = shape;
23     collisions = new LinkedList!(Collider2D);
24     tags = new LinkedList!(int);
25   }
26 
27   ///
28   @property Entity entity()
29   {
30     return _entity;
31   }
32 
33   ///
34   package(prova) @property void entity(Entity entity)
35   {
36     _entity = entity;
37   }
38 
39   ///
40   @property bool collisionOccured()
41   {
42     return collisions.length > 0;
43   }
44 
45   ///
46   Vector2 getSize();
47   ///
48   bool intersects(RectCollider collider);
49   ///
50   bool intersects(CircleCollider collider);
51   ///
52   bool intersects(PointCollider collider);
53   ///
54   Vector2 resolve(RectCollider collider);
55   ///
56   Vector2 resolve(CircleCollider collider);
57   ///
58   Vector2 resolve(PointCollider collider);
59 
60   ///
61   Vector2 getPosition()
62   {
63     Vector3 position = _entity.getWorldPosition();
64 
65     return Vector2(position.x, position.y) + offset;
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 
128   /// Should be called when a collider is resized
129   protected void updateSize()
130   {
131     if(spacialMap) {
132       spacialMap.updateBucketSize(this);
133     }
134   }
135 }