]> git.localhorst.tv Git - l2e.git/commitdiff
reworked Application's state stack
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 7 Aug 2012 13:14:30 +0000 (15:14 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 7 Aug 2012 13:14:30 +0000 (15:14 +0200)
src/app/Application.cpp
src/app/Application.h
src/app/State.h
src/battle/BattleState.cpp
src/battle/BattleState.h
src/battle/states/SelectAttackType.cpp
src/battle/states/SelectAttackType.h
src/battle/states/SelectMoveAction.cpp
src/battle/states/SelectMoveAction.h

index 19aa06a18543de3e1c7662a490098d794e8e0aca..80ebb5d1ac1c8ae51a63a508a4a763026d1b695e 100644 (file)
@@ -16,8 +16,7 @@ namespace app {
 Application::Application(sdl::InitScreen *screen, State *initialState)
 : screen(screen)
 , states()
-, last(SDL_GetTicks())
-, toPop(0) {
+, last(SDL_GetTicks()) {
        assert(screen && "cannot create application without screen");
        assert(initialState && "cannot create application without initial state");
        RealPushState(initialState);
@@ -33,40 +32,72 @@ State *Application::CurrentState() {
 }
 
 void Application::UpdateState() {
-       while (toPop > 0) {
-               RealPopState();
-               --toPop;
-       }
-       while (!toPush.empty()) {
-               State *s(toPush.front());
-               toPush.pop();
-               RealPushState(s);
+       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) {
-       PopState();
-       PushState(s);
+       StateCommand cmd;
+       cmd.type = StateCommand::CHANGE;
+       cmd.state = s;
+       stateChanges.push(cmd);
 }
 
 void Application::PushState(State *s) {
-       toPush.push(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->Screen());
+       s->ResumeState(*this, screen->Screen());
 }
 
-void Application::PopState() {
-       ++toPop;
+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() {
        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() {
index dcc5e006c0dc36d28b65859bcbb048761cfc96be..853d0cb25cefc91897beeaa41e7365f027a2604a 100644 (file)
@@ -41,9 +41,18 @@ public:
        Input &Buttons() { return input; }
        const Input &Buttons() const { return input; }
 
+private:
+       struct StateCommand {
+               enum Type {
+                       PUSH, POP, CHANGE
+               } type;
+               State *state;
+       };
+
 private:
        State *CurrentState();
        void UpdateState();
+       void RealChangeState(State *);
        void RealPushState(State *);
        void RealPopState();
        void PopAllStates();
@@ -56,10 +65,9 @@ private:
 private:
        sdl::InitScreen *screen;
        std::stack<State *> states;
-       std::queue<State *> toPush;
+       std::queue<StateCommand> stateChanges;
        Input input;
        Uint32 last;
-       int toPop;
 
 };
 
index 7f46c5746c580ddc1ea089acab018d2f3b1f5926..678f2b986d88d69d68366bb829aaebbef47c0124 100644 (file)
@@ -22,9 +22,16 @@ public:
 
 public:
        /// do some setup
+       /// called when the state first enters the stack
        /// @param ctrl the Application running the state
        virtual void EnterState(Application &ctrl, SDL_Surface *screen) = 0;
-       virtual void ExitState() = 0;
+       /// do some cleanup
+       /// called when the state is popped from the stack
+       virtual void ExitState(Application &ctrl, SDL_Surface *screen) = 0;
+       /// called when the state becomes the active one
+       virtual void ResumeState(Application &ctrl, SDL_Surface *screen) = 0;
+       /// called when the state becomes inactive
+       virtual void PauseState(Application &ctrl, SDL_Surface *screen) = 0;
 
        /// adapt the state's graphics to given dimensions
        virtual void Resize(int width, int height) = 0;
index 4e12f7929a5be2ada8fa319e6ce275827375fae0..2c5fe8174449ceb899f2bf7f8f634baff60304ba 100644 (file)
@@ -51,10 +51,21 @@ void BattleState::EnterState(Application &ctrl, SDL_Surface *screen) {
        for (vector<Hero>::size_type i(0), end(heroes.size()); i < end; ++i) {
                heroTags.push_back(HeroTag(&heroes[i], HeroTag::Alignment((i + 1) % 2)));
        }
+}
+
+void BattleState::ExitState(Application &ctrl, SDL_Surface *screen) {
+
+}
+
+void BattleState::ResumeState(Application &ctrl, SDL_Surface *screen) {
+       // reset attack choices
+       activeHero = -1;
+       attackChoices.clear();
+       attackChoices.resize(heroes.size());
        ctrl.PushState(new SelectMoveAction(this));
 }
 
-void BattleState::ExitState() {
+void BattleState::PauseState(Application &ctrl, SDL_Surface *screen) {
 
 }
 
@@ -74,7 +85,6 @@ void BattleState::Render(SDL_Surface *screen) {
        RenderMonsters(screen, offset);
 //     RenderHeroes(screen, offset);
        RenderHeroTags(screen, offset);
-       RenderAttackTypeMenu(screen, offset);
 }
 
 void BattleState::RenderBackground(SDL_Surface *screen, const Vector<int> &offset) {
@@ -112,15 +122,8 @@ void BattleState::RenderHeroTags(SDL_Surface *screen, const Vector<int> &offset)
        tagPosition[3] = Point<int>(tagWidth + attackTypeMenu.IconWidth(), uiOffset + tagHeight + attackTypeMenu.IconHeight());
 
        for (vector<HeroTag>::size_type i(0), end(heroTags.size()); i < end; ++i) {
-               heroTags[i].Render(screen, tagWidth, tagHeight, tagPosition[i] + offset, i == activeHero);
+               heroTags[i].Render(screen, tagWidth, tagHeight, tagPosition[i] + offset, (int)i == activeHero);
        }
 }
 
-void BattleState::RenderAttackTypeMenu(SDL_Surface *screen, const Vector<int> &offset) {
-       Point<int> position(
-                       (BackgroundWidth() - attackTypeMenu.Width()) / 2,
-                       (BackgroundHeight() * 3 / 4) - (attackTypeMenu.Height() / 2));
-       attackTypeMenu.Render(screen, position + offset);
-}
-
 }
index 73f3fbc01813c478870d6cb42ff7988b87872c9b..12c55f71856d1536cc12e432ec7cca0777f72b03 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef BATTLE_BATTLESTATE_H_
 #define BATTLE_BATTLESTATE_H_
 
+#include "AttackChoice.h"
 #include "AttackTypeMenu.h"
 #include "Hero.h"
 #include "HeroTag.h"
@@ -46,7 +47,9 @@ public:
 
 public:
        virtual void EnterState(app::Application &ctrl, SDL_Surface *screen);
-       virtual void ExitState();
+       virtual void ExitState(app::Application &ctrl, SDL_Surface *screen);
+       virtual void ResumeState(app::Application &ctrl, SDL_Surface *screen);
+       virtual void PauseState(app::Application &ctrl, SDL_Surface *screen);
 
        virtual void Resize(int width, int height);
 
@@ -60,6 +63,9 @@ public:
 
        bool HasMoreHeroes() const { return activeHero < (int) heroes.size(); }
        void NextHero() { ++activeHero; }
+       bool HasChosenAttackType() const { return attackChoices[activeHero].GetType() != AttackChoice::UNDECIDED; }
+       void SetAttackType(AttackChoice::Type t) { attackChoices[activeHero].SetType(t); }
+       bool AttackSelectionDone() const { return activeHero >= (int) heroes.size(); }
 
 public:
        geometry::Vector<int> CalculateScreenOffset(SDL_Surface *screen) const {
@@ -74,7 +80,6 @@ public:
        void RenderMonsters(SDL_Surface *screen, const geometry::Vector<int> &offset);
        void RenderHeroes(SDL_Surface *screen, const geometry::Vector<int> &offset);
        void RenderHeroTags(SDL_Surface *screen, const geometry::Vector<int> &offset);
-       void RenderAttackTypeMenu(SDL_Surface *screen, const geometry::Vector<int> &offset);
 
 private:
        SDL_Surface *background;
@@ -87,6 +92,7 @@ private:
        std::vector<Monster> monsters;
        std::vector<Hero> heroes;
        std::vector<HeroTag> heroTags;
+       std::vector<AttackChoice> attackChoices;
        int activeHero;
 
 };
index c0548132b536c115d5cee98265ce4afd43856ace..c7a65be7a3ade4d69d9c54895d2248d24ac587d0 100644 (file)
@@ -9,25 +9,35 @@
 
 #include "../AttackChoice.h"
 #include "../BattleState.h"
+#include "../../app/Application.h"
 #include "../../app/Input.h"
 #include "../../geometry/operators.h"
 
 #include <stdexcept>
 
+using app::Application;
 using app::Input;
 using geometry::Point;
 using geometry::Vector;
 
 namespace battle {
 
-void SelectAttackType::EnterState(app::Application &c, SDL_Surface *screen) {
+void SelectAttackType::EnterState(Application &c, SDL_Surface *screen) {
        ctrl = &c;
 }
 
-void SelectAttackType::ExitState() {
+void SelectAttackType::ExitState(Application &c, SDL_Surface *screen) {
        ctrl = 0;
 }
 
+void SelectAttackType::ResumeState(Application &ctrl, SDL_Surface *screen) {
+
+}
+
+void SelectAttackType::PauseState(Application &ctrl, SDL_Surface *screen) {
+
+}
+
 
 void SelectAttackType::Resize(int width, int height) {
 
@@ -48,15 +58,16 @@ void SelectAttackType::HandleInput(const Input &input) {
        }
 
        if (input.JustPressed(Input::ACTION_A)) {
+               battle->SetAttackType(battle->GetAttackTypeMenu().Selected());
                switch (battle->GetAttackTypeMenu().Selected()) {
                        case AttackChoice::SWORD:
-                               // TODO: switch to next character
+                               battle->NextHero();
                                break;
                        case AttackChoice::MAGIC:
                                // TODO: switch to spell select
                                break;
                        case AttackChoice::DEFEND:
-                               // TODO: switch to next character
+                               battle->NextHero();
                                break;
                        case AttackChoice::IKARI:
                                // TODO: switch to ikari attack select
@@ -68,6 +79,11 @@ void SelectAttackType::HandleInput(const Input &input) {
                                throw std::logic_error("selected invalid attack type");
                }
        }
+
+       if (battle->AttackSelectionDone()) {
+               // TODO: switch to battle animation instead
+               ctrl->PopState();
+       }
 }
 
 void SelectAttackType::UpdateWorld(float deltaT) {
index 3b101881ff5d22e123438569e409b9252d53f5c5..b2974bb423ecdf68105e6209c977474b358b3a7a 100644 (file)
@@ -26,7 +26,9 @@ public:
 
 public:
        virtual void EnterState(app::Application &ctrl, SDL_Surface *screen);
-       virtual void ExitState();
+       virtual void ExitState(app::Application &ctrl, SDL_Surface *screen);
+       virtual void ResumeState(app::Application &ctrl, SDL_Surface *screen);
+       virtual void PauseState(app::Application &ctrl, SDL_Surface *screen);
 
        virtual void Resize(int width, int height);
 
index 54f0f297661f2654ef49ffb82ed463b07ec57c98..bee880be88c418135939da8a01c0ee9336eaa792 100644 (file)
 #include "../../app/Input.h"
 #include "../../geometry/operators.h"
 
+using app::Application;
 using app::Input;
 using geometry::Point;
 using geometry::Vector;
 
 namespace battle {
 
-void SelectMoveAction::EnterState(app::Application &c, SDL_Surface *screen) {
+void SelectMoveAction::EnterState(Application &c, SDL_Surface *screen) {
        ctrl = &c;
 }
 
-void SelectMoveAction::ExitState() {
+void SelectMoveAction::ExitState(Application &c, SDL_Surface *screen) {
        ctrl = 0;
 }
 
+void SelectMoveAction::ResumeState(Application &ctrl, SDL_Surface *screen) {
+
+}
+
+void SelectMoveAction::PauseState(Application &ctrl, SDL_Surface *screen) {
+
+}
+
 
 void SelectMoveAction::Resize(int width, int height) {
 
index c1356631beb34421ed53da93d7e353db67dc0c82..bce6bfeab13ee01ffb3183a33be6884462093070 100644 (file)
@@ -26,7 +26,9 @@ public:
 
 public:
        virtual void EnterState(app::Application &ctrl, SDL_Surface *screen);
-       virtual void ExitState();
+       virtual void ExitState(app::Application &ctrl, SDL_Surface *screen);
+       virtual void ResumeState(app::Application &ctrl, SDL_Surface *screen);
+       virtual void PauseState(app::Application &ctrl, SDL_Surface *screen);
 
        virtual void Resize(int width, int height);