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