]> git.localhorst.tv Git - l2e.git/blob - src/app/Application.cpp
added ComplexAnimation
[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         assert(screen && "cannot create application without screen");
21         assert(initialState && "cannot create application without initial state");
22         RealPushState(initialState);
23 }
24
25 Application::~Application() {
26         PopAllStates();
27 }
28
29
30 State *Application::CurrentState() {
31         return states.empty() ? 0 : states.top();
32 }
33
34 void Application::UpdateState() {
35         while (!stateChanges.empty()) {
36                 switch (stateChanges.front().type) {
37                         case StateCommand::PUSH:
38                                 RealPushState(stateChanges.front().state);
39                                 break;
40                         case StateCommand::POP:
41                                 RealPopState();
42                                 break;
43                         case StateCommand::CHANGE:
44                                 RealChangeState(stateChanges.front().state);
45                                 break;
46                 }
47                 stateChanges.pop();
48         }
49 }
50
51 void Application::ChangeState(State *s) {
52         StateCommand cmd;
53         cmd.type = StateCommand::CHANGE;
54         cmd.state = s;
55         stateChanges.push(cmd);
56 }
57
58 void Application::PushState(State *s) {
59         StateCommand cmd;
60         cmd.type = StateCommand::PUSH;
61         cmd.state = s;
62         stateChanges.push(cmd);
63 }
64
65 void Application::PopState() {
66         StateCommand cmd;
67         cmd.type = StateCommand::POP;
68         cmd.state = 0;
69         stateChanges.push(cmd);
70 }
71
72 void Application::RealChangeState(State *s) {
73         if (!states.empty()) {
74                 states.top()->PauseState(*this, screen->Screen());
75                 states.top()->ExitState(*this, screen->Screen());
76                 states.pop();
77         }
78         states.push(s);
79         s->EnterState(*this, screen->Screen());
80         s->ResumeState(*this, screen->Screen());
81 }
82
83 void Application::RealPushState(State *s) {
84         if (!states.empty()) {
85                 states.top()->PauseState(*this, screen->Screen());
86         }
87         states.push(s);
88         s->EnterState(*this, screen->Screen());
89         s->ResumeState(*this, screen->Screen());
90 }
91
92 void Application::RealPopState() {
93         if (states.empty()) return;
94         states.top()->PauseState(*this, screen->Screen());
95         states.top()->ExitState(*this, screen->Screen());
96         delete states.top();
97         states.pop();
98         if (!states.empty()) {
99                 states.top()->ResumeState(*this, screen->Screen());
100         }
101 }
102
103 void Application::Quit() {
104         PopAllStates();
105 }
106
107 void Application::PopAllStates() {
108         while (!states.empty()) {
109                 RealPopState();
110         }
111 }
112
113
114 void Application::Run() {
115         while (CurrentState()) {
116                 Loop();
117         }
118 }
119
120 void Application::Loop() {
121         Uint32 now(SDL_GetTicks());
122         Uint32 deltaT(now - last);
123         GlobalTimers().Update(deltaT);
124         if (deltaT > 34) deltaT = 34;
125
126         if (CurrentState()) {
127                 CurrentState()->GraphicsTimers().Update(deltaT);
128         }
129         HandleEvents();
130         if (!StateChangePending()) {
131                 UpdateWorld(deltaT);
132                 Render();
133         }
134
135         last = now;
136         UpdateState();
137 }
138
139
140 void Application::HandleEvents() {
141         if (!CurrentState()) return;
142         input.ResetInteractiveState();
143         SDL_Event event;
144         while (SDL_PollEvent(&event)) {
145                 switch (event.type) {
146                         case SDL_QUIT:
147                                 PopAllStates();
148                                 break;
149                         case SDL_VIDEORESIZE:
150                                 screen->Resize(event.resize.w, event.resize.h);
151                                 CurrentState()->Resize(event.resize.w, event.resize.h);
152                                 break;
153                         case SDL_KEYDOWN:
154                         case SDL_KEYUP:
155                                 input.HandleKeyboardEvent(event.key);
156                                 break;
157                         default:
158                                 // skip event
159                                 break;
160                 }
161         }
162         CurrentState()->HandleEvents(input);
163 }
164
165 void Application::UpdateWorld(Uint32 deltaT) {
166         if (!CurrentState()) return;
167         for (Uint32 i(0); i < deltaT; ++i) {
168                 CurrentState()->PhysicsTimers().Update(0.001f);
169                 CurrentState()->UpdateWorld(0.001f);
170         }
171 }
172
173 void Application::Render(void) {
174         if (!CurrentState()) return;
175         CurrentState()->Render(screen->Screen());
176         screen->Flip();
177 }
178
179 }