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