X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fapp%2FApplication.cpp;h=b84d7248da1a465b7eafa557cc85c0d393b6789f;hb=2ccc2369d32fb680a3047519d79c17de34c4e10a;hp=d3b00a1efaf125aa38f62561979b5c8a0bdd038c;hpb=867fd5d9b79c3b9c1d0fb17ba9f55cfe971b93d5;p=l2e.git diff --git a/src/app/Application.cpp b/src/app/Application.cpp index d3b00a1..b84d724 100644 --- a/src/app/Application.cpp +++ b/src/app/Application.cpp @@ -13,80 +13,148 @@ namespace app { -Application::Application(sdl::InitScreen *screen, State *initialState) +Application::Application(sdl::InitScreen &screen, State *initialState) : screen(screen) , states() -, last(SDL_GetTicks()) { - assert(screen && "cannot create application without screen"); +, last(SDL_GetTicks()) +, inStateChage(false) { assert(initialState && "cannot create application without initial state"); RealPushState(initialState); } -Application::~Application(void) { +Application::~Application() { PopAllStates(); } -State *Application::CurrentState(void) { - return states.top(); +State *Application::CurrentState() { + return states.empty() ? 0 : states.top(); +} + +void Application::UpdateState() { + inStateChage = true; + 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(); + } + inStateChage = false; } void Application::ChangeState(State *s) { - RealPopState(); - RealPushState(s); + if (inStateChage) { + RealChangeState(s); + } else { + StateCommand cmd; + cmd.type = StateCommand::CHANGE; + cmd.state = s; + stateChanges.push(cmd); + } } void Application::PushState(State *s) { - RealPushState(s); + if (inStateChage) { + RealPushState(s); + } else { + StateCommand cmd; + cmd.type = StateCommand::PUSH; + cmd.state = s; + stateChanges.push(cmd); + } } -void Application::RealPushState(State *s) { +void Application::PopState() { + if (inStateChage) { + RealPopState(); + } else { + StateCommand cmd; + cmd.type = StateCommand::POP; + cmd.state = 0; + stateChanges.push(cmd); + } +} + +void Application::RealChangeState(State *s) { + if (!states.empty()) { + states.top()->OnPauseState(*this, screen.Screen()); + states.top()->OnExitState(*this, screen.Screen()); + states.pop(); + } states.push(s); - s->EnterState(*this, screen->Screen()); + s->OnEnterState(*this, screen.Screen()); + s->OnResumeState(*this, screen.Screen()); } -void Application::PopState(void) { - RealPopState(); +void Application::RealPushState(State *s) { + if (!states.empty()) { + states.top()->OnPauseState(*this, screen.Screen()); + } + states.push(s); + s->OnEnterState(*this, screen.Screen()); + s->OnResumeState(*this, screen.Screen()); } -void Application::RealPopState(void) { +void Application::RealPopState() { if (states.empty()) return; - states.top()->ExitState(); + states.top()->OnPauseState(*this, screen.Screen()); + states.top()->OnExitState(*this, screen.Screen()); delete states.top(); states.pop(); + if (!states.empty()) { + states.top()->OnResumeState(*this, screen.Screen()); + } } -void Application::Quit(void) { +void Application::Quit() { PopAllStates(); } -void Application::PopAllStates(void) { +void Application::PopAllStates() { while (!states.empty()) { - RealPopState(); + states.top()->OnPauseState(*this, screen.Screen()); + states.top()->OnExitState(*this, screen.Screen()); + delete states.top(); + states.pop(); } } -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; + GlobalTimers().Update(deltaT); + if (deltaT > 30) deltaT = 30; + if (CurrentState()) { + CurrentState()->GraphicsTimers().Update(deltaT); + } HandleEvents(); - UpdateWorld(deltaT); - Render(); + if (!StateChangePending()) { + UpdateWorld(deltaT); + Render(); + } last = now; + UpdateState(); } -void Application::HandleEvents(void) { +void Application::HandleEvents() { if (!CurrentState()) return; input.ResetInteractiveState(); SDL_Event event; @@ -96,8 +164,8 @@ void Application::HandleEvents(void) { PopAllStates(); break; case SDL_VIDEORESIZE: - screen->Resize(event.resize.w, event.resize.h); - CurrentState()->Resize(event.resize.w, event.resize.h); + screen.Resize(event.resize.w, event.resize.h); + CurrentState()->OnResize(event.resize.w, event.resize.h); break; case SDL_KEYDOWN: case SDL_KEYUP: @@ -108,20 +176,21 @@ void Application::HandleEvents(void) { break; } } - CurrentState()->HandleInput(input); + if (CurrentState()) CurrentState()->HandleEvents(input); } void Application::UpdateWorld(Uint32 deltaT) { if (!CurrentState()) return; - for (Uint32 i(0); i < deltaT; ++i) { + for (Uint32 i(0); i < deltaT && !StateChangePending(); ++i) { + CurrentState()->PhysicsTimers().Update(0.001f); CurrentState()->UpdateWorld(0.001f); } } void Application::Render(void) { if (!CurrentState()) return; - CurrentState()->Render(screen->Screen()); - screen->Flip(); + CurrentState()->Render(screen.Screen()); + screen.Flip(); } }