1 #include "Application.hpp"
3 #include "FrameCounter.hpp"
5 #include "../audio/Sound.hpp"
6 #include "../graphics/Font.hpp"
7 #include "../world/BlockType.hpp"
8 #include "../world/Entity.hpp"
18 string get_asset_path() {
19 char *base = SDL_GetBasePath();
30 Application::Application(const Config &config)
31 : init(config.doublebuf, config.multisampling)
33 , assets(get_asset_path())
37 , interface(config.interface, assets, audio, counter, world)
38 , test_controller(MakeTestEntity(world))
40 viewport.VSync(config.vsync);
43 Application::~Application() {
47 Entity &Application::MakeTestEntity(World &world) {
48 Entity &e = world.AddEntity();
50 e.Position({ 0.0f, 0.0f, 0.0f });
51 e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } });
52 e.WorldCollidable(true);
53 e.SetShape(world.BlockTypes()[1].shape, { 1.0f, 1.0f, 0.0f });
54 e.AngularVelocity(glm::quat(glm::vec3{ 0.00001f, 0.000006f, 0.000013f }));
59 void Application::RunN(size_t n) {
60 Uint32 last = SDL_GetTicks();
61 for (size_t i = 0; i < n; ++i) {
62 Uint32 now = SDL_GetTicks();
63 int delta = now - last;
69 void Application::RunT(size_t t) {
70 Uint32 last = SDL_GetTicks();
71 Uint32 finish = last + t;
72 while (last < finish) {
73 Uint32 now = SDL_GetTicks();
74 int delta = now - last;
80 void Application::RunS(size_t n, size_t t) {
81 for (size_t i = 0; i < n; ++i) {
87 void Application::Run() {
89 Uint32 last = SDL_GetTicks();
90 init.window.GrabMouse();
92 Uint32 now = SDL_GetTicks();
93 int delta = now - last;
99 void Application::Loop(int dt) {
100 counter.EnterFrame();
108 void Application::HandleEvents() {
109 counter.EnterHandle();
111 while (SDL_PollEvent(&event)) {
112 switch (event.type) {
114 interface.HandlePress(event.key);
117 interface.HandleRelease(event.key);
119 case SDL_MOUSEBUTTONDOWN:
120 interface.HandlePress(event.button);
122 case SDL_MOUSEBUTTONUP:
123 interface.HandleRelease(event.button);
125 case SDL_MOUSEMOTION:
126 interface.Handle(event.motion);
129 interface.Handle(event.wheel);
134 case SDL_WINDOWEVENT:
135 Handle(event.window);
141 counter.ExitHandle();
144 void Application::Handle(const SDL_WindowEvent &event) {
145 switch (event.event) {
146 case SDL_WINDOWEVENT_FOCUS_GAINED:
147 init.window.GrabMouse();
149 case SDL_WINDOWEVENT_FOCUS_LOST:
150 init.window.ReleaseMouse();
152 case SDL_WINDOWEVENT_RESIZED:
153 viewport.Resize(event.data1, event.data2);
160 void Application::Update(int dt) {
161 counter.EnterUpdate();
162 interface.Update(dt);
163 test_controller.Update(dt);
166 glm::mat4 trans = world.Player().Transform(Chunk::Pos(0, 0, 0));
167 glm::vec3 dir(trans * glm::vec4(0.0f, 0.0f, -1.0f, 0.0f));
168 glm::vec3 up(trans * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
169 audio.Position(world.Player().Position());
170 audio.Velocity(world.Player().Velocity());
171 audio.Orientation(dir, up);
173 counter.ExitUpdate();
176 void Application::Render() {
177 // gl implementation may (and will probably) delay vsync blocking until
178 // the first write after flipping, which is this clear call
180 counter.EnterRender();
182 world.Render(viewport);
183 interface.Render(viewport);
185 counter.ExitRender();
190 Assets::Assets(const string &base)
191 : fonts(base + "fonts/")
192 , sounds(base + "sounds/") {
196 Font Assets::LoadFont(const string &name, int size) const {
197 string full = fonts + name + ".ttf";
198 return Font(full.c_str(), size);
201 Sound Assets::LoadSound(const string &name) const {
202 string full = sounds + name + ".wav";
203 return Sound(full.c_str());
207 void FrameCounter::EnterFrame() noexcept {
208 last_enter = SDL_GetTicks();
209 last_tick = last_enter;
212 void FrameCounter::EnterHandle() noexcept {
216 void FrameCounter::ExitHandle() noexcept {
217 current.handle = Tick();
220 void FrameCounter::EnterUpdate() noexcept {
224 void FrameCounter::ExitUpdate() noexcept {
225 current.update = Tick();
228 void FrameCounter::EnterRender() noexcept {
232 void FrameCounter::ExitRender() noexcept {
233 current.render = Tick();
236 void FrameCounter::ExitFrame() noexcept {
237 Uint32 now = SDL_GetTicks();
238 current.total = now - last_enter;
239 current.running = current.handle + current.update + current.render;
240 current.waiting = current.total - current.running;
244 if (cur_frame >= NUM_FRAMES) {
253 int FrameCounter::Tick() noexcept {
254 Uint32 now = SDL_GetTicks();
255 int delta = now - last_tick;
260 void FrameCounter::Accumulate() noexcept {
261 sum.handle += current.handle;
262 sum.update += current.update;
263 sum.render += current.render;
264 sum.running += current.running;
265 sum.waiting += current.waiting;
266 sum.total += current.total;
268 max.handle = std::max(current.handle, max.handle);
269 max.update = std::max(current.update, max.update);
270 max.render = std::max(current.render, max.render);
271 max.running = std::max(current.running, max.running);
272 max.waiting = std::max(current.waiting, max.waiting);
273 max.total = std::max(current.total, max.total);
275 current = Frame<int>();
278 void FrameCounter::Push() noexcept {
280 avg.handle = sum.handle * factor;
281 avg.update = sum.update * factor;
282 avg.render = sum.render * factor;
283 avg.running = sum.running * factor;
284 avg.waiting = sum.waiting * factor;
285 avg.total = sum.total * factor;