]> git.localhorst.tv Git - orbi.git/blob - src/collision.cpp
initial collision tests
[orbi.git] / src / collision.cpp
1 #include "app/SDL.h"
2 #include "graphics/Camera.h"
3 #include "graphics/Canvas.h"
4 #include "graphics/Color.h"
5 #include "graphics/Vector.h"
6 #include "graphics/Window.h"
7 #include "world/AABB.h"
8
9 #include <SDL.h>
10 #include <vector>
11
12 using namespace orbi;
13 using namespace std;
14
15
16 namespace {
17
18 struct World {
19
20         bool alive;
21
22         Vector<float> focus;
23         Camera cam;
24
25         Vector<int> move;
26
27         AABB controlled;
28         vector<AABB> stationary;
29
30         struct Collision {
31                 Vector<float> pos;
32                 Vector<float> norm;
33                 Vector<float> depth;
34         };
35         vector<Collision> coll;
36
37         World()
38         : alive(true)
39         , focus()
40         , cam(Vector<int>(), focus)
41         , controlled()
42         , stationary()
43         { }
44
45 };
46
47 void key_down(const SDL_KeyboardEvent &e, World &world) {
48         switch (e.keysym.sym) {
49                 case SDLK_UP:
50                         world.move.y -= 1;
51                         break;
52                 case SDLK_DOWN:
53                         world.move.y += 1;
54                         break;
55                 case SDLK_LEFT:
56                         world.move.x -= 1;
57                         break;
58                 case SDLK_RIGHT:
59                         world.move.x += 1;
60                         break;
61                 default:
62                         break;
63         }
64 }
65
66 void key_up(const SDL_KeyboardEvent &e, World &world) {
67         switch (e.keysym.sym) {
68                 case SDLK_UP:
69                         world.move.y += 1;
70                         break;
71                 case SDLK_DOWN:
72                         world.move.y -= 1;
73                         break;
74                 case SDLK_LEFT:
75                         world.move.x += 1;
76                         break;
77                 case SDLK_RIGHT:
78                         world.move.x -= 1;
79                         break;
80                 default:
81                         break;
82         }
83 }
84
85 void handle(World &world) {
86         SDL_Event event;
87         while (SDL_PollEvent(&event)) {
88                 switch (event.type) {
89                         case SDL_QUIT:
90                                 world.alive = false;
91                                 break;
92                         case SDL_WINDOWEVENT:
93                                 if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
94                                         world.cam.Resize(event.window.data1, event.window.data2);
95                                 }
96                                 break;
97                         case SDL_KEYDOWN:
98                                 if (!event.key.repeat) {
99                                         key_down(event.key, world);
100                                 }
101                                 break;
102                         case SDL_KEYUP:
103                                 if (!event.key.repeat) {
104                                         key_up(event.key, world);
105                                 }
106                                 break;
107                 }
108         }
109 }
110
111 void update(int dt, World &world) {
112         const Vector<float> speed { 5, 5 };
113
114         const float delta = dt / 1e3;
115
116         world.controlled.Move(Vector<float>(world.move) * speed * delta);
117         world.focus = world.controlled.Center();
118
119         world.coll.clear();
120         for (const AABB &e : world.stationary) {
121                 World::Collision coll;
122                 if (world.controlled.Intersects(
123                                 e,
124                                 coll.pos,
125                                 coll.norm,
126                                 coll.depth)) {
127                         world.coll.push_back(coll);
128                 }
129         }
130 }
131
132 void render(Canvas &canvas, const World &world) {
133         constexpr Color background(0x00, 0x00, 0x00);
134         constexpr Color outlineColor(0x00, 0x00, 0xFA);
135         constexpr Color controlledColor(0xFA, 0xFA, 0x00);
136         constexpr Color entityColor(0x00, 0xFA, 0x00);
137         constexpr Color collisionColor(0xFA, 0x00, 0x00);
138         constexpr Color normalColor(0xFA, 0x00, 0x00);
139
140         canvas.SetColor(background);
141         canvas.Fill();
142
143         canvas.SetColor(outlineColor);
144         canvas.Grid(
145                 world.cam.ToScreen(Vector<int>(0, 0)),
146                 world.cam.ToScale(Vector<float>(10, 10)),
147                 world.cam.ToScale(Vector<float>(1, 1)));
148
149         canvas.SetColor(entityColor);
150         for (const AABB &e : world.stationary) {
151                 canvas.OutlineRect(
152                         world.cam.ToScreen(Vector<float>(e.Left(), e.Top())),
153                         world.cam.ToScale(e.Size()));
154         }
155
156         canvas.SetColor(controlledColor);
157         canvas.OutlineRect(
158                 world.cam.ToScreen(Vector<float>(world.controlled.Left(), world.controlled.Top())),
159                 world.cam.ToScale(world.controlled.Size()));
160
161         if (world.coll.empty()) return;
162
163         for (const World::Collision &c : world.coll) {
164                 canvas.SetColor(collisionColor);
165                 canvas.Arrow(
166                         world.cam.ToScreen(c.pos),
167                         world.cam.ToScreen(c.pos + c.depth));
168                 canvas.SetColor(normalColor);
169                 canvas.Arrow(
170                         world.cam.ToScreen(c.pos),
171                         world.cam.ToScreen(c.pos) + Vector<int>(c.norm * 25.0f));
172         }
173 }
174
175 void run(Canvas &canvas) {
176         World world;
177         world.cam.SetScale(Vector<float>(32, 32));
178         world.controlled.Resize(Vector<float>(2, 3));
179         world.controlled.Move(Vector<float>(1, 1.5));
180
181         AABB e;
182         e.Resize(Vector<float>(2, 2));
183         e.Move(Vector<float>(5, 5));
184         world.stationary.push_back(e);
185         e.Move(Vector<float>(0, 2));
186         world.stationary.push_back(e);
187         e.Move(Vector<float>(-2, 0));
188         world.stationary.push_back(e);
189
190         Uint32 last = SDL_GetTicks();
191         while (world.alive) {
192                 handle(world);
193                 Uint32 now = SDL_GetTicks();
194
195                 int delta = now - last;
196                 if (delta == 0) {
197                         SDL_Delay(1);
198                         continue;
199                 } else if (delta > 30) {
200                         delta = 30;
201                 }
202
203                 update(delta, world);
204                 render(canvas, world);
205
206                 canvas.Present();
207                 last = now;
208         }
209 }
210
211 }
212
213
214 int main(int argc, const char *argv[]) {
215         SDL sdl(SDL_INIT_VIDEO);
216
217         Window win(
218                 "orbi collision test",
219                 Window::POS_UNDEF,
220                 Vector<int>(800, 600),
221                 SDL_WINDOW_RESIZABLE
222         );
223         Canvas canv(win.CreateCanvas(
224                 0
225         ));
226
227         run(canv);
228
229         return 0;
230 }