]> git.localhorst.tv Git - blank.git/blob - src/app/app.cpp
moved entity spawn and control into its own class
[blank.git] / src / app / app.cpp
1 #include "Application.hpp"
2 #include "Assets.hpp"
3 #include "FrameCounter.hpp"
4
5 #include "init.hpp"
6 #include "../audio/Sound.hpp"
7 #include "../graphics/Font.hpp"
8 #include "../world/BlockType.hpp"
9 #include "../world/Entity.hpp"
10
11 #include <iostream>
12 #include <stdexcept>
13
14 using std::string;
15
16
17 namespace {
18
19 string get_asset_path() {
20         char *base = SDL_GetBasePath();
21         string assets(base);
22         assets += "assets/";
23         SDL_free(base);
24         return assets;
25 }
26
27 }
28
29 namespace blank {
30
31 Application::Application(Window &win, const Config &config)
32 : window(win)
33 , viewport()
34 , assets(get_asset_path())
35 , audio()
36 , counter()
37 , world(config.world)
38 , interface(config.interface, assets, audio, counter, world)
39 , spawner(world)
40 , running(false) {
41         viewport.VSync(config.vsync);
42 }
43
44 Application::~Application() {
45         audio.StopAll();
46 }
47
48
49 void Application::RunN(size_t n) {
50         Uint32 last = SDL_GetTicks();
51         for (size_t i = 0; i < n; ++i) {
52                 Uint32 now = SDL_GetTicks();
53                 int delta = now - last;
54                 Loop(delta);
55                 last = now;
56         }
57 }
58
59 void Application::RunT(size_t t) {
60         Uint32 last = SDL_GetTicks();
61         Uint32 finish = last + t;
62         while (last < finish) {
63                 Uint32 now = SDL_GetTicks();
64                 int delta = now - last;
65                 Loop(delta);
66                 last = now;
67         }
68 }
69
70 void Application::RunS(size_t n, size_t t) {
71         for (size_t i = 0; i < n; ++i) {
72                 Loop(t);
73         }
74 }
75
76
77 void Application::Run() {
78         running = true;
79         Uint32 last = SDL_GetTicks();
80         window.GrabMouse();
81         while (running) {
82                 Uint32 now = SDL_GetTicks();
83                 int delta = now - last;
84                 Loop(delta);
85                 last = now;
86         }
87 }
88
89 void Application::Loop(int dt) {
90         counter.EnterFrame();
91         HandleEvents();
92         Update(dt);
93         Render();
94         counter.ExitFrame();
95 }
96
97
98 void Application::HandleEvents() {
99         counter.EnterHandle();
100         SDL_Event event;
101         while (SDL_PollEvent(&event)) {
102                 switch (event.type) {
103                         case SDL_KEYDOWN:
104                                 interface.HandlePress(event.key);
105                                 break;
106                         case SDL_KEYUP:
107                                 interface.HandleRelease(event.key);
108                                 break;
109                         case SDL_MOUSEBUTTONDOWN:
110                                 interface.HandlePress(event.button);
111                                 break;
112                         case SDL_MOUSEBUTTONUP:
113                                 interface.HandleRelease(event.button);
114                                 break;
115                         case SDL_MOUSEMOTION:
116                                 interface.Handle(event.motion);
117                                 break;
118                         case SDL_MOUSEWHEEL:
119                                 interface.Handle(event.wheel);
120                                 break;
121                         case SDL_QUIT:
122                                 running = false;
123                                 break;
124                         case SDL_WINDOWEVENT:
125                                 Handle(event.window);
126                                 break;
127                         default:
128                                 break;
129                 }
130         }
131         counter.ExitHandle();
132 }
133
134 void Application::Handle(const SDL_WindowEvent &event) {
135         switch (event.event) {
136                 case SDL_WINDOWEVENT_FOCUS_GAINED:
137                         window.GrabMouse();
138                         break;
139                 case SDL_WINDOWEVENT_FOCUS_LOST:
140                         window.ReleaseMouse();
141                         break;
142                 case SDL_WINDOWEVENT_RESIZED:
143                         viewport.Resize(event.data1, event.data2);
144                         break;
145                 default:
146                         break;
147         }
148 }
149
150 void Application::Update(int dt) {
151         counter.EnterUpdate();
152         interface.Update(dt);
153         spawner.Update(dt);
154         world.Update(dt);
155
156         glm::mat4 trans = world.Player().Transform(Chunk::Pos(0, 0, 0));
157         glm::vec3 dir(trans * glm::vec4(0.0f, 0.0f, -1.0f, 0.0f));
158         glm::vec3 up(trans * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
159         audio.Position(world.Player().Position());
160         audio.Velocity(world.Player().Velocity());
161         audio.Orientation(dir, up);
162
163         counter.ExitUpdate();
164 }
165
166 void Application::Render() {
167         // gl implementation may (and will probably) delay vsync blocking until
168         // the first write after flipping, which is this clear call
169         viewport.Clear();
170         counter.EnterRender();
171
172         world.Render(viewport);
173         interface.Render(viewport);
174
175         counter.ExitRender();
176         window.Flip();
177 }
178
179
180 Assets::Assets(const string &base)
181 : fonts(base + "fonts/")
182 , sounds(base + "sounds/") {
183
184 }
185
186 Font Assets::LoadFont(const string &name, int size) const {
187         string full = fonts + name + ".ttf";
188         return Font(full.c_str(), size);
189 }
190
191 Sound Assets::LoadSound(const string &name) const {
192         string full = sounds + name + ".wav";
193         return Sound(full.c_str());
194 }
195
196
197 void FrameCounter::EnterFrame() noexcept {
198         last_enter = SDL_GetTicks();
199         last_tick = last_enter;
200 }
201
202 void FrameCounter::EnterHandle() noexcept {
203         Tick();
204 }
205
206 void FrameCounter::ExitHandle() noexcept {
207         current.handle = Tick();
208 }
209
210 void FrameCounter::EnterUpdate() noexcept {
211         Tick();
212 }
213
214 void FrameCounter::ExitUpdate() noexcept {
215         current.update = Tick();
216 }
217
218 void FrameCounter::EnterRender() noexcept {
219         Tick();
220 }
221
222 void FrameCounter::ExitRender() noexcept {
223         current.render = Tick();
224 }
225
226 void FrameCounter::ExitFrame() noexcept {
227         Uint32 now = SDL_GetTicks();
228         current.total = now - last_enter;
229         current.running = current.handle + current.update + current.render;
230         current.waiting = current.total - current.running;
231         Accumulate();
232
233         ++cur_frame;
234         if (cur_frame >= NUM_FRAMES) {
235                 Push();
236                 cur_frame = 0;
237                 changed = true;
238         } else {
239                 changed = false;
240         }
241 }
242
243 int FrameCounter::Tick() noexcept {
244         Uint32 now = SDL_GetTicks();
245         int delta = now - last_tick;
246         last_tick = now;
247         return delta;
248 }
249
250 void FrameCounter::Accumulate() noexcept {
251         sum.handle += current.handle;
252         sum.update += current.update;
253         sum.render += current.render;
254         sum.running += current.running;
255         sum.waiting += current.waiting;
256         sum.total += current.total;
257
258         max.handle = std::max(current.handle, max.handle);
259         max.update = std::max(current.update, max.update);
260         max.render = std::max(current.render, max.render);
261         max.running = std::max(current.running, max.running);
262         max.waiting = std::max(current.waiting, max.waiting);
263         max.total = std::max(current.total, max.total);
264
265         current = Frame<int>();
266 }
267
268 void FrameCounter::Push() noexcept {
269         peak = max;
270         avg.handle = sum.handle * factor;
271         avg.update = sum.update * factor;
272         avg.render = sum.render * factor;
273         avg.running = sum.running * factor;
274         avg.waiting = sum.waiting * factor;
275         avg.total = sum.total * factor;
276
277         sum = Frame<int>();
278         max = Frame<int>();
279 }
280
281 }