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