../src/battle/states/SelectItem.cpp \
../src/battle/states/SelectMoveAction.cpp \
../src/battle/states/SelectSpell.cpp \
-../src/battle/states/SelectTarget.cpp
+../src/battle/states/SelectTarget.cpp \
+../src/battle/states/SwapHeroes.cpp
OBJS += \
./src/battle/states/SelectAttackType.o \
./src/battle/states/SelectItem.o \
./src/battle/states/SelectMoveAction.o \
./src/battle/states/SelectSpell.o \
-./src/battle/states/SelectTarget.o
+./src/battle/states/SelectTarget.o \
+./src/battle/states/SwapHeroes.o
CPP_DEPS += \
./src/battle/states/SelectAttackType.d \
./src/battle/states/SelectItem.d \
./src/battle/states/SelectMoveAction.d \
./src/battle/states/SelectSpell.d \
-./src/battle/states/SelectTarget.d
+./src/battle/states/SelectTarget.d \
+./src/battle/states/SwapHeroes.d
# Each subdirectory must supply rules for building sources it contributes
../src/battle/states/SelectItem.cpp \
../src/battle/states/SelectMoveAction.cpp \
../src/battle/states/SelectSpell.cpp \
-../src/battle/states/SelectTarget.cpp
+../src/battle/states/SelectTarget.cpp \
+../src/battle/states/SwapHeroes.cpp
OBJS += \
./src/battle/states/SelectAttackType.o \
./src/battle/states/SelectItem.o \
./src/battle/states/SelectMoveAction.o \
./src/battle/states/SelectSpell.o \
-./src/battle/states/SelectTarget.o
+./src/battle/states/SelectTarget.o \
+./src/battle/states/SwapHeroes.o
CPP_DEPS += \
./src/battle/states/SelectAttackType.d \
./src/battle/states/SelectItem.d \
./src/battle/states/SelectMoveAction.d \
./src/battle/states/SelectSpell.d \
-./src/battle/states/SelectTarget.d
+./src/battle/states/SelectTarget.d \
+./src/battle/states/SwapHeroes.d
# Each subdirectory must supply rules for building sources it contributes
#include "../geometry/operators.h"
#include "../graphics/Sprite.h"
+#include <algorithm>
#include <stdexcept>
using app::Application;
heroes.push_back(h);
}
+void BattleState::SwapHeroes(std::vector<Hero>::size_type lhs, std::vector<Hero>::size_type rhs) {
+ if (lhs < 0 || lhs >= heroes.size() || rhs < 0 || rhs >= heroes.size() || lhs == rhs) return;
+ std::swap(heroes[lhs], heroes[rhs]);
+}
+
void BattleState::Resize(int w, int h) {
LoadSpellMenu(i);
ikariMenus.push_back(res->ikariMenuPrototype);
LoadIkariMenu(i);
- heroTags[i] = HeroTag(&heroes[i], attackChoices + i, res, HeroTag::Alignment((i + 1) % 2));
+ heroTags[i] = HeroTag(this, i);
}
int tagHeight(attackTypeMenu.Height());
const Hero &ActiveHero() const { return heroes[activeHero]; }
Hero &HeroAt(std::vector<Hero>::size_type index) { return heroes[index]; }
const Hero &HeroAt(std::vector<Hero>::size_type index) const { return heroes[index]; }
+ void SwapHeroes(std::vector<Hero>::size_type lhs, std::vector<Hero>::size_type rhs);
const HeroTag &ActiveHeroTag() const { return heroTags[activeHero]; }
const HeroTag &HeroTagAt(std::vector<Hero>::size_type index) const { return heroTags[index]; }
const geometry::Point<int> &HeroTagPositionAt(std::vector<Hero>::size_type index) const { return heroTagPositions[index]; }
void SetAttackType(AttackChoice::Type t) { attackChoices[activeHero].SetType(t); }
AttackChoice &ActiveHeroAttackChoice() { return attackChoices[activeHero]; }
const AttackChoice &ActiveHeroAttackChoice() const { return attackChoices[activeHero]; }
+ const AttackChoice &AttackChoiceAt(std::vector<Hero>::size_type index) const { return attackChoices[index]; }
TargetSelection &ActiveHeroTargets() { return attackChoices[activeHero].Selection(); }
const TargetSelection &ActiveHeroTargets() const { return attackChoices[activeHero].Selection(); }
bool AttackSelectionDone() const { return activeHero >= (int) heroes.size(); }
#include "HeroTag.h"
#include "AttackChoice.h"
+#include "BattleState.h"
#include "Hero.h"
#include "Resources.h"
#include "../geometry/operators.h"
namespace battle {
+const graphics::Sprite *HeroTag::HeroSprite() const {
+ return battle->HeroAt(index).Sprite();
+}
+
void HeroTag::Render(SDL_Surface *screen, int width, int height, Point<int> position, bool active) const {
// frame
- const Frame *frame(active ? res->activeHeroTagFrame : res->heroTagFrame);
+ const Frame *frame(active ? battle->Res().activeHeroTagFrame : battle->Res().heroTagFrame);
Vector<int> frameOffset(frame->BorderWidth(), frame->BorderHeight());
- Vector<int> alignOffset(align == LEFT ? 4 * res->heroTagFont->CharWidth() : 0, 0);
+ Vector<int> alignOffset((index % 2) ? 4 * battle->Res().heroTagFont->CharWidth() : 0, 0);
frame->Draw(screen, position, width, height);
+ const Hero &hero(battle->HeroAt(index));
+
// gauges
// NOTE: assuming frame border is unit size until charsets are impemented
- int gaugeX((align == LEFT ? 10 : 6) * res->heroTagFont->CharWidth());
+ int gaugeX(((index % 2) ? 10 : 6) * battle->Res().heroTagFont->CharWidth());
// 4 units reserved for hero, gaugeX already includes frame offset
- int gaugeWidth(width - gaugeX - (align == LEFT ? 1 : 5) * res->heroTagFont->CharWidth());
+ int gaugeWidth(width - gaugeX - ((index % 2) ? 1 : 5) * battle->Res().heroTagFont->CharWidth());
// health gauge, second line
- Vector<int> healthGaugeOffset(gaugeX, frameOffset.Y() + res->heroTagFont->CharHeight());
- res->healthGauge->Draw(screen, position + healthGaugeOffset, gaugeWidth, hero->RelativeHealth(255));
+ Vector<int> healthGaugeOffset(gaugeX, frameOffset.Y() + battle->Res().heroTagFont->CharHeight());
+ battle->Res().healthGauge->Draw(screen, position + healthGaugeOffset, gaugeWidth, hero.RelativeHealth(255));
// mana gauge, third line
- Vector<int> manaGaugeOffset(gaugeX, frameOffset.Y() + 2 * res->heroTagFont->CharHeight());
- res->manaGauge->Draw(screen, position + manaGaugeOffset, gaugeWidth, hero->RelativeMana(255));
+ Vector<int> manaGaugeOffset(gaugeX, frameOffset.Y() + 2 * battle->Res().heroTagFont->CharHeight());
+ battle->Res().manaGauge->Draw(screen, position + manaGaugeOffset, gaugeWidth, hero.RelativeMana(255));
// ikari gauge, fourth line
- Vector<int> ikariGaugeOffset(gaugeX, frameOffset.Y() + 3 * res->heroTagFont->CharHeight());
- res->ikariGauge->Draw(screen, position + ikariGaugeOffset, gaugeWidth, hero->RelativeIP(255));
+ Vector<int> ikariGaugeOffset(gaugeX, frameOffset.Y() + 3 * battle->Res().heroTagFont->CharHeight());
+ battle->Res().ikariGauge->Draw(screen, position + ikariGaugeOffset, gaugeWidth, hero.RelativeIP(255));
// labels
- int labelX((align == LEFT ? 5 : 1) * res->heroTagFont->CharWidth());
+ int labelX(((index % 2) ? 5 : 1) * battle->Res().heroTagFont->CharWidth());
// level
Vector<int> levelLabelOffset(gaugeX, frameOffset.Y());
- res->heroTagLabels->Draw(screen, position + levelLabelOffset, 0, 0);
+ battle->Res().heroTagLabels->Draw(screen, position + levelLabelOffset, 0, 0);
// hp
- Vector<int> healthLabelOffset(labelX, frameOffset.Y() + res->heroTagFont->CharHeight());
- res->heroTagLabels->Draw(screen, position + healthLabelOffset, 0, 1);
+ Vector<int> healthLabelOffset(labelX, frameOffset.Y() + battle->Res().heroTagFont->CharHeight());
+ battle->Res().heroTagLabels->Draw(screen, position + healthLabelOffset, 0, 1);
// mp
- Vector<int> manaLabelOffset(labelX, frameOffset.Y() + 2 * res->heroTagFont->CharHeight());
- res->heroTagLabels->Draw(screen, position + manaLabelOffset, 0, 2);
+ Vector<int> manaLabelOffset(labelX, frameOffset.Y() + 2 * battle->Res().heroTagFont->CharHeight());
+ battle->Res().heroTagLabels->Draw(screen, position + manaLabelOffset, 0, 2);
// cm
- Vector<int> moveLabelOffset(labelX, frameOffset.Y() + 3 * res->heroTagFont->CharHeight());
- res->heroTagLabels->Draw(screen, position + moveLabelOffset, 0, 3);
+ Vector<int> moveLabelOffset(labelX, frameOffset.Y() + 3 * battle->Res().heroTagFont->CharHeight());
+ battle->Res().heroTagLabels->Draw(screen, position + moveLabelOffset, 0, 3);
// ip
- Vector<int> ikariLabelOffset(labelX + 3 * res->heroTagFont->CharWidth(), frameOffset.Y() + 3 * res->heroTagFont->CharHeight());
- res->heroTagLabels->Draw(screen, position + ikariLabelOffset, 0, 4);
+ Vector<int> ikariLabelOffset(labelX + 3 * battle->Res().heroTagFont->CharWidth(), frameOffset.Y() + 3 * battle->Res().heroTagFont->CharHeight());
+ battle->Res().heroTagLabels->Draw(screen, position + ikariLabelOffset, 0, 4);
// numbers
// level
- Vector<int> levelNumberOffset(gaugeX + res->heroTagLabels->Width(), levelLabelOffset.Y());
- res->heroTagFont->DrawNumber(hero->Level(), screen, position + levelNumberOffset, 2);
+ Vector<int> levelNumberOffset(gaugeX + battle->Res().heroTagLabels->Width(), levelLabelOffset.Y());
+ battle->Res().heroTagFont->DrawNumber(hero.Level(), screen, position + levelNumberOffset, 2);
// health
- Vector<int> healthNumberOffset(labelX + res->heroTagLabels->Width(), healthLabelOffset.Y());
- res->heroTagFont->DrawNumber(hero->Health(), screen, position + healthNumberOffset, 3);
+ Vector<int> healthNumberOffset(labelX + battle->Res().heroTagLabels->Width(), healthLabelOffset.Y());
+ battle->Res().heroTagFont->DrawNumber(hero.Health(), screen, position + healthNumberOffset, 3);
//mana
- Vector<int> manaNumberOffset(labelX + res->heroTagLabels->Width(), manaLabelOffset.Y());
- res->heroTagFont->DrawNumber(hero->Mana(), screen, position + manaNumberOffset, 3);
+ Vector<int> manaNumberOffset(labelX + battle->Res().heroTagLabels->Width(), manaLabelOffset.Y());
+ battle->Res().heroTagFont->DrawNumber(hero.Mana(), screen, position + manaNumberOffset, 3);
// name
- res->normalFont->DrawString(hero->Name(), screen, position + frameOffset + alignOffset, 5);
+ battle->Res().normalFont->DrawString(hero.Name(), screen, position + frameOffset + alignOffset, 5);
// attack icon
- if (choice->GetType() != AttackChoice::UNDECIDED) {
- Vector<int> attackIconOffset(labelX + res->heroTagLabels->Width(), frameOffset.Y() + 3 * res->heroTagFont->CharHeight());
- res->attackChoiceIcons->Draw(screen, position + attackIconOffset, 0, choice->GetType());
+ if (battle->AttackChoiceAt(index).GetType() != AttackChoice::UNDECIDED) {
+ Vector<int> attackIconOffset(labelX + battle->Res().heroTagLabels->Width(), frameOffset.Y() + 3 * battle->Res().heroTagFont->CharHeight());
+ battle->Res().attackChoiceIcons->Draw(screen, position + attackIconOffset, 0, battle->AttackChoiceAt(index).GetType());
}
// hero
- hero->Sprite()->Draw(screen, position + HeroOffset(), 0, hero->Health() > 0 ? 0 : 2);
+ HeroSprite()->Draw(screen, position + HeroOffset(), 0, battle->HeroAt(index).Health() > 0 ? 0 : 2);
}
Vector<int> HeroTag::HeroOffset() const {
return Vector<int>(
- (align == LEFT) ? res->normalFont->CharWidth() : 10 * res->normalFont->CharWidth(),
- res->normalFont->CharWidth());
+ (index % 2) ? battle->Res().normalFont->CharWidth() : 10 * battle->Res().normalFont->CharWidth(),
+ battle->Res().normalFont->CharWidth());
}
}
namespace battle {
-class AttackChoice;
-struct Resources;
+class BattleState;
class HeroTag {
public:
- enum Alignment {
- LEFT,
- RIGHT
- };
-
-public:
- HeroTag() : hero(0), choice(0), res(0), align(LEFT) { };
- HeroTag(const Hero *hero, const AttackChoice *choice, const Resources *res, Alignment align)
- : hero(hero), choice(choice), res(res), align(align) { }
+ HeroTag() : battle(0), index(0) { };
+ HeroTag(const BattleState *battle, int heroIndex)
+ : battle(battle), index(heroIndex) { }
~HeroTag() { }
public:
- const graphics::Sprite *HeroSprite() const { return hero->Sprite(); }
+ const graphics::Sprite *HeroSprite() const;
geometry::Vector<int> HeroOffset() const;
void Render(SDL_Surface *screen, int width, int height, geometry::Point<int> position, bool active) const;
private:
- const Hero *hero;
- const AttackChoice *choice;
- const Resources *res;
- Alignment align;
+ const BattleState *battle;
+ int index;
};
struct Resources {
+ graphics::Sprite *swapCursor;
graphics::Sprite *moveIcons;
graphics::Sprite *attackIcons;
graphics::Sprite *attackChoiceIcons;
Resources()
- : moveIcons(0)
+ : swapCursor(0)
+ , moveIcons(0)
, attackIcons(0)
, attackChoiceIcons(0)
#include "SelectMoveAction.h"
#include "SelectAttackType.h"
+#include "SwapHeroes.h"
#include "../BattleState.h"
#include "../MoveMenu.h"
#include "../../app/Application.h"
battle->NextHero();
break;
case MoveMenu::CHANGE:
- // TODO: switch to change state
+ ctrl->PushState(new SwapHeroes(battle, this));
break;
case MoveMenu::RUN:
// TODO: switch to run state
--- /dev/null
+/*
+ * SwapHeroes.cpp
+ *
+ * Created on: Aug 10, 2012
+ * Author: holy
+ */
+
+#include "SwapHeroes.h"
+
+#include "SelectMoveAction.h"
+#include "../BattleState.h"
+#include "../../app/Application.h"
+#include "../../app/Input.h"
+#include "../../geometry/operators.h"
+#include "../../geometry/Point.h"
+
+using app::Application;
+using app::Input;
+using geometry::Point;
+using geometry::Vector;
+using std::vector;
+
+namespace battle {
+
+void SwapHeroes::EnterState(Application &c, SDL_Surface *screen) {
+ ctrl = &c;
+}
+
+void SwapHeroes::ExitState(Application &c, SDL_Surface *screen) {
+ ctrl = 0;
+}
+
+void SwapHeroes::ResumeState(Application &ctrl, SDL_Surface *screen) {
+
+}
+
+void SwapHeroes::PauseState(Application &ctrl, SDL_Surface *screen) {
+
+}
+
+
+void SwapHeroes::Resize(int width, int height) {
+
+}
+
+
+void SwapHeroes::HandleInput(const Input &input) {
+ if (input.JustPressed(Input::ACTION_A)) {
+ if (selected != -1 && cursor != selected) {
+ battle->SwapHeroes(cursor, selected);
+ selected = -1;
+ } else {
+ selected = cursor;
+ }
+ }
+ if (input.JustPressed(Input::ACTION_B)) {
+ if (cursor == selected) {
+ selected = -1;
+ } else {
+ ctrl->PopState();
+ }
+ }
+
+ if (input.JustPressed(Input::PAD_UP)) {
+ MoveUp();
+ }
+ if (input.JustPressed(Input::PAD_RIGHT)) {
+ MoveRight();
+ }
+ if (input.JustPressed(Input::PAD_DOWN)) {
+ MoveDown();
+ }
+ if (input.JustPressed(Input::PAD_LEFT)) {
+ MoveLeft();
+ }
+}
+
+
+void SwapHeroes::MoveUp() {
+ if (cursor < 2) {
+ if (battle->HeroPositionOccupied(cursor + 2)) {
+ cursor += 2;
+ }
+ } else {
+ cursor -= 2;
+ }
+}
+
+void SwapHeroes::MoveRight() {
+ if (cursor < 3 && battle->HeroPositionOccupied(cursor + 1)) {
+ ++cursor;
+ } else {
+ cursor = 0;
+ }
+}
+
+void SwapHeroes::MoveDown() {
+ if (cursor < 2) {
+ if (battle->HeroPositionOccupied(cursor + 2)) {
+ cursor += 2;
+ }
+ } else {
+ cursor -= 2;
+ }
+}
+
+void SwapHeroes::MoveLeft() {
+ if (cursor > 0) {
+ --cursor;
+ } else {
+ cursor = battle->Heroes().size();
+ }
+}
+
+
+void SwapHeroes::UpdateWorld(float deltaT) {
+
+}
+
+void SwapHeroes::Render(SDL_Surface *screen) {
+ Vector<int> offset(battle->CalculateScreenOffset(screen));
+ parent->Render(screen);
+ RenderCursors(screen, offset);
+}
+
+void SwapHeroes::RenderCursors(SDL_Surface *screen, const geometry::Vector<int> &offset) {
+ // offset the cursor by 1/8th to the left and bottom
+ Vector<int> cursorOffset(battle->Res().swapCursor->Width() / -8, battle->Res().swapCursor->Height() / 8);
+ Vector<int> indicatorOffset(0, 0);
+ vector<Point<int> > positions;
+ for (vector<Hero>::size_type i(0), end(battle->Heroes().size()); i < end; ++i) {
+ Vector<int> positionCorrection(battle->Res().swapCursor->Width() / 2, battle->HeroTagAt(i).HeroSprite()->Height() - battle->Res().swapCursor->Height() / 2);
+ // indicator offsets are inverted for heroes
+ positionCorrection -= cursorOffset;
+ positions.push_back(battle->HeroTagPositionAt(i) + battle->HeroTagAt(i).HeroOffset() + positionCorrection);
+ }
+ if (flipFlop) {
+ for (vector<Point<int> >::size_type i(0); i < positions.size(); ++i) {
+ if (selected == int(i)) {
+ battle->Res().swapCursor->DrawTopRight(screen, positions[i] + offset);
+ }
+ }
+ }
+ flipFlop = !flipFlop;
+ battle->Res().swapCursor->DrawTopRight(screen, positions[cursor] + offset + cursorOffset);
+}
+
+}
--- /dev/null
+/*
+ * SwapHeroes.h
+ *
+ * Created on: Aug 10, 2012
+ * Author: holy
+ */
+
+#ifndef BATTLE_SWAPHEROES_H_
+#define BATTLE_SWAPHEROES_H_
+
+#include "../../app/State.h"
+
+#include "../../geometry/Vector.h"
+
+namespace battle {
+
+class BattleState;
+class SelectMoveAction;
+
+class SwapHeroes
+: public app::State {
+
+public:
+ SwapHeroes(BattleState *battle, SelectMoveAction *parent)
+ : ctrl(0), battle(battle), parent(parent), cursor(0), selected(-1), flipFlop(true) { }
+
+public:
+ virtual void EnterState(app::Application &ctrl, SDL_Surface *screen);
+ 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);
+
+ virtual void HandleInput(const app::Input &);
+ virtual void UpdateWorld(float deltaT);
+ virtual void Render(SDL_Surface *);
+
+private:
+ void MoveUp();
+ void MoveRight();
+ void MoveDown();
+ void MoveLeft();
+
+private:
+ void RenderCursors(SDL_Surface *screen, const geometry::Vector<int> &offset);
+
+private:
+ app::Application *ctrl;
+ BattleState *battle;
+ SelectMoveAction *parent;
+ int cursor;
+ int selected;
+ bool flipFlop;
+
+};
+
+}
+
+#endif /* BATTLE_SWAPHEROES_H_ */
battle::Resources battleRes;
+ SDL_Surface *swapCursorImg(IMG_Load("test-data/swap-cursor.png"));
+ Sprite swapCursorSprite(swapCursorImg, 32, 32);
+ battleRes.swapCursor = &swapCursorSprite;
SDL_Surface *attackIconsImg(IMG_Load("test-data/attack-type-icons.png"));
Sprite attackIconsSprite(attackIconsImg, 32, 32);
battleRes.attackIcons = &attackIconsSprite;