namespace app {
-Application::Application(SDL_Surface *screen, State *initialState)
+Application::Application(sdl::InitScreen *screen, State *initialState)
: screen(screen)
, states()
, last(SDL_GetTicks()) {
RealPushState(initialState);
}
-Application::~Application(void) {
+Application::~Application() {
PopAllStates();
}
-State *Application::CurrentState(void) {
+State *Application::CurrentState() {
return states.top();
}
+void Application::UpdateState() {
+ while (!stateChanges.empty()) {
+ switch (stateChanges.front().type) {
+ case StateCommand::PUSH:
+ RealPushState(stateChanges.front().state);
+ break;
+ case StateCommand::POP:
+ RealPopState();
+ break;
+ case StateCommand::CHANGE:
+ RealChangeState(stateChanges.front().state);
+ break;
+ }
+ stateChanges.pop();
+ }
+}
+
void Application::ChangeState(State *s) {
- RealPopState();
- RealPushState(s);
+ StateCommand cmd;
+ cmd.type = StateCommand::CHANGE;
+ cmd.state = s;
+ stateChanges.push(cmd);
}
void Application::PushState(State *s) {
- RealPushState(s);
+ StateCommand cmd;
+ cmd.type = StateCommand::PUSH;
+ cmd.state = s;
+ stateChanges.push(cmd);
}
-void Application::RealPushState(State *s) {
+void Application::PopState() {
+ StateCommand cmd;
+ cmd.type = StateCommand::POP;
+ cmd.state = 0;
+ stateChanges.push(cmd);
+}
+
+void Application::RealChangeState(State *s) {
+ if (!states.empty()) {
+ states.top()->PauseState(*this, screen->Screen());
+ states.top()->ExitState(*this, screen->Screen());
+ states.pop();
+ }
states.push(s);
- s->EnterState(*this, screen);
+ s->EnterState(*this, screen->Screen());
+ s->ResumeState(*this, screen->Screen());
}
-void Application::PopState(void) {
- RealPopState();
+void Application::RealPushState(State *s) {
+ if (!states.empty()) {
+ states.top()->PauseState(*this, screen->Screen());
+ }
+ states.push(s);
+ s->EnterState(*this, screen->Screen());
+ s->ResumeState(*this, screen->Screen());
}
-void Application::RealPopState(void) {
+void Application::RealPopState() {
if (states.empty()) return;
- states.top()->ExitState();
+ states.top()->PauseState(*this, screen->Screen());
+ states.top()->ExitState(*this, screen->Screen());
delete states.top();
states.pop();
+ if (!states.empty()) {
+ states.top()->ResumeState(*this, screen->Screen());
+ }
}
-void Application::Quit(void) {
+void Application::Quit() {
PopAllStates();
}
-void Application::PopAllStates(void) {
+void Application::PopAllStates() {
while (!states.empty()) {
RealPopState();
}
}
-void Application::Run(void) {
+void Application::Run() {
while (CurrentState()) {
Loop();
}
}
-void Application::Loop(void) {
+void Application::Loop() {
Uint32 now(SDL_GetTicks());
Uint32 deltaT(now - last);
if (deltaT > 34) deltaT = 34;
Render();
last = now;
+ UpdateState();
}
-void Application::HandleEvents(void) {
+void Application::HandleEvents() {
if (!CurrentState()) return;
+ input.ResetInteractiveState();
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
PopAllStates();
break;
+ case SDL_VIDEORESIZE:
+ screen->Resize(event.resize.w, event.resize.h);
+ CurrentState()->Resize(event.resize.w, event.resize.h);
+ break;
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ input.HandleKeyboardEvent(event.key);
+ break;
default:
- CurrentState()->HandleEvent(event);
+ // skip event
break;
}
}
+ CurrentState()->HandleInput(input);
}
void Application::UpdateWorld(Uint32 deltaT) {
void Application::Render(void) {
if (!CurrentState()) return;
- CurrentState()->Render(screen);
- SDL_Flip(screen);
+ CurrentState()->Render(screen->Screen());
+ screen->Flip();
}
}