]> git.localhorst.tv Git - l2e.git/blob - src/app/Application.cpp
added gauges for health, mana, and ikari displays
[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.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         if (deltaT > 34) deltaT = 34;
124
125         HandleEvents();
126         UpdateWorld(deltaT);
127         Render();
128
129         last = now;
130         UpdateState();
131 }
132
133
134 void Application::HandleEvents() {
135         if (!CurrentState()) return;
136         input.ResetInteractiveState();
137         SDL_Event event;
138         while (SDL_PollEvent(&event)) {
139                 switch (event.type) {
140                         case SDL_QUIT:
141                                 PopAllStates();
142                                 break;
143                         case SDL_VIDEORESIZE:
144                                 screen->Resize(event.resize.w, event.resize.h);
145                                 CurrentState()->Resize(event.resize.w, event.resize.h);
146                                 break;
147                         case SDL_KEYDOWN:
148                         case SDL_KEYUP:
149                                 input.HandleKeyboardEvent(event.key);
150                                 break;
151                         default:
152                                 // skip event
153                                 break;
154                 }
155         }
156         CurrentState()->HandleInput(input);
157 }
158
159 void Application::UpdateWorld(Uint32 deltaT) {
160         if (!CurrentState()) return;
161         for (Uint32 i(0); i < deltaT; ++i) {
162                 CurrentState()->UpdateWorld(0.001f);
163         }
164 }
165
166 void Application::Render(void) {
167         if (!CurrentState()) return;
168         CurrentState()->Render(screen->Screen());
169         screen->Flip();
170 }
171
172 }