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