]> git.localhorst.tv Git - l2e.git/blob - src/app/Application.cpp
delayed state pushing/popping till the end of each loop
[l2e.git] / src / app / Application.cpp
1 /*
2  * Application.cpp
3  *
4  *  Created on: Apr 8, 2012
5  *      Author: holy
6  */
7
8 #include "Application.h"
9
10 #include "State.h"
11
12 #include <cassert>
13
14 namespace app {
15
16 Application::Application(sdl::InitScreen *screen, State *initialState)
17 : screen(screen)
18 , states()
19 , last(SDL_GetTicks())
20 , toPop(0) {
21         assert(screen && "cannot create application without screen");
22         assert(initialState && "cannot create application without initial state");
23         RealPushState(initialState);
24 }
25
26 Application::~Application() {
27         PopAllStates();
28 }
29
30
31 State *Application::CurrentState() {
32         return states.top();
33 }
34
35 void Application::UpdateState() {
36         while (toPop > 0) {
37                 RealPopState();
38                 --toPop;
39         }
40         while (!toPush.empty()) {
41                 State *s(toPush.front());
42                 toPush.pop();
43                 RealPushState(s);
44         }
45 }
46
47 void Application::ChangeState(State *s) {
48         PopState();
49         PushState(s);
50 }
51
52 void Application::PushState(State *s) {
53         toPush.push(s);
54 }
55
56 void Application::RealPushState(State *s) {
57         states.push(s);
58         s->EnterState(*this, screen->Screen());
59 }
60
61 void Application::PopState() {
62         ++toPop;
63 }
64
65 void Application::RealPopState() {
66         if (states.empty()) return;
67         states.top()->ExitState();
68         delete states.top();
69         states.pop();
70 }
71
72 void Application::Quit() {
73         PopAllStates();
74 }
75
76 void Application::PopAllStates() {
77         while (!states.empty()) {
78                 RealPopState();
79         }
80 }
81
82
83 void Application::Run() {
84         while (CurrentState()) {
85                 Loop();
86         }
87 }
88
89 void Application::Loop() {
90         Uint32 now(SDL_GetTicks());
91         Uint32 deltaT(now - last);
92         if (deltaT > 34) deltaT = 34;
93
94         HandleEvents();
95         UpdateWorld(deltaT);
96         Render();
97
98         last = now;
99         UpdateState();
100 }
101
102
103 void Application::HandleEvents() {
104         if (!CurrentState()) return;
105         input.ResetInteractiveState();
106         SDL_Event event;
107         while (SDL_PollEvent(&event)) {
108                 switch (event.type) {
109                         case SDL_QUIT:
110                                 PopAllStates();
111                                 break;
112                         case SDL_VIDEORESIZE:
113                                 screen->Resize(event.resize.w, event.resize.h);
114                                 CurrentState()->Resize(event.resize.w, event.resize.h);
115                                 break;
116                         case SDL_KEYDOWN:
117                         case SDL_KEYUP:
118                                 input.HandleKeyboardEvent(event.key);
119                                 break;
120                         default:
121                                 // skip event
122                                 break;
123                 }
124         }
125         CurrentState()->HandleInput(input);
126 }
127
128 void Application::UpdateWorld(Uint32 deltaT) {
129         if (!CurrentState()) return;
130         for (Uint32 i(0); i < deltaT; ++i) {
131                 CurrentState()->UpdateWorld(0.001f);
132         }
133 }
134
135 void Application::Render(void) {
136         if (!CurrentState()) return;
137         CurrentState()->Render(screen->Screen());
138         screen->Flip();
139 }
140
141 }