1 #include "Application.hpp"
3 #include "Environment.hpp"
4 #include "FrameCounter.hpp"
6 #include "StateControl.hpp"
9 #include "../audio/Sound.hpp"
10 #include "../graphics/Font.hpp"
11 #include "../world/BlockType.hpp"
12 #include "../world/Entity.hpp"
22 Application::Application(Environment &e)
28 Application::~Application() {
33 void Application::RunN(size_t n) {
34 Uint32 last = SDL_GetTicks();
35 for (size_t i = 0; HasState() && i < n; ++i) {
36 Uint32 now = SDL_GetTicks();
37 int delta = now - last;
43 void Application::RunT(size_t t) {
44 Uint32 last = SDL_GetTicks();
45 Uint32 finish = last + t;
46 while (HasState() && last < finish) {
47 Uint32 now = SDL_GetTicks();
48 int delta = now - last;
54 void Application::RunS(size_t n, size_t t) {
55 for (size_t i = 0; HasState() && i < n; ++i) {
61 void Application::Run() {
62 Uint32 last = SDL_GetTicks();
63 env.window.GrabMouse();
65 Uint32 now = SDL_GetTicks();
66 int delta = now - last;
72 void Application::Loop(int dt) {
73 env.counter.EnterFrame();
75 if (!HasState()) return;
77 env.state.Commit(*this);
78 if (!HasState()) return;
80 env.counter.ExitFrame();
84 void Application::HandleEvents() {
85 env.counter.EnterHandle();
87 while (HasState() && SDL_PollEvent(&event)) {
89 env.state.Commit(*this);
91 env.counter.ExitHandle();
94 void Application::Handle(const SDL_Event &event) {
100 Handle(event.window);
103 GetState().Handle(event);
108 void Application::Handle(const SDL_WindowEvent &event) {
109 switch (event.event) {
110 case SDL_WINDOWEVENT_FOCUS_GAINED:
111 env.window.GrabMouse();
113 case SDL_WINDOWEVENT_FOCUS_LOST:
114 env.window.ReleaseMouse();
116 case SDL_WINDOWEVENT_RESIZED:
117 env.viewport.Resize(event.data1, event.data2);
124 void Application::Update(int dt) {
125 env.counter.EnterUpdate();
127 GetState().Update(dt);
129 env.counter.ExitUpdate();
132 void Application::Render() {
133 // gl implementation may (and will probably) delay vsync blocking until
134 // the first write after flipping, which is this clear call
135 env.viewport.Clear();
136 env.counter.EnterRender();
139 GetState().Render(env.viewport);
142 env.counter.ExitRender();
147 void Application::PushState(State *s) {
151 State *Application::PopState() {
152 State *s = states.top();
157 State *Application::SwitchState(State *s_new) {
158 State *s_old = states.top();
159 states.top() = s_new;
163 State &Application::GetState() {
164 return *states.top();
167 bool Application::HasState() const noexcept {
168 return !states.empty();
172 void StateControl::Commit(Application &app) {
173 while (!cue.empty()) {
178 app.PushState(m.state);
181 app.SwitchState(m.state);
187 while (app.HasState()) {
196 Assets::Assets(const string &base)
197 : fonts(base + "fonts/")
198 , sounds(base + "sounds/") {
202 Font Assets::LoadFont(const string &name, int size) const {
203 string full = fonts + name + ".ttf";
204 return Font(full.c_str(), size);
207 Sound Assets::LoadSound(const string &name) const {
208 string full = sounds + name + ".wav";
209 return Sound(full.c_str());
213 void FrameCounter::EnterFrame() noexcept {
214 last_enter = SDL_GetTicks();
215 last_tick = last_enter;
218 void FrameCounter::EnterHandle() noexcept {
222 void FrameCounter::ExitHandle() noexcept {
223 current.handle = Tick();
226 void FrameCounter::EnterUpdate() noexcept {
230 void FrameCounter::ExitUpdate() noexcept {
231 current.update = Tick();
234 void FrameCounter::EnterRender() noexcept {
238 void FrameCounter::ExitRender() noexcept {
239 current.render = Tick();
242 void FrameCounter::ExitFrame() noexcept {
243 Uint32 now = SDL_GetTicks();
244 current.total = now - last_enter;
245 current.running = current.handle + current.update + current.render;
246 current.waiting = current.total - current.running;
250 if (cur_frame >= NUM_FRAMES) {
259 int FrameCounter::Tick() noexcept {
260 Uint32 now = SDL_GetTicks();
261 int delta = now - last_tick;
266 void FrameCounter::Accumulate() noexcept {
267 sum.handle += current.handle;
268 sum.update += current.update;
269 sum.render += current.render;
270 sum.running += current.running;
271 sum.waiting += current.waiting;
272 sum.total += current.total;
274 max.handle = std::max(current.handle, max.handle);
275 max.update = std::max(current.update, max.update);
276 max.render = std::max(current.render, max.render);
277 max.running = std::max(current.running, max.running);
278 max.waiting = std::max(current.waiting, max.waiting);
279 max.total = std::max(current.total, max.total);
281 current = Frame<int>();
284 void FrameCounter::Push() noexcept {
286 avg.handle = sum.handle * factor;
287 avg.update = sum.update * factor;
288 avg.render = sum.render * factor;
289 avg.running = sum.running * factor;
290 avg.waiting = sum.waiting * factor;
291 avg.total = sum.total * factor;