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