1 #include "Application.hpp"
3 #include "FrameCounter.hpp"
6 #include "../audio/Sound.hpp"
7 #include "../graphics/Font.hpp"
8 #include "../world/BlockType.hpp"
9 #include "../world/Entity.hpp"
19 string get_asset_path() {
20 char *base = SDL_GetBasePath();
31 Application::Application(Window &win, const Config &config)
34 , assets(get_asset_path())
38 , interface(config.interface, assets, audio, counter, world)
39 , test_controller(MakeTestEntity(world))
41 viewport.VSync(config.vsync);
44 Application::~Application() {
48 Entity &Application::MakeTestEntity(World &world) {
49 Entity &e = world.AddEntity();
51 e.Position({ 0.0f, 0.0f, 0.0f });
52 e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } });
53 e.WorldCollidable(true);
54 e.SetShape(world.BlockTypes()[1].shape, { 1.0f, 1.0f, 0.0f });
55 e.AngularVelocity(glm::quat(glm::vec3{ 0.00001f, 0.000006f, 0.000013f }));
60 void Application::RunN(size_t n) {
61 Uint32 last = SDL_GetTicks();
62 for (size_t i = 0; i < n; ++i) {
63 Uint32 now = SDL_GetTicks();
64 int delta = now - last;
70 void Application::RunT(size_t t) {
71 Uint32 last = SDL_GetTicks();
72 Uint32 finish = last + t;
73 while (last < finish) {
74 Uint32 now = SDL_GetTicks();
75 int delta = now - last;
81 void Application::RunS(size_t n, size_t t) {
82 for (size_t i = 0; i < n; ++i) {
88 void Application::Run() {
90 Uint32 last = SDL_GetTicks();
93 Uint32 now = SDL_GetTicks();
94 int delta = now - last;
100 void Application::Loop(int dt) {
101 counter.EnterFrame();
109 void Application::HandleEvents() {
110 counter.EnterHandle();
112 while (SDL_PollEvent(&event)) {
113 switch (event.type) {
115 interface.HandlePress(event.key);
118 interface.HandleRelease(event.key);
120 case SDL_MOUSEBUTTONDOWN:
121 interface.HandlePress(event.button);
123 case SDL_MOUSEBUTTONUP:
124 interface.HandleRelease(event.button);
126 case SDL_MOUSEMOTION:
127 interface.Handle(event.motion);
130 interface.Handle(event.wheel);
135 case SDL_WINDOWEVENT:
136 Handle(event.window);
142 counter.ExitHandle();
145 void Application::Handle(const SDL_WindowEvent &event) {
146 switch (event.event) {
147 case SDL_WINDOWEVENT_FOCUS_GAINED:
150 case SDL_WINDOWEVENT_FOCUS_LOST:
151 window.ReleaseMouse();
153 case SDL_WINDOWEVENT_RESIZED:
154 viewport.Resize(event.data1, event.data2);
161 void Application::Update(int dt) {
162 counter.EnterUpdate();
163 interface.Update(dt);
164 test_controller.Update(dt);
167 glm::mat4 trans = world.Player().Transform(Chunk::Pos(0, 0, 0));
168 glm::vec3 dir(trans * glm::vec4(0.0f, 0.0f, -1.0f, 0.0f));
169 glm::vec3 up(trans * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
170 audio.Position(world.Player().Position());
171 audio.Velocity(world.Player().Velocity());
172 audio.Orientation(dir, up);
174 counter.ExitUpdate();
177 void Application::Render() {
178 // gl implementation may (and will probably) delay vsync blocking until
179 // the first write after flipping, which is this clear call
181 counter.EnterRender();
183 world.Render(viewport);
184 interface.Render(viewport);
186 counter.ExitRender();
191 Assets::Assets(const string &base)
192 : fonts(base + "fonts/")
193 , sounds(base + "sounds/") {
197 Font Assets::LoadFont(const string &name, int size) const {
198 string full = fonts + name + ".ttf";
199 return Font(full.c_str(), size);
202 Sound Assets::LoadSound(const string &name) const {
203 string full = sounds + name + ".wav";
204 return Sound(full.c_str());
208 void FrameCounter::EnterFrame() noexcept {
209 last_enter = SDL_GetTicks();
210 last_tick = last_enter;
213 void FrameCounter::EnterHandle() noexcept {
217 void FrameCounter::ExitHandle() noexcept {
218 current.handle = Tick();
221 void FrameCounter::EnterUpdate() noexcept {
225 void FrameCounter::ExitUpdate() noexcept {
226 current.update = Tick();
229 void FrameCounter::EnterRender() noexcept {
233 void FrameCounter::ExitRender() noexcept {
234 current.render = Tick();
237 void FrameCounter::ExitFrame() noexcept {
238 Uint32 now = SDL_GetTicks();
239 current.total = now - last_enter;
240 current.running = current.handle + current.update + current.render;
241 current.waiting = current.total - current.running;
245 if (cur_frame >= NUM_FRAMES) {
254 int FrameCounter::Tick() noexcept {
255 Uint32 now = SDL_GetTicks();
256 int delta = now - last_tick;
261 void FrameCounter::Accumulate() noexcept {
262 sum.handle += current.handle;
263 sum.update += current.update;
264 sum.render += current.render;
265 sum.running += current.running;
266 sum.waiting += current.waiting;
267 sum.total += current.total;
269 max.handle = std::max(current.handle, max.handle);
270 max.update = std::max(current.update, max.update);
271 max.render = std::max(current.render, max.render);
272 max.running = std::max(current.running, max.running);
273 max.waiting = std::max(current.waiting, max.waiting);
274 max.total = std::max(current.total, max.total);
276 current = Frame<int>();
279 void FrameCounter::Push() noexcept {
281 avg.handle = sum.handle * factor;
282 avg.update = sum.update * factor;
283 avg.render = sum.render * factor;
284 avg.running = sum.running * factor;
285 avg.waiting = sum.waiting * factor;
286 avg.total = sum.total * factor;