]> git.localhorst.tv Git - orbi.git/blob - src/world/World.cpp
entity/entity collision stub
[orbi.git] / src / world / World.cpp
1 #include "World.h"
2
3 #include "Collision.h"
4 #include "../graphics/const.h"
5
6 #include <algorithm>
7 #include <cmath>
8
9 using namespace std;
10
11
12 namespace orbi {
13
14 World::World(Vector<int> size)
15 : size(size)
16 , count(size.x * size.y)
17 , gravity(0, 5)
18 , terminal(50, 50)
19 , fixSpeed(5)
20 , tiles(count) {
21
22 }
23
24
25 void World::Update(float dt) {
26         for (Entity &e : entities) {
27                 e.Update(dt, gravity, terminal);
28                 e.onGround = false;
29
30                 BoundsCollision(e, dt);
31                 TileCollision(e, dt);
32
33         }
34 }
35
36 void World::BoundsCollision(Entity &e, float dt) {
37         if (e.vbox.Top() < 0) {
38                 e.Move(Vector<float>(0, -e.vbox.Top()));
39                 e.vel.y = 0;
40         }
41         if (e.vbox.Bottom() > size.y) {
42                 e.Move(Vector<float>(0, size.y - e.vbox.Bottom()));
43                 e.vel.y = 0;
44                 e.onGround = true;
45         }
46         if (e.hbox.Right() > size.x) {
47                 e.Move(Vector<float>(size.x - e.hbox.Right(), 0));
48                 e.vel.x = 0;
49         }
50         if (e.hbox.Left() < 0) {
51                 e.Move(Vector<float>(-e.hbox.Left(), 0));
52                 e.vel.x = 0;
53         }
54 }
55
56 void World::TileCollision(Entity &e, float dt) {
57         Vector<float> response;
58
59         // top
60         for (int x = e.vbox.Left(), y = e.vbox.Top(),
61                         end = std::ceil(e.vbox.Right()); x < end; ++x) {
62                 const Tile &tile = TileAt(Vector<int>(x, y));
63                 if (tile.IsSolid()) {
64                         response.y = y + 1 - e.vbox.Top();
65                         e.vel.y = 0;
66                         break;
67                 }
68         }
69
70         // bottom
71         for (int x = e.vbox.Left(), y = e.vbox.Bottom(),
72                         end = std::ceil(e.vbox.Right()); x < end; ++x) {
73                 const Tile &tile = TileAt(Vector<int>(x, y));
74                 if (tile.IsSolid()) {
75                         response.y = y - e.vbox.Bottom();
76                         e.onGround = true;
77                         e.vel.y = 0;
78                         break;
79                 }
80         }
81         if (response.y <= 0) {
82                 // bottom, second row
83                 // due to the hbox's huge bottom gap
84                 for (int x = e.vbox.Left(), y = e.vbox.Bottom() - 1,
85                                 end = std::ceil(e.vbox.Right()); x < end; ++x) {
86                         const Tile &tile = TileAt(Vector<int>(x, y));
87                         if (tile.IsSolid()) {
88                                 response.y = -1;
89                                 e.onGround = true;
90                                 e.vel.y = 0;
91                                 break;
92                         }
93                 }
94         }
95
96         // left
97         for (int y = e.hbox.Top(), x = e.hbox.Left(),
98                         end = std::ceil(e.hbox.Bottom()); y < end; ++y) {
99                 const Tile &tile = TileAt(Vector<int>(x, y));
100                 if (tile.IsSolid()) {
101                         response.x = x + 1 - e.hbox.Left();
102                         e.vel.x = 0;
103                         break;
104                 }
105         }
106
107         // right
108         for (int y = e.hbox.Top(), x = e.hbox.Right(),
109                         end = std::ceil(e.hbox.Bottom()); y < end; ++y) {
110                 const Tile &tile = TileAt(Vector<int>(x, y));
111                 if (tile.IsSolid()) {
112                         response.x = x - e.hbox.Right();
113                         e.vel.x = 0;
114                         break;
115                 }
116         }
117
118         if (response.x > fixSpeed * dt) {
119                 response.x = fixSpeed * dt;
120         } else if (response.x < -fixSpeed * dt) {
121                 response.x = -fixSpeed * dt;
122         }
123         if (response.y > fixSpeed * dt) {
124                 response.y = fixSpeed * dt;
125         } else if (response.y < -fixSpeed * dt) {
126                 response.y = -fixSpeed * dt;
127         }
128         e.Move(response);
129 }
130
131 void World::EntityCollision() {
132         if (entities.size() <= 1) return;
133
134         auto firstEnd(entities.end());
135         --firstEnd;
136         for (auto first(entities.begin()); first != firstEnd; ++first) {
137                 auto second(first);
138                 ++second;
139                 for (auto secondEnd(entities.end()); second != secondEnd; ++second) {
140                         if (first->bounds.Intersects(second->bounds)) {
141                                 // damage + knockback
142                         }
143                 }
144         }
145 }
146
147
148 const AABB &World::TileShapeAt(Vector<int> pos) const {
149         tileShape = AABB(pos, Vector<float>(1, 1));
150         return tileShape;
151 }
152
153
154 Entity &World::AddEntity(const Entity &e) {
155         entities.emplace_back(e);
156         return entities.back();
157 }
158
159 }