From 3c72a71fbf6de96333a641051a20c6bf8b3a5df3 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Fri, 10 Aug 2012 03:45:31 +0200 Subject: [PATCH] added attack targets selection state --- Debug/src/battle/states/subdir.mk | 9 +- Debug/src/battle/subdir.mk | 9 +- Release/src/battle/states/subdir.mk | 9 +- Release/src/battle/subdir.mk | 9 +- src/battle/AttackChoice.h | 7 +- src/battle/BattleState.cpp | 28 +++--- src/battle/BattleState.h | 21 ++++- src/battle/HeroTag.cpp | 13 +-- src/battle/HeroTag.h | 7 +- src/battle/Monster.h | 2 + src/battle/Resources.h | 7 ++ src/battle/TargetSelection.cpp | 97 ++++++++++++++++++++ src/battle/TargetSelection.h | 67 ++++++++++++++ src/battle/states/SelectAttackType.cpp | 14 ++- src/battle/states/SelectTarget.cpp | 117 +++++++++++++++++++++++++ src/battle/states/SelectTarget.h | 57 ++++++++++++ src/graphics/Sprite.h | 4 + src/main.cpp | 10 +++ test-data/targeting-icons.png | Bin 0 -> 414 bytes 19 files changed, 448 insertions(+), 39 deletions(-) create mode 100644 src/battle/TargetSelection.cpp create mode 100644 src/battle/TargetSelection.h create mode 100644 src/battle/states/SelectTarget.cpp create mode 100644 src/battle/states/SelectTarget.h create mode 100644 test-data/targeting-icons.png diff --git a/Debug/src/battle/states/subdir.mk b/Debug/src/battle/states/subdir.mk index 8217544..a4898a8 100644 --- a/Debug/src/battle/states/subdir.mk +++ b/Debug/src/battle/states/subdir.mk @@ -8,21 +8,24 @@ CPP_SRCS += \ ../src/battle/states/SelectIkari.cpp \ ../src/battle/states/SelectItem.cpp \ ../src/battle/states/SelectMoveAction.cpp \ -../src/battle/states/SelectSpell.cpp +../src/battle/states/SelectSpell.cpp \ +../src/battle/states/SelectTarget.cpp OBJS += \ ./src/battle/states/SelectAttackType.o \ ./src/battle/states/SelectIkari.o \ ./src/battle/states/SelectItem.o \ ./src/battle/states/SelectMoveAction.o \ -./src/battle/states/SelectSpell.o +./src/battle/states/SelectSpell.o \ +./src/battle/states/SelectTarget.o CPP_DEPS += \ ./src/battle/states/SelectAttackType.d \ ./src/battle/states/SelectIkari.d \ ./src/battle/states/SelectItem.d \ ./src/battle/states/SelectMoveAction.d \ -./src/battle/states/SelectSpell.d +./src/battle/states/SelectSpell.d \ +./src/battle/states/SelectTarget.d # Each subdirectory must supply rules for building sources it contributes diff --git a/Debug/src/battle/subdir.mk b/Debug/src/battle/subdir.mk index dd0f37f..c459c3e 100644 --- a/Debug/src/battle/subdir.mk +++ b/Debug/src/battle/subdir.mk @@ -11,7 +11,8 @@ CPP_SRCS += \ ../src/battle/HeroTag.cpp \ ../src/battle/Monster.cpp \ ../src/battle/MoveMenu.cpp \ -../src/battle/PartyLayout.cpp +../src/battle/PartyLayout.cpp \ +../src/battle/TargetSelection.cpp OBJS += \ ./src/battle/AttackChoice.o \ @@ -21,7 +22,8 @@ OBJS += \ ./src/battle/HeroTag.o \ ./src/battle/Monster.o \ ./src/battle/MoveMenu.o \ -./src/battle/PartyLayout.o +./src/battle/PartyLayout.o \ +./src/battle/TargetSelection.o CPP_DEPS += \ ./src/battle/AttackChoice.d \ @@ -31,7 +33,8 @@ CPP_DEPS += \ ./src/battle/HeroTag.d \ ./src/battle/Monster.d \ ./src/battle/MoveMenu.d \ -./src/battle/PartyLayout.d +./src/battle/PartyLayout.d \ +./src/battle/TargetSelection.d # Each subdirectory must supply rules for building sources it contributes diff --git a/Release/src/battle/states/subdir.mk b/Release/src/battle/states/subdir.mk index 6bd8035..23338be 100644 --- a/Release/src/battle/states/subdir.mk +++ b/Release/src/battle/states/subdir.mk @@ -8,21 +8,24 @@ CPP_SRCS += \ ../src/battle/states/SelectIkari.cpp \ ../src/battle/states/SelectItem.cpp \ ../src/battle/states/SelectMoveAction.cpp \ -../src/battle/states/SelectSpell.cpp +../src/battle/states/SelectSpell.cpp \ +../src/battle/states/SelectTarget.cpp OBJS += \ ./src/battle/states/SelectAttackType.o \ ./src/battle/states/SelectIkari.o \ ./src/battle/states/SelectItem.o \ ./src/battle/states/SelectMoveAction.o \ -./src/battle/states/SelectSpell.o +./src/battle/states/SelectSpell.o \ +./src/battle/states/SelectTarget.o CPP_DEPS += \ ./src/battle/states/SelectAttackType.d \ ./src/battle/states/SelectIkari.d \ ./src/battle/states/SelectItem.d \ ./src/battle/states/SelectMoveAction.d \ -./src/battle/states/SelectSpell.d +./src/battle/states/SelectSpell.d \ +./src/battle/states/SelectTarget.d # Each subdirectory must supply rules for building sources it contributes diff --git a/Release/src/battle/subdir.mk b/Release/src/battle/subdir.mk index 4ab8784..65a6623 100644 --- a/Release/src/battle/subdir.mk +++ b/Release/src/battle/subdir.mk @@ -11,7 +11,8 @@ CPP_SRCS += \ ../src/battle/HeroTag.cpp \ ../src/battle/Monster.cpp \ ../src/battle/MoveMenu.cpp \ -../src/battle/PartyLayout.cpp +../src/battle/PartyLayout.cpp \ +../src/battle/TargetSelection.cpp OBJS += \ ./src/battle/AttackChoice.o \ @@ -21,7 +22,8 @@ OBJS += \ ./src/battle/HeroTag.o \ ./src/battle/Monster.o \ ./src/battle/MoveMenu.o \ -./src/battle/PartyLayout.o +./src/battle/PartyLayout.o \ +./src/battle/TargetSelection.o CPP_DEPS += \ ./src/battle/AttackChoice.d \ @@ -31,7 +33,8 @@ CPP_DEPS += \ ./src/battle/HeroTag.d \ ./src/battle/Monster.d \ ./src/battle/MoveMenu.d \ -./src/battle/PartyLayout.d +./src/battle/PartyLayout.d \ +./src/battle/TargetSelection.d # Each subdirectory must supply rules for building sources it contributes diff --git a/src/battle/AttackChoice.h b/src/battle/AttackChoice.h index b11a81d..0068e6f 100644 --- a/src/battle/AttackChoice.h +++ b/src/battle/AttackChoice.h @@ -8,6 +8,8 @@ #ifndef BATTLE_ATTACKCHOICE_H_ #define BATTLE_ATTACKCHOICE_H_ +#include "TargetSelection.h" + namespace battle { class AttackChoice { @@ -23,15 +25,18 @@ public: }; public: - AttackChoice() : type(UNDECIDED) { } + explicit AttackChoice(BattleState *b = 0) : type(UNDECIDED), selection(b) { } ~AttackChoice() { } public: Type GetType() const { return type; } void SetType(Type t) { type = t; } + TargetSelection &Selection() { return selection; } + const TargetSelection &Selection() const { return selection; } private: Type type; + TargetSelection selection; }; diff --git a/src/battle/BattleState.cpp b/src/battle/BattleState.cpp index ec56169..ad22517 100644 --- a/src/battle/BattleState.cpp +++ b/src/battle/BattleState.cpp @@ -53,14 +53,22 @@ void BattleState::Resize(int w, int h) { void BattleState::EnterState(Application &ctrl, SDL_Surface *screen) { monstersLayout->CalculatePositions(background->w, background->h, monsterPositions); heroesLayout->CalculatePositions(background->w, background->h, heroesPositions); - attackChoices.resize(heroes.size()); for (vector::size_type i(0), end(heroes.size()); i < end; ++i) { spellMenus.push_back(res->spellMenuPrototype); // TODO: insert spell menu entries ikariMenus.push_back(res->ikariMenuPrototype); // TODO: insert ikari menu entries - heroTags.push_back(HeroTag(&heroes[i], &attackChoices[i], res, HeroTag::Alignment((i + 1) % 2))); + heroTags[i] = HeroTag(&heroes[i], attackChoices + i, res, HeroTag::Alignment((i + 1) % 2)); } + + int tagHeight(attackTypeMenu.Height()); + int tagWidth(attackTypeMenu.Width() * 2 + attackTypeMenu.Width() / 2); + int xOffset((BackgroundWidth() - 2 * tagWidth) / 2); + heroTagPositions[0] = Point(xOffset, BackgroundHeight() - 2 * tagHeight); + heroTagPositions[1] = Point(xOffset + tagWidth, BackgroundHeight() - 2 * tagHeight); + heroTagPositions[2] = Point(xOffset, BackgroundHeight() - tagHeight); + heroTagPositions[3] = Point(xOffset + tagWidth, BackgroundHeight() - tagHeight); + // TODO: insert item menu entries itemMenu = res->itemMenuPrototype; LoadInventory(); @@ -88,8 +96,9 @@ void BattleState::ResumeState(Application &ctrl, SDL_Surface *screen) { // TODO: check for victory, defeat or run // reset attack choices activeHero = -1; - attackChoices.clear(); - attackChoices.resize(heroes.size()); + for (vector::size_type i(0), end(heroes.size()); i < end; ++i) { + attackChoices[i] = AttackChoice(this); + } ctrl.PushState(new SelectMoveAction(this)); } @@ -141,16 +150,9 @@ void BattleState::RenderHeroes(SDL_Surface *screen, const Vector &offset) { void BattleState::RenderHeroTags(SDL_Surface *screen, const Vector &offset) { int tagHeight(attackTypeMenu.Height()); int tagWidth(attackTypeMenu.Width() * 2 + attackTypeMenu.Width() / 2); - int xOffset((BackgroundWidth() - 2 * tagWidth) / 2); - Point tagPosition[4]; - tagPosition[0] = Point(xOffset, BackgroundHeight() - 2 * tagHeight); - tagPosition[1] = Point(xOffset + tagWidth, BackgroundHeight() - 2 * tagHeight); - tagPosition[2] = Point(xOffset, BackgroundHeight() - tagHeight); - tagPosition[3] = Point(xOffset + tagWidth, BackgroundHeight() - tagHeight); - - for (vector::size_type i(0), end(heroTags.size()); i < end; ++i) { - heroTags[i].Render(screen, tagWidth, tagHeight, tagPosition[i] + offset, (int)i == activeHero); + for (vector::size_type i(0), end(heroes.size()); i < end; ++i) { + heroTags[i].Render(screen, tagWidth, tagHeight, heroTagPositions[i] + offset, (int)i == activeHero); } } diff --git a/src/battle/BattleState.h b/src/battle/BattleState.h index 96a7ce2..3b29354 100644 --- a/src/battle/BattleState.h +++ b/src/battle/BattleState.h @@ -79,9 +79,17 @@ public: void PreviousHero() { --activeHero; } Hero &ActiveHero() { return heroes[activeHero]; } const Hero &ActiveHero() const { return heroes[activeHero]; } + Hero &HeroAt(std::vector::size_type index) { return heroes[index]; } + const Hero &HeroAt(std::vector::size_type index) const { return heroes[index]; } + const HeroTag &ActiveHeroTag() const { return heroTags[activeHero]; } + const HeroTag &HeroTagAt(std::vector::size_type index) const { return heroTags[index]; } + const geometry::Point &HeroTagPositionAt(std::vector::size_type index) const { return heroTagPositions[index]; } bool HasChosenAttackType() const { return attackChoices[activeHero].GetType() != AttackChoice::UNDECIDED; } void SetAttackType(AttackChoice::Type t) { attackChoices[activeHero].SetType(t); } + TargetSelection &ActiveHeroTargets() { return attackChoices[activeHero].Selection(); } + const TargetSelection &ActiveHeroTargets() const { return attackChoices[activeHero].Selection(); } bool AttackSelectionDone() const { return activeHero >= (int) heroes.size(); } + graphics::Menu &GetSpellMenu() { return spellMenus[activeHero]; } const graphics::Menu &GetSpellMenu() const { return spellMenus[activeHero]; } graphics::Menu &GetIkariMenu() { return ikariMenus[activeHero]; } @@ -89,6 +97,13 @@ public: graphics::Menu &GetItemMenu() { return itemMenu; } const graphics::Menu &GetItemMenu() const { return itemMenu; } + const std::vector > &MonsterPositions() const { return monsterPositions; } + bool MonsterPositionOccupied(int index) { return index >= 0 && index < int(monsters.size()) && monsters[index].Health() > 0; } + const std::vector > &HeroesPositions() const { return heroesPositions; } + bool HeroPositionOccupied(int index) { return index >= 0 && index < int(heroes.size()); } + std::vector &Heroes() { return heroes; } + const std::vector &Heroes() const { return heroes; } + public: geometry::Vector CalculateScreenOffset(SDL_Surface *screen) const { return geometry::Vector( @@ -113,6 +128,7 @@ private: const Resources *res; AttackTypeMenu attackTypeMenu; MoveMenu moveMenu; + // TODO: combine all data about heros or monsters std::vector > monsterPositions; std::vector > heroesPositions; std::vector monsters; @@ -120,8 +136,9 @@ private: std::vector > spellMenus; graphics::Menu itemMenu; std::vector > ikariMenus; - std::vector heroTags; - std::vector attackChoices; + HeroTag heroTags[4]; + geometry::Point heroTagPositions[4]; + AttackChoice attackChoices[4]; int activeHero; }; diff --git a/src/battle/HeroTag.cpp b/src/battle/HeroTag.cpp index 96dedd9..a83ba8b 100644 --- a/src/battle/HeroTag.cpp +++ b/src/battle/HeroTag.cpp @@ -30,8 +30,6 @@ void HeroTag::Render(SDL_Surface *screen, int width, int height, Point posi Vector alignOffset(align == LEFT ? 4 * res->heroTagFont->CharWidth() : 0, 0); frame->Draw(screen, position, width, height); - int yOffset((height - hero->Sprite()->Height()) / 2); - // gauges // NOTE: assuming frame border is unit size until charsets are impemented int gaugeX((align == LEFT ? 10 : 6) * res->heroTagFont->CharWidth()); @@ -86,10 +84,13 @@ void HeroTag::Render(SDL_Surface *screen, int width, int height, Point posi } // hero - Vector heroOffset( - (align == LEFT) ? yOffset : width - hero->Sprite()->Width() - yOffset, - yOffset); - hero->Sprite()->Draw(screen, position + heroOffset, 0, hero->Health() > 0 ? 0 : 2); + hero->Sprite()->Draw(screen, position + HeroOffset(), 0, hero->Health() > 0 ? 0 : 2); +} + +Vector HeroTag::HeroOffset() const { + return Vector( + (align == LEFT) ? res->normalFont->CharWidth() : 10 * res->normalFont->CharWidth(), + res->normalFont->CharWidth()); } } diff --git a/src/battle/HeroTag.h b/src/battle/HeroTag.h index d361252..5f122cf 100644 --- a/src/battle/HeroTag.h +++ b/src/battle/HeroTag.h @@ -8,7 +8,9 @@ #ifndef BATTLE_HEROTAG_H_ #define BATTLE_HEROTAG_H_ +#include "Hero.h" #include "../geometry/Point.h" +#include "../geometry/Vector.h" #include @@ -22,7 +24,6 @@ namespace graphics { namespace battle { class AttackChoice; -class Hero; struct Resources; class HeroTag { @@ -34,11 +35,15 @@ public: }; 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() { } public: + const graphics::Sprite *HeroSprite() const { return hero->Sprite(); } + geometry::Vector HeroOffset() const; + void Render(SDL_Surface *screen, int width, int height, geometry::Point position, bool active) const; private: diff --git a/src/battle/Monster.h b/src/battle/Monster.h index 1c92184..d3a7162 100644 --- a/src/battle/Monster.h +++ b/src/battle/Monster.h @@ -52,6 +52,8 @@ public: // temporary setters until loader is implemented public: void SetSprite(graphics::Sprite *s) { sprite = s; } + void SetMaxHealth(Uint16 m) { maxHealth = m; } + void SetHealth(Uint16 h) { health = h; } private: const char *name; diff --git a/src/battle/Resources.h b/src/battle/Resources.h index b07e2b2..c0fb48c 100644 --- a/src/battle/Resources.h +++ b/src/battle/Resources.h @@ -45,6 +45,9 @@ struct Resources { graphics::Font *disabledFont; graphics::Sprite *menuCursor; + graphics::Sprite *weaponTargetCursor; + graphics::Sprite *magicTargetCursor; + graphics::Sprite *itemTargetCursor; const char *spellMenuHeadline; graphics::Menu spellMenuPrototype; @@ -78,6 +81,10 @@ struct Resources { , disabledFont(0) , menuCursor(0) + , weaponTargetCursor(0) + , magicTargetCursor(0) + , itemTargetCursor(0) + , spellMenuHeadline("") , inventory(0) , itemMenuHeadline("") diff --git a/src/battle/TargetSelection.cpp b/src/battle/TargetSelection.cpp new file mode 100644 index 0000000..8563907 --- /dev/null +++ b/src/battle/TargetSelection.cpp @@ -0,0 +1,97 @@ +/* + * TargetSelection.cpp + * + * Created on: Aug 9, 2012 + * Author: holy + */ + +#include "TargetSelection.h" + +#include "BattleState.h" + +namespace battle { + +TargetSelection::TargetSelection(BattleState *battle, bool multiple, bool atEnemy) +: battle(battle) +, selected(battle ? (battle->MonsterPositions().size() > battle->Heroes().size() ? battle->MonsterPositions().size() : battle->Heroes().size()) : 0, false) +, selection(-1) +, cursor(0) +, multiple(multiple) +, enemy(atEnemy) { + if (battle && enemy) { + FindNextEnemy(); + } +} + +void TargetSelection::SelectEnemies() { + if (TargetsEnemies()) return; + enemy = true; + UnselectAll(); + cursor = 0; + FindNextEnemy(); +} + +void TargetSelection::SelectHeroes() { + if (TargetsHeroes()) return; + enemy = false; + UnselectAll(); + cursor = 0; +} + + +void TargetSelection::Reset() { + UnselectAll(); + cursor = 0; + if (TargetsEnemies()) { + FindNextEnemy(); + } +} + + +void TargetSelection::MoveUp() { + if (TargetsEnemies()) return; + if (cursor < 2) { + SelectEnemies(); + } else { + cursor -= 2; + } +} + +void TargetSelection::MoveRight() { + if (TargetsEnemies()) { + cursor = (cursor + 1) % battle->MonsterPositions().size(); + while (!battle->MonsterPositionOccupied(cursor)) { + cursor = (cursor + 1) % battle->MonsterPositions().size(); + } + } else { + cursor = (cursor + 1) % battle->Heroes().size(); + } +} + +void TargetSelection::MoveDown() { + if (TargetsEnemies()) { + SelectHeroes(); + return; + } + int newCursor(cursor + 2 % 4); + if (newCursor < int(battle->Heroes().size())) { + cursor = newCursor; + } +} + +void TargetSelection::MoveLeft() { + if (TargetsEnemies()) { + cursor = (cursor + battle->MonsterPositions().size() - 1) % battle->MonsterPositions().size(); + FindNextEnemy(); + } else { + cursor = (cursor + battle->Heroes().size() - 1) % battle->Heroes().size(); + } +} + +void TargetSelection::FindNextEnemy() { + while (!battle->MonsterPositionOccupied(cursor)) { + cursor = (cursor + battle->MonsterPositions().size() - 1) % battle->MonsterPositions().size(); + } +} + +} diff --git a/src/battle/TargetSelection.h b/src/battle/TargetSelection.h new file mode 100644 index 0000000..664e960 --- /dev/null +++ b/src/battle/TargetSelection.h @@ -0,0 +1,67 @@ +/* + * TargetSelection.h + * + * Created on: Aug 9, 2012 + * Author: holy + */ + +#ifndef BATTLE_TARGETSELECTION_H_ +#define BATTLE_TARGETSELECTION_H_ + +#include + +namespace battle { + +class BattleState; + +class TargetSelection { + +public: + explicit TargetSelection(BattleState *battle = 0, bool multiple = false, bool atEnemy = true); + +public: + bool TargetsEnemies() const { return enemy; } + bool TargetsHeroes() const { return !TargetsEnemies(); } + bool IsSelected(int index) const { return index >= 0 && index < int(selected.size()) && selected[index]; } + bool HasSelected() const { return selection >= 0; } + int SingleSelection() const { return selection; } + + bool SelectMultiple() const { return multiple; } + void SetMultiple() { multiple = true; } + bool SelectSingle() const { return !SelectMultiple(); } + void SetSingle() { multiple = false; } + + void SelectEnemies(); + void SelectHeroes(); + void Select(int index) { selected[index] = true; selection = index; } + void Unselect(int index) { selected[index] = false; } + void UnselectAll() { selected.assign(selected.size(), false); selection = -1; } + + void Reset(); + void Resize(int num) { selected.resize(num, false); } + + void MoveUp(); + void MoveRight(); + void MoveDown(); + void MoveLeft(); + void Select() { Select(cursor); } + void Unselect() { Unselect(cursor); } + int Current() const { return cursor; } + bool CurrentIsSelected() { return IsSelected(cursor); } + +private: + void FindNextEnemy(); + +private: + BattleState *battle; + std::vector selected; + int selection; + int cursor; + bool multiple; + bool enemy; + +}; + +} + +#endif /* BATTLE_TARGETSELECTION_H_ */ diff --git a/src/battle/states/SelectAttackType.cpp b/src/battle/states/SelectAttackType.cpp index 786277d..c007320 100644 --- a/src/battle/states/SelectAttackType.cpp +++ b/src/battle/states/SelectAttackType.cpp @@ -11,6 +11,7 @@ #include "SelectItem.h" #include "SelectMoveAction.h" #include "SelectSpell.h" +#include "SelectTarget.h" #include "../AttackChoice.h" #include "../BattleState.h" #include "../../app/Application.h" @@ -35,6 +36,10 @@ void SelectAttackType::ExitState(Application &c, SDL_Surface *screen) { } void SelectAttackType::ResumeState(Application &ctrl, SDL_Surface *screen) { + if (battle->ActiveHeroTargets().HasSelected()) { + battle->SetAttackType(battle->GetAttackTypeMenu().Selected()); + battle->NextHero(); + } if (battle->AttackSelectionDone()) { // pass through ctrl.PopState(); @@ -67,9 +72,10 @@ void SelectAttackType::HandleInput(const Input &input) { if (input.JustPressed(Input::ACTION_A)) { switch (battle->GetAttackTypeMenu().Selected()) { case AttackChoice::SWORD: - // TODO: switch to target select - battle->SetAttackType(AttackChoice::SWORD); - battle->NextHero(); + // TODO: detect single/multiple/all attack mode + battle->ActiveHeroTargets().SetSingle(); + battle->ActiveHeroTargets().Reset(); + ctrl->PushState(new SelectTarget(battle, this, &battle->ActiveHeroTargets(), battle->Res().weaponTargetCursor, true)); break; case AttackChoice::MAGIC: if (battle->ActiveHero().CanUseMagic()) { @@ -90,8 +96,8 @@ void SelectAttackType::HandleInput(const Input &input) { throw std::logic_error("selected invalid attack type"); } } else if (input.JustPressed(Input::ACTION_B)) { - battle->SetAttackType(AttackChoice::UNDECIDED); battle->PreviousHero(); + battle->SetAttackType(AttackChoice::UNDECIDED); if (battle->BeforeFirstHero()) { ctrl->ChangeState(new SelectMoveAction(battle)); } diff --git a/src/battle/states/SelectTarget.cpp b/src/battle/states/SelectTarget.cpp new file mode 100644 index 0000000..dedf8e7 --- /dev/null +++ b/src/battle/states/SelectTarget.cpp @@ -0,0 +1,117 @@ +/* + * SelectTarget.cpp + * + * Created on: Aug 9, 2012 + * Author: holy + */ + +#include "SelectTarget.h" + +#include "SelectAttackType.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 SelectTarget::EnterState(Application &c, SDL_Surface *screen) { + ctrl = &c; +} + +void SelectTarget::ExitState(Application &c, SDL_Surface *screen) { + ctrl = 0; +} + +void SelectTarget::ResumeState(Application &ctrl, SDL_Surface *screen) { + +} + +void SelectTarget::PauseState(Application &ctrl, SDL_Surface *screen) { + +} + + +void SelectTarget::Resize(int width, int height) { + +} + + +void SelectTarget::HandleInput(const Input &input) { + if (input.JustPressed(Input::ACTION_A)) { + if (selection->CurrentIsSelected()) { + ctrl->PopState(); // return control to parent + } else { + selection->Select(); + if (selection->SelectSingle()) { + ctrl->PopState(); // return control to parent + } + } + } + if (input.JustPressed(Input::ACTION_B)) { + if (selection->CurrentIsSelected()) { + selection->Unselect(); + } else { + selection->UnselectAll(); + ctrl->PopState(); // return control to parent + } + } + + if (input.JustPressed(Input::PAD_UP)) { + selection->MoveUp(); + } + if (input.JustPressed(Input::PAD_RIGHT)) { + selection->MoveRight(); + } + if (input.JustPressed(Input::PAD_DOWN)) { + selection->MoveDown(); + } + if (input.JustPressed(Input::PAD_LEFT)) { + selection->MoveLeft(); + } +} + +void SelectTarget::UpdateWorld(float deltaT) { + +} + +void SelectTarget::Render(SDL_Surface *screen) { + Vector offset(battle->CalculateScreenOffset(screen)); + parent->Render(screen); + RenderCursors(screen, offset); +} + +void SelectTarget::RenderCursors(SDL_Surface *screen, const geometry::Vector &offset) { + // TODO: this should be related to the enemy's width + Vector cursorOffset(0, 0); + Vector indicatorOffset(0, 0); + vector > positions; + if (selection->TargetsEnemies()) { + for (vector >::const_iterator i(battle->MonsterPositions().begin()), end(battle->MonsterPositions().end()); i != end; ++i) { + positions.push_back(*i); + } + } else { + for (vector::size_type i(0), end(battle->Heroes().size()); i < end; ++i) { + Vector positionCorrection(cursorIcon->Width() / 2, battle->HeroTagAt(i).HeroSprite()->Height() - cursorIcon->Height() / 2); + positions.push_back(battle->HeroTagPositionAt(i) + battle->HeroTagAt(i).HeroOffset() + positionCorrection); + } + } + if (flipFlop) { + for (vector >::size_type i(0); i < positions.size(); ++i) { + if (selection->IsSelected(i)) { + cursorIcon->DrawTopRight(screen, positions[i] + offset); + } + } + } + flipFlop = !flipFlop; + cursorIcon->DrawTopRight(screen, positions[selection->Current()] + offset + cursorOffset); +} + +} diff --git a/src/battle/states/SelectTarget.h b/src/battle/states/SelectTarget.h new file mode 100644 index 0000000..b9085a5 --- /dev/null +++ b/src/battle/states/SelectTarget.h @@ -0,0 +1,57 @@ +/* + * SelectTarget.h + * + * Created on: Aug 9, 2012 + * Author: holy + */ + +#ifndef BATTLE_SELECTTARGET_H_ +#define BATTLE_SELECTTARGET_H_ + +#include "../../app/State.h" + +#include "../../geometry/Vector.h" + +namespace graphics { class Sprite; } + +namespace battle { + +class BattleState; +class TargetSelection; +class SelectAttackType; + +class SelectTarget +: public app::State { + +public: + SelectTarget(BattleState *battle, SelectAttackType *parent, TargetSelection *selection, const graphics::Sprite *cursorIcon, bool startWithEnemy) + : ctrl(0), battle(battle), parent(parent), selection(selection), cursorIcon(cursorIcon), 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 RenderCursors(SDL_Surface *screen, const geometry::Vector &offset); + +private: + app::Application *ctrl; + BattleState *battle; + SelectAttackType *parent; + TargetSelection *selection; + const graphics::Sprite *cursorIcon; + bool flipFlop; + +}; + +} + +#endif /* BATTLE_SELECTTARGET_H_ */ diff --git a/src/graphics/Sprite.h b/src/graphics/Sprite.h index 4a99af4..d56c691 100644 --- a/src/graphics/Sprite.h +++ b/src/graphics/Sprite.h @@ -26,6 +26,10 @@ public: int Width() const { return width; } int Height() const { return height; } void Draw(SDL_Surface *dest, geometry::Point position, int col = 0, int row = 0) const; + void DrawTopRight(SDL_Surface *dest, geometry::Point position, int col = 0, int row = 0) const { + geometry::Vector offset(-Width(), 0); + Draw(dest, position + offset, col, row); + } void DrawCenter(SDL_Surface *dest, geometry::Point position, int col = 0, int row = 0) const { geometry::Vector offset(-Width() / 2, -Height() / 2); Draw(dest, position + offset, col, row); diff --git a/src/main.cpp b/src/main.cpp index dbe50d2..5e14001 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -78,6 +78,8 @@ int main(int argc, char **argv) { Sprite dummySprite(monsterImg, 64, 64); Monster monster; monster.SetSprite(&dummySprite); + monster.SetMaxHealth(10); + monster.SetHealth(10); SDL_Surface *maximImg(IMG_Load("test-data/maxim.png")); Sprite maximSprite(maximImg, 64, 64); @@ -193,6 +195,14 @@ int main(int argc, char **argv) { Sprite handCursorSprite(handCursorImg, 32, 32); battleRes.menuCursor = &handCursorSprite; + SDL_Surface *targetingIconsImg(IMG_Load("test-data/targeting-icons.png")); + Sprite weaponTargetCursor(targetingIconsImg, 32, 32); + battleRes.weaponTargetCursor = &weaponTargetCursor; + // TODO: add image for magic targeting cursor + battleRes.magicTargetCursor = &weaponTargetCursor; + // TODO: add image for item targeting cursor + battleRes.itemTargetCursor = &weaponTargetCursor; + battleRes.spellMenuHeadline = "Please choose a spell."; battleRes.spellMenuPrototype = Menu(&normalFont, &disabledFont, &handCursorSprite, 12, 6, 8, 0, 2, 32); battleRes.spellMenuPrototype.Add("Reset : 0", 0, false); diff --git a/test-data/targeting-icons.png b/test-data/targeting-icons.png new file mode 100644 index 0000000000000000000000000000000000000000..64b32bf9f98a043edfd6c7a16f084938b3329b38 GIT binary patch literal 414 zcmV;P0b%}$P)A2#^^nXBQF%GkgVBNl+M)VitnJ){v~IR)Q-DVs*@I z4#e#UYYxV4OSp38Qt@l@{=GYk6|GWv<6UQNjXz%2su0(<_W^8{Ny3$1woyBOd_o(9=TvU8>AWfpmM2HpIzk5^lWuDv#O9v`UL_T2aK!Fp zq8HYuOr(98j+Qdl#k&=My8cXP>h9D4xVZF{1F|QoZe8rn+ke8q__`+=?m3xZqJ1|~ z=3Dke98IQY$54w2bDA*Eg!F(!md|(oWmH@b%zN|cA}b67A6=BDxZ?ItE&u=k07*qo IM6N<$f*EJLP5=M^ literal 0 HcmV?d00001 -- 2.39.2