1 #include "Application.hpp"
3 #include "FrameCounter.hpp"
5 #include "../graphics/Font.hpp"
6 #include "../world/BlockType.hpp"
7 #include "../world/Entity.hpp"
17 string get_asset_path() {
18 char *base = SDL_GetBasePath();
29 Application::Application(const Config &config)
33 , init_gl(config.doublebuf, config.multisampling)
35 , ctx(window.CreateContext())
37 , assets(get_asset_path())
44 , interface(config.interface, assets, counter, world)
45 , test_controller(MakeTestEntity(world))
48 GLContext::EnableVSync();
51 glClearColor(0.0, 0.0, 0.0, 1.0);
54 Entity &Application::MakeTestEntity(World &world) {
55 Entity &e = world.AddEntity();
57 e.Position({ 0.0f, 0.0f, 0.0f });
58 e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } });
59 e.WorldCollidable(true);
60 e.SetShape(world.BlockTypes()[1].shape, { 1.0f, 1.0f, 0.0f });
61 e.AngularVelocity(glm::quat(glm::vec3{ 0.00001f, 0.000006f, 0.000013f }));
66 void Application::RunN(size_t n) {
67 Uint32 last = SDL_GetTicks();
68 for (size_t i = 0; i < n; ++i) {
69 Uint32 now = SDL_GetTicks();
70 int delta = now - last;
76 void Application::RunT(size_t t) {
77 Uint32 last = SDL_GetTicks();
78 Uint32 finish = last + t;
79 while (last < finish) {
80 Uint32 now = SDL_GetTicks();
81 int delta = now - last;
87 void Application::RunS(size_t n, size_t t) {
88 for (size_t i = 0; i < n; ++i) {
94 void Application::Run() {
96 Uint32 last = SDL_GetTicks();
99 Uint32 now = SDL_GetTicks();
100 int delta = now - last;
106 void Application::Loop(int dt) {
107 counter.EnterFrame();
115 void Application::HandleEvents() {
116 counter.EnterHandle();
118 while (SDL_PollEvent(&event)) {
119 switch (event.type) {
121 interface.HandlePress(event.key);
124 interface.HandleRelease(event.key);
126 case SDL_MOUSEBUTTONDOWN:
127 interface.HandlePress(event.button);
129 case SDL_MOUSEBUTTONUP:
130 interface.HandleRelease(event.button);
132 case SDL_MOUSEMOTION:
133 interface.Handle(event.motion);
136 interface.Handle(event.wheel);
141 case SDL_WINDOWEVENT:
142 Handle(event.window);
148 counter.ExitHandle();
151 void Application::Handle(const SDL_WindowEvent &event) {
152 switch (event.event) {
153 case SDL_WINDOWEVENT_FOCUS_GAINED:
156 case SDL_WINDOWEVENT_FOCUS_LOST:
157 window.ReleaseMouse();
159 case SDL_WINDOWEVENT_RESIZED:
160 cam.Viewport(event.data1, event.data2);
161 interface.Handle(event);
164 interface.Handle(event);
169 void Application::Update(int dt) {
170 counter.EnterUpdate();
171 interface.Update(dt);
172 test_controller.Update(dt);
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 chunk_prog.SetProjection(cam.Projection());
184 entity_prog.SetProjection(cam.Projection());
186 world.Render(chunk_prog, entity_prog);
188 interface.Render(entity_prog, sprite_prog);
190 counter.ExitRender();
195 Assets::Assets(const string &base)
196 : fonts(base + "fonts/") {
200 Font Assets::LoadFont(const string &name, int size) const {
201 string full = fonts + name + ".ttf";
202 return Font(full.c_str(), size);
206 void FrameCounter::EnterFrame() noexcept {
207 last_enter = SDL_GetTicks();
208 last_tick = last_enter;
211 void FrameCounter::EnterHandle() noexcept {
215 void FrameCounter::ExitHandle() noexcept {
216 running.handle += Tick();
219 void FrameCounter::EnterUpdate() noexcept {
223 void FrameCounter::ExitUpdate() noexcept {
224 running.update += Tick();
227 void FrameCounter::EnterRender() noexcept {
231 void FrameCounter::ExitRender() noexcept {
232 running.render += Tick();
235 void FrameCounter::ExitFrame() noexcept {
236 Uint32 now = SDL_GetTicks();
237 running.total += now - last_enter;
239 if (cur_frame >= NUM_FRAMES) {
240 avg.handle = running.handle * factor;
241 avg.update = running.update * factor;
242 avg.render = running.render * factor;
243 avg.total = running.total * factor;
244 running = Frame<int>{};
252 int FrameCounter::Tick() noexcept {
253 Uint32 now = SDL_GetTicks();
254 int delta = now - last_tick;
259 void FrameCounter::Print(std::ostream &out) const {
260 out << "frame: " << AvgFrame() << std::endl;
261 out << " handle: " << AvgHandle() << std::endl;
262 out << " update: " << AvgUpdate() << std::endl;
263 out << " render: " << AvgRender() << std::endl;
264 out << " running: " << AvgRunning() << std::endl;
265 out << " waiting: " << AvgWaiting() << std::endl;