From aedc31b88715246abc00a0ab333bea6e17bbb780 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Sun, 12 Aug 2012 21:14:13 +0200 Subject: [PATCH] added number animation --- Debug/src/battle/subdir.mk | 3 + Release/src/battle/subdir.mk | 3 + src/battle/NumberAnimation.cpp | 115 +++++++++++++++++++++++++++ src/battle/NumberAnimation.h | 46 +++++++++++ src/battle/states/PerformAttacks.cpp | 86 +++++++++++++++----- src/battle/states/PerformAttacks.h | 14 +++- src/graphics/Animation.h | 3 + 7 files changed, 250 insertions(+), 20 deletions(-) create mode 100644 src/battle/NumberAnimation.cpp create mode 100644 src/battle/NumberAnimation.h diff --git a/Debug/src/battle/subdir.mk b/Debug/src/battle/subdir.mk index 20dd9c3..df33d4e 100644 --- a/Debug/src/battle/subdir.mk +++ b/Debug/src/battle/subdir.mk @@ -11,6 +11,7 @@ CPP_SRCS += \ ../src/battle/HeroTag.cpp \ ../src/battle/Monster.cpp \ ../src/battle/MoveMenu.cpp \ +../src/battle/NumberAnimation.cpp \ ../src/battle/PartyLayout.cpp \ ../src/battle/SmallHeroTag.cpp \ ../src/battle/TargetSelection.cpp @@ -23,6 +24,7 @@ OBJS += \ ./src/battle/HeroTag.o \ ./src/battle/Monster.o \ ./src/battle/MoveMenu.o \ +./src/battle/NumberAnimation.o \ ./src/battle/PartyLayout.o \ ./src/battle/SmallHeroTag.o \ ./src/battle/TargetSelection.o @@ -35,6 +37,7 @@ CPP_DEPS += \ ./src/battle/HeroTag.d \ ./src/battle/Monster.d \ ./src/battle/MoveMenu.d \ +./src/battle/NumberAnimation.d \ ./src/battle/PartyLayout.d \ ./src/battle/SmallHeroTag.d \ ./src/battle/TargetSelection.d diff --git a/Release/src/battle/subdir.mk b/Release/src/battle/subdir.mk index d25e980..776e860 100644 --- a/Release/src/battle/subdir.mk +++ b/Release/src/battle/subdir.mk @@ -11,6 +11,7 @@ CPP_SRCS += \ ../src/battle/HeroTag.cpp \ ../src/battle/Monster.cpp \ ../src/battle/MoveMenu.cpp \ +../src/battle/NumberAnimation.cpp \ ../src/battle/PartyLayout.cpp \ ../src/battle/SmallHeroTag.cpp \ ../src/battle/TargetSelection.cpp @@ -23,6 +24,7 @@ OBJS += \ ./src/battle/HeroTag.o \ ./src/battle/Monster.o \ ./src/battle/MoveMenu.o \ +./src/battle/NumberAnimation.o \ ./src/battle/PartyLayout.o \ ./src/battle/SmallHeroTag.o \ ./src/battle/TargetSelection.o @@ -35,6 +37,7 @@ CPP_DEPS += \ ./src/battle/HeroTag.d \ ./src/battle/Monster.d \ ./src/battle/MoveMenu.d \ +./src/battle/NumberAnimation.d \ ./src/battle/PartyLayout.d \ ./src/battle/SmallHeroTag.d \ ./src/battle/TargetSelection.d diff --git a/src/battle/NumberAnimation.cpp b/src/battle/NumberAnimation.cpp new file mode 100644 index 0000000..7002f57 --- /dev/null +++ b/src/battle/NumberAnimation.cpp @@ -0,0 +1,115 @@ +/* + * NumberAnimation.cpp + * + * Created on: Aug 12, 2012 + * Author: holy + */ + +#include "NumberAnimation.h" + +#include "../geometry/operators.h" +#include "../geometry/Vector.h" + +using app::State; +using geometry::Point; +using geometry::Vector; +using graphics::ComplexAnimation; +using graphics::Sprite; + +namespace battle { + +NumberAnimation::NumberAnimation(int number, const ComplexAnimation &a, const Sprite *numbers) +: number(number) { + animation[0] = a; + animation[1] = a; + animation[2] = a; + animation[3] = a; + + animation[0].ChangeSprite(numbers); + animation[1].ChangeSprite(numbers); + animation[2].ChangeSprite(numbers); + animation[3].ChangeSprite(numbers); + + if (number > 9999) { + animation[0].SetColOffset(9); + animation[1].SetColOffset(9); + animation[2].SetColOffset(9); + animation[3].SetColOffset(9); + } else { + animation[0].SetColOffset(number / 1000 % 10); + animation[1].SetColOffset(number / 100 % 10); + animation[2].SetColOffset(number / 10 % 10); + animation[3].SetColOffset(number % 10); + } +} + +void NumberAnimation::Start(State &s) { + if (number > 999) { + animation[0].Start(s); + } else if (number > 99) { + animation[1].Start(s); + } else if (number > 9) { + animation[2].Start(s); + } else { + animation[3].Start(s); + } +} + +bool NumberAnimation::Running() const { + return animation[0].Running() || animation[1].Running() || animation[2].Running() || animation[3].Running(); +} + +void NumberAnimation::CheckTimers(State &s) { + if (animation[0].Running() && animation[0].Frame() == 1) { + animation[1].Start(s); + } else if (animation[1].Running() && animation[1].Frame() == 1) { + animation[2].Start(s); + } else if (animation[2].Running() && animation[2].Frame() == 1) { + animation[3].Start(s); + } +} + + +int NumberAnimation::Width() const { + if (number < 10) { + return animation[0].GetSprite()->Width(); + } else if (number < 100) { + return 2 * animation[0].GetSprite()->Width(); + } else if (number < 1000) { + return 3 * animation[0].GetSprite()->Width(); + } else { + return 4 * animation[0].GetSprite()->Width(); + } +} + +int NumberAnimation::Height() const { + return animation[0].GetSprite()->Height(); +} + +void NumberAnimation::Draw(SDL_Surface *dest, const Point &positionIn) const { + Point position(positionIn); + Vector step(animation[0].GetSprite()->Width(), 0); + if (number > 999) { + if (animation[0].Running()) { + animation[0].Draw(dest, position); + } + position += step; + } + if (number > 99) { + if (animation[1].Running() || animation[0].Running()) { + animation[1].Draw(dest, position); + } + position += step; + } + if (number > 9) { + if (animation[2].Running() || animation[1].Running() || animation[0].Running()) { + animation[2].Draw(dest, position); + } + position += step; + } + if (animation[3].Running() || animation[2].Running() || animation[1].Running() || animation[0].Running()) { + animation[3].Draw(dest, position); + } +} + +} diff --git a/src/battle/NumberAnimation.h b/src/battle/NumberAnimation.h new file mode 100644 index 0000000..2c96b5e --- /dev/null +++ b/src/battle/NumberAnimation.h @@ -0,0 +1,46 @@ +/* + * NumberAnimation.h + * + * Created on: Aug 12, 2012 + * Author: holy + */ + +#ifndef BATTLE_NUMBERANIMATION_H_ +#define BATTLE_NUMBERANIMATION_H_ + +#include "../graphics/ComplexAnimation.h" + +#include "../geometry/Point.h" + +namespace app { + class Application; + class State; +} + +namespace battle { + +class NumberAnimation { + +public: + NumberAnimation() : number(-1) { } + NumberAnimation(int number, const graphics::ComplexAnimation &prototype, const graphics::Sprite *numbers); + +public: + void Start(app::State &); + bool Running() const; + void CheckTimers(app::State &); + + int Width() const; + int Height() const; + + void Draw(SDL_Surface *dest, const geometry::Point &position) const; + +private: + int number; + graphics::ComplexAnimation animation[4]; + +}; + +} + +#endif /* BATTLE_NUMBERANIMATION_H_ */ diff --git a/src/battle/states/PerformAttacks.cpp b/src/battle/states/PerformAttacks.cpp index 4f7a427..b5cd9be 100644 --- a/src/battle/states/PerformAttacks.cpp +++ b/src/battle/states/PerformAttacks.cpp @@ -27,12 +27,15 @@ using app::Application; using app::Input; using geometry::Point; using geometry::Vector; +using std::vector; namespace battle { void PerformAttacks::EnterState(Application &c, SDL_Surface *screen) { ctrl = &c; battle->WriteOrder(order); + numberAnimation.reserve(battle->MaxMonsters() > battle->NumHeroes() + 1 ? battle->MaxMonsters() : battle->NumHeroes() + 1); + numberPosition.reserve(numberAnimation.size()); } void PerformAttacks::ExitState(Application &c, SDL_Surface *screen) { @@ -54,23 +57,11 @@ void PerformAttacks::Resize(int width, int height) { void PerformAttacks::HandleEvents(const Input &input) { - if (titleBarTimer.Running() || (moveAnimation && moveAnimation->Running())) return; - - if (moveAnimation) moveAnimation->Stop(); - titleBarTimer.Clear(); - - ++cursor; - - while (cursor < int(order.size())) { - if (order[cursor].isMonster) { - if (battle->MonsterAt(order[cursor].index).Health() > 0) break; - } else { - if (battle->HeroAt(order[cursor].index).Health() > 0) break; - } - ++cursor; - } - - if (cursor >= int(order.size())) { + CheckNumberAnimation(); + if (HasAnimationsRunning()) return; + ResetAnimation(); + AdvanceCursor(); + if (Finished()) { battle->ClearAllAttacks(); ctrl->PopState(); return; @@ -88,6 +79,14 @@ void PerformAttacks::HandleEvents(const Input &input) { case AttackChoice::SWORD: titleBarText = hero.HasWeapon() ? hero.Weapon()->Name() : "Melee attack!"; moveAnimation = hero.AttackAnimation(); + numberAnimation.push_back(NumberAnimation(15, battle->Res().numberAnimationPrototype, battle->Res().bigNumberSprite)); + if (ac.Selection().TargetsEnemies()) { + numberPosition.push_back( + battle->MonsterPositions()[ac.Selection().SingleSelection()]); + } else { + numberPosition.push_back( + battle->HeroesPositions()[ac.Selection().SingleSelection()]); + } break; case AttackChoice::MAGIC: titleBarText = ac.GetSpell()->Name(); @@ -118,10 +117,51 @@ void PerformAttacks::HandleEvents(const Input &input) { } } - titleBarTimer = GraphicsTimers().StartCountdown(1500); + if (titleBarText) titleBarTimer = GraphicsTimers().StartCountdown(1500); if (moveAnimation) moveAnimation->Start(*this); } +void PerformAttacks::CheckNumberAnimation() { + if (moveAnimation && moveAnimation->Running()) return; + if (!moveAnimation || moveAnimation->JustFinished()) { + for (vector::iterator i(numberAnimation.begin()), end(numberAnimation.end()); i != end; ++i) { + i->Start(*this); + } + } else { + for (vector::iterator i(numberAnimation.begin()), end(numberAnimation.end()); i != end; ++i) { + i->CheckTimers(*this); + } + } +} + +bool PerformAttacks::HasAnimationsRunning() const { + if (titleBarTimer.Running()) return true; + if (moveAnimation && moveAnimation->Running()) return true; + for (vector::const_iterator i(numberAnimation.begin()), end(numberAnimation.end()); i != end; ++i) { + if (i->Running()) return true; + } + return false; +} + +void PerformAttacks::ResetAnimation() { + if (moveAnimation) moveAnimation->Stop(); + titleBarTimer.Clear(); + numberAnimation.clear(); + numberPosition.clear(); +} + +void PerformAttacks::AdvanceCursor() { + ++cursor; + while (cursor < int(order.size())) { + if (order[cursor].isMonster) { + if (battle->MonsterAt(order[cursor].index).Health() > 0) break; + } else { + if (battle->HeroAt(order[cursor].index).Health() > 0) break; + } + ++cursor; + } +} + void PerformAttacks::UpdateWorld(float deltaT) { @@ -134,6 +174,7 @@ void PerformAttacks::Render(SDL_Surface *screen) { battle->RenderHeroes(screen, offset); battle->RenderSmallHeroTags(screen, offset); RenderTitleBar(screen, offset); + RenderNumbers(screen, offset); } void PerformAttacks::RenderTitleBar(SDL_Surface *screen, const Vector &offset) { @@ -148,4 +189,13 @@ void PerformAttacks::RenderTitleBar(SDL_Surface *screen, const Vector &offs battle->Res().titleFont->DrawString(titleBarText, screen, textPosition + offset); } +void PerformAttacks::RenderNumbers(SDL_Surface *screen, const Vector &offset) { + for (vector::size_type i(0), end(numberAnimation.size()); i < end; ++i) { + if (numberAnimation[i].Running()) { + Vector align(numberAnimation[i].Width() / -2, numberAnimation[i].Height() * -3 / 4); + numberAnimation[i].Draw(screen, numberPosition[i] + align + offset); + } + } +} + } diff --git a/src/battle/states/PerformAttacks.h b/src/battle/states/PerformAttacks.h index e0d3df8..a5f3247 100644 --- a/src/battle/states/PerformAttacks.h +++ b/src/battle/states/PerformAttacks.h @@ -11,12 +11,12 @@ #include "../../app/State.h" #include "../BattleState.h" +#include "../NumberAnimation.h" #include "../../geometry/Vector.h" +#include "../../graphics/ComplexAnimation.h" #include -namespace graphics { class Animation; } - namespace battle { class PerformAttacks @@ -38,8 +38,16 @@ public: virtual void UpdateWorld(float deltaT); virtual void Render(SDL_Surface *); +private: + void CheckNumberAnimation(); + bool HasAnimationsRunning() const; + void ResetAnimation(); + void AdvanceCursor(); + bool Finished() const { return cursor >= int(order.size()); } + private: void RenderTitleBar(SDL_Surface *screen, const geometry::Vector &offset); + void RenderNumbers(SDL_Surface *screen, const geometry::Vector &offset); private: app::Application *ctrl; @@ -48,6 +56,8 @@ private: const char *titleBarText; app::Timer titleBarTimer; std::vector order; + std::vector numberAnimation; + std::vector > numberPosition; int cursor; }; diff --git a/src/graphics/Animation.h b/src/graphics/Animation.h index 524912d..0c6ae28 100644 --- a/src/graphics/Animation.h +++ b/src/graphics/Animation.h @@ -42,6 +42,9 @@ public: bool Running() const { return timer.Running() && (repeat || timer.Iteration() < NumFrames()); } + bool JustFinished() const { + return timer.JustHit() && timer.Iteration() == NumFrames(); + } const app::Timer &GetTimer() { return timer; } -- 2.39.2