]> git.localhorst.tv Git - gworm.git/blob - src/app/Application.cpp
d798b37c757f89b75aab6b41a524ed727caaa076
[gworm.git] / src / app / Application.cpp
1 #include "Application.h"
2
3 #include "../graphics/Canvas.h"
4 #include "../graphics/Color.h"
5 #include "../world/Entity.h"
6 #include "../world/World.h"
7
8 #include <chrono>
9 #include <iostream>
10 using namespace std;
11 using namespace chrono;
12
13
14 namespace gworm {
15
16 Application::Application(Canvas &c, World &w)
17 : canvas(c)
18 , world(w)
19 , focus(Vector<float>(250, 250), 25)
20 , cam(c.Size(), focus.Pos())
21 , last(SDL_GetTicks())
22 , running(false)
23 , paused(false) {
24
25 }
26
27
28 void Application::Run() {
29         running = true;
30         while (running) {
31                 Uint32 now = SDL_GetTicks();
32                 int delta = now - last;
33                 Loop(delta);
34                 last = now;
35         }
36 }
37
38
39 void Application::Loop(int delta) {
40         cout << "delta: " << delta << endl << endl;
41         auto enter = chrono::system_clock::now();
42
43         HandleEvents();
44         auto event = chrono::system_clock::now();
45         cout << "       event: " << duration_cast<milliseconds>(event - enter).count() << endl;
46
47         if (delta == 0) {
48                 SDL_Delay(1);
49                 return;
50         }
51
52         auto update = event;
53         if (!paused) {
54                 Update(delta);
55                 update = chrono::system_clock::now();
56                 cout << "       update: " << duration_cast<milliseconds>(update - event).count() << endl;
57         }
58
59         Render();
60         auto render = chrono::system_clock::now();
61         cout << "       render: " << duration_cast<milliseconds>(render - update).count() << endl;
62
63         canvas.Present();
64 }
65
66
67 void Application::HandleEvents() {
68         SDL_Event event;
69         while (SDL_PollEvent(&event)) {
70                 switch (event.type) {
71                         case SDL_QUIT:
72                                 running = false;
73                                 break;
74                         case SDL_WINDOWEVENT:
75                                 if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
76                                         cam.Resize(event.window.data1, event.window.data2);
77                                 }
78                                 break;
79                         case SDL_KEYDOWN:
80                                 if (!event.key.repeat) {
81                                         OnKeyDown(event.key);
82                                 }
83                                 break;
84                         case SDL_KEYUP:
85                                 if (!event.key.repeat) {
86                                         OnKeyUp(event.key);
87                                 }
88                                 break;
89                         default:
90                                 // skip event
91                                 break;
92                 }
93         }
94 }
95
96 void Application::OnKeyDown(const SDL_KeyboardEvent &e) {
97         switch (e.keysym.sym) {
98                 case SDLK_UP:
99                         focus.MoveUp();
100                         break;
101                 case SDLK_DOWN:
102                         focus.MoveDown();
103                         break;
104                 case SDLK_LEFT:
105                         focus.MoveLeft();
106                         break;
107                 case SDLK_RIGHT:
108                         focus.MoveRight();
109                         break;
110                 case SDLK_p:
111                         paused = !paused;
112                         break;
113                 default:
114                         break;
115         }
116 }
117
118 void Application::OnKeyUp(const SDL_KeyboardEvent &e) {
119         switch (e.keysym.sym) {
120                 case SDLK_UP:
121                         focus.StopUp();
122                         break;
123                 case SDLK_DOWN:
124                         focus.StopDown();
125                         break;
126                 case SDLK_LEFT:
127                         focus.StopLeft();
128                         break;
129                 case SDLK_RIGHT:
130                         focus.StopRight();
131                         break;
132                 default:
133                         break;
134         }
135 }
136
137
138 void Application::Update(int dt) {
139         const float delta = dt / 1e3;
140         cam.Update(delta);
141         world.Update(delta);
142         focus.Update(delta);
143 }
144
145
146 void Application::Render() {
147         RenderBackground();
148         RenderWorld();
149         RenderEntities();
150         RenderUI();
151 }
152
153 void Application::RenderBackground() {
154         constexpr Color background(0x00, 0x00, 0x00);
155
156         canvas.SetColor(background);
157         canvas.Fill();
158 }
159
160 void Application::RenderWorld() {
161         Vector<int> begin(0, 0);
162         Vector<int> end(world.Size());
163         Vector<int> topLeft = cam.ToScreen(Vector<float>(begin));
164         Vector<int> bottomRight = cam.ToScreen(Vector<float>(end));
165         Vector<int> clip(canvas.Size());
166
167         if (begin.x > clip.x || begin.y > clip.y || end.x < 0 || end.y < 0) {
168                 return;
169         }
170
171         if (topLeft.x < 0) {
172                 begin.x -= topLeft.x;
173                 topLeft.x = 0;
174         }
175         if (topLeft.y < 0) {
176                 begin.y -= topLeft.y;
177                 topLeft.y = 0;
178         }
179         if (bottomRight.x > clip.x) {
180                 end.x -= bottomRight.x - clip.x;
181                 bottomRight.x = clip.x;
182         }
183         if (bottomRight.y > clip.y) {
184                 end.y -= bottomRight.y - clip.y;
185                 bottomRight.y = clip.y;
186         }
187
188         for (Vector<int> pos(begin), cur(topLeft); pos.y < end.y; ++pos.y, ++cur.y) {
189                 for (pos.x = begin.x, cur.x = topLeft.x; pos.x < end.x; ++pos.x, ++cur.x) {
190                         canvas.SetColor(world.ColorAt(pos));
191                         canvas.Dot(cur);
192                 }
193         }
194 }
195
196 void Application::RenderEntities() {
197         constexpr Color entityColor(0x00, 0xFA, 0x00);
198         canvas.SetColor(entityColor);
199
200         for (const Entity &e : world.Entities()) {
201                 canvas.Cross(cam.ToScreen(e.pos), 10);
202         }
203 }
204
205 void Application::RenderUI() {
206         constexpr Color focusColor(0xFA, 0xFA, 0x00);
207         constexpr Color forceColor(0xFA, 0x00, 0x00);
208         constexpr Color speedColor(0x00, 0xFA, 0x00);
209
210         canvas.SetColor(focusColor);
211         canvas.Cross(cam.ToScreen(focus.Pos()), 15);
212
213         for (const Entity &e : world.Entities()) {
214                 const Vector<int> screenPos = cam.ToScreen(e.pos);
215
216                 canvas.SetColor(forceColor);
217                 canvas.Arrow(screenPos, screenPos + Vector<int>(e.acc * e.mass * 10.0f));
218
219                 canvas.SetColor(speedColor);
220                 canvas.Arrow(screenPos, screenPos + Vector<int>(e.vel * 10.0f));
221
222                 cout << "entity: pos " << e.pos << ", vel " << e.vel << ", acc " << e.acc << endl;
223         }
224 }
225
226 }