瀏覽代碼

Cleaned up BattleHero class

Ivan Savenko 2 年之前
父節點
當前提交
e7206cb759

+ 0 - 1
client/battle/BattleAnimationClasses.cpp

@@ -93,7 +93,6 @@ BattleStackAnimation::BattleStackAnimation(BattleInterface & owner, const CStack
 
 void AttackAnimation::nextFrame()
 {
-	assert(myAnim->getType() == group);
 	if(myAnim->getType() != group)
 	{
 		myAnim->setType(group);

+ 6 - 0
client/battle/BattleAnimationClasses.h

@@ -328,6 +328,12 @@ public:
 	void nextFrame() override;
 };
 
+class HeroAnimation : public BattleAnimation
+{
+public:
+	HeroAnimation(BattleInterface * owner_, const CStack * shooter);
+};
+
 /// Class that waits till projectile of certain shooter hits a target
 class WaitingProjectileAnimation : public BattleAnimation
 {

+ 1 - 4
client/battle/BattleConstants.h

@@ -43,9 +43,7 @@ namespace EBattleEffect
 	};
 }
 
-namespace EHeroAnimType
-{
-enum Type
+enum class EHeroAnimType
 {
 	HOLDING    = 0,
 	IDLE       = 1, // idling movement that happens from time to time
@@ -53,7 +51,6 @@ enum Type
 	VICTORY    = 3, // when enemy stack killed or huge damage is dealt
 	CAST_SPELL = 4  // spellcasting
 };
-}
 
 namespace ECreatureAnimType
 {

+ 1 - 1
client/battle/BattleControlPanel.cpp

@@ -39,7 +39,7 @@ BattleControlPanel::BattleControlPanel(BattleInterface & owner, const Point & po
 	bOptions = std::make_shared<CButton>    (Point(  3,  5), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&BattleControlPanel::bOptionsf,this), SDLK_o);
 	bSurrender = std::make_shared<CButton>  (Point( 54,  5), "icm001.def", CGI->generaltexth->zelp[379], std::bind(&BattleControlPanel::bSurrenderf,this), SDLK_s);
 	bFlee = std::make_shared<CButton>       (Point(105,  5), "icm002.def", CGI->generaltexth->zelp[380], std::bind(&BattleControlPanel::bFleef,this), SDLK_r);
-	bAutofight = std::make_shared<CButton>  (Point(157,  5), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&BattleControlPanel::bAutofightf,this), SDLK_a);
+	bAutofight = std::make_shared<CButton>  (Point(158,  5), "icm004.def", CGI->generaltexth->zelp[382], std::bind(&BattleControlPanel::bAutofightf,this), SDLK_a);
 	bSpell = std::make_shared<CButton>      (Point(645,  5), "icm005.def", CGI->generaltexth->zelp[385], std::bind(&BattleControlPanel::bSpellf,this), SDLK_c);
 	bWait = std::make_shared<CButton>       (Point(696,  5), "icm006.def", CGI->generaltexth->zelp[386], std::bind(&BattleControlPanel::bWaitf,this), SDLK_w);
 	bDefence = std::make_shared<CButton>    (Point(747,  5), "icm007.def", CGI->generaltexth->zelp[387], std::bind(&BattleControlPanel::bDefencef,this), SDLK_d);

+ 1 - 13
client/battle/BattleInterface.cpp

@@ -107,7 +107,6 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
 		queue->moveTo(Point(pos.x, pos.y - queue->pos.h));
 	}
 
-
 	CPlayerInterface::battleInt = this;
 
 	//initializing armies
@@ -142,10 +141,6 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
 		}
 
 		attackingHero = std::make_shared<BattleHero>(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, *this);
-
-		auto img = attackingHero->animation->getImage(0, 0, true);
-		if(img)
-			attackingHero->pos = genRect(img->height(), img->width(), pos.x - 43, pos.y - 19);
 	}
 
 
@@ -166,10 +161,6 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
 		}
 
 		defendingHero = std::make_shared<BattleHero>(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, *this);
-
-		auto img = defendingHero->animation->getImage(0, 0, true);
-		if(img)
-			defendingHero->pos = genRect(img->height(), img->width(), pos.x + 693, pos.y - 19);
 	}
 
 	obstacleController.reset(new BattleObstacleController(*this));
@@ -588,7 +579,7 @@ void BattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)
 		fieldController->redrawBackgroundWithHexes();
 }
 
-void BattleInterface::setHeroAnimation(ui8 side, int phase)
+void BattleInterface::setHeroAnimation(ui8 side, EHeroAnimType phase)
 {
 	if(side == BattleSide::ATTACKER)
 	{
@@ -714,9 +705,6 @@ void BattleInterface::endAction(const BattleAction* action)
 {
 	const CStack *stack = curInt->cb->battleGetStackByID(action->stackNumber);
 
-	if(action->actionType == EActionType::HERO_SPELL)
-		setHeroAnimation(action->side, EHeroAnimType::HOLDING);
-
 	stacksController->endAction(action);
 
 	queue->update();

+ 1 - 1
client/battle/BattleInterface.h

@@ -138,7 +138,7 @@ private:
 
 	void showInterface(SDL_Surface * to);
 
-	void setHeroAnimation(ui8 side, int phase);
+	void setHeroAnimation(ui8 side, EHeroAnimType phase);
 
 	void executeSpellCast(); //called when a hero casts a spell
 

+ 64 - 47
client/battle/BattleInterfaceClasses.cpp

@@ -47,8 +47,8 @@
 
 void BattleConsole::showAll(SDL_Surface * to)
 {
-	Point consolePos(pos.x + 10,      pos.y + 17);
-	Point textPos   (pos.x + pos.w/2, pos.y + 17);
+	Point consolePos(pos.x + 10,      pos.y + 19);
+	Point textPos   (pos.x + pos.w/2, pos.y + 19);
 
 	if (!consoleText.empty())
 	{
@@ -160,46 +160,60 @@ void BattleConsole::clear()
 
 void BattleHero::render(Canvas & canvas)
 {
-	auto flagFrame = flagAnimation->getImage(flagAnim, 0, true);
+	size_t groupIndex = static_cast<size_t>(phase);
 
-	if(!flagFrame)
-		return;
+	auto flagFrame = flagAnimation->getImage(flagCurrentFrame, 0, true);
+	auto heroFrame = animation->getImage(currentFrame, groupIndex, true);
 
-	//animation of flag
-	Point flagPosition = pos.topLeft();
+	Point heroPosition = pos.center() - heroFrame->dimensions() / 2;
+	Point flagPosition = pos.center() - flagFrame->dimensions() / 2;
 
 	if(flip)
-		flagPosition += Point(61, 39);
+		flagPosition += Point(-4, -41);
 	else
-		flagPosition += Point(72, 39);
+		flagPosition += Point(4, -41);
 
+	canvas.draw(flagFrame, flagPosition);
+	canvas.draw(heroFrame, heroPosition);
 
-	auto heroFrame = animation->getImage(currentFrame, phase, true);
+	//FIXME: un-hardcode speed
+	flagCurrentFrame += 0.25f;
+	currentFrame += 0.25f;
 
-	canvas.draw(flagFrame, flagPosition);
-	canvas.draw(heroFrame, pos.topLeft());
+	if(flagCurrentFrame >= flagAnimation->size(0))
+		flagCurrentFrame -= flagAnimation->size(0);
 
-	if(++animCount >= 4)
+	if(currentFrame >= animation->size(groupIndex))
 	{
-		animCount = 0;
-		if(++flagAnim >= flagAnimation->size(0))
-			flagAnim = 0;
-
-		if(++currentFrame >= lastFrame)
-			switchToNextPhase();
+		currentFrame -= animation->size(groupIndex);
+		if (phaseFinishedCallback)
+		{
+			phaseFinishedCallback();
+			phaseFinishedCallback = std::function<void()>();
+		}
 	}
 }
 
-void BattleHero::setPhase(int newPhase)
+float BattleHero::getFrame() const
+{
+	return currentFrame;
+}
+
+void BattleHero::onPhaseFinished(const std::function<void()> & callback)
+{
+	phaseFinishedCallback = callback;
+}
+
+void BattleHero::setPhase(EHeroAnimType newPhase)
 {
 	nextPhase = newPhase;
 	switchToNextPhase(); //immediately switch to next phase and then restore idling phase
-	nextPhase = 0;
+	nextPhase = EHeroAnimType::HOLDING;
 }
 
 void BattleHero::hover(bool on)
 {
-	//TODO: Make lines below work properly
+	//TODO: BROKEN CODE
 	if (on)
 		CCS->curh->changeGraphic(ECursor::COMBAT, 5);
 	else
@@ -208,25 +222,25 @@ void BattleHero::hover(bool on)
 
 void BattleHero::clickLeft(tribool down, bool previousState)
 {
-	if(myOwner->actionsController->spellcastingModeActive()) //we are casting a spell
+	if(owner.actionsController->spellcastingModeActive()) //we are casting a spell
 		return;
 
 	if(boost::logic::indeterminate(down))
 		return;
 
-	if(!myHero || down || !myOwner->myTurn)
+	if(!myHero || down || !owner.myTurn)
 		return;
 
-	if(myOwner->getCurrentPlayerInterface()->cb->battleCanCastSpell(myHero, spells::Mode::HERO) == ESpellCastProblem::OK) //check conditions
+	if(owner.getCurrentPlayerInterface()->cb->battleCanCastSpell(myHero, spells::Mode::HERO) == ESpellCastProblem::OK) //check conditions
 	{
-		BattleHex hoveredHex = myOwner->fieldController->getHoveredHex();
+		BattleHex hoveredHex = owner.fieldController->getHoveredHex();
 		//do nothing when any hex is hovered - hero's animation overlaps battlefield
 		if ( hoveredHex != BattleHex::INVALID )
 			return;
 
 		CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 
-		GH.pushIntT<CSpellWindow>(myHero, myOwner->getCurrentPlayerInterface());
+		GH.pushIntT<CSpellWindow>(myHero, owner.getCurrentPlayerInterface());
 	}
 }
 
@@ -236,13 +250,13 @@ void BattleHero::clickRight(tribool down, bool previousState)
 		return;
 
 	Point windowPosition;
-	windowPosition.x = (!flip) ? myOwner->pos.topLeft().x + 1 : myOwner->pos.topRight().x - 79;
-	windowPosition.y = myOwner->pos.y + 135;
+	windowPosition.x = (!flip) ? owner.pos.topLeft().x + 1 : owner.pos.topRight().x - 79;
+	windowPosition.y = owner.pos.y + 135;
 
 	InfoAboutHero targetHero;
-	if(down && (myOwner->myTurn || settings["session"]["spectate"].Bool()))
+	if(down && (owner.myTurn || settings["session"]["spectate"].Bool()))
 	{
-		auto h = flip ? myOwner->defendingHeroInstance : myOwner->attackingHeroInstance;
+		auto h = flip ? owner.defendingHeroInstance : owner.attackingHeroInstance;
 		targetHero.initFromHero(h, InfoAboutHero::EInfoLevel::INBATTLE);
 		GH.pushIntT<HeroInfoWindow>(targetHero, &windowPosition);
 	}
@@ -250,30 +264,33 @@ void BattleHero::clickRight(tribool down, bool previousState)
 
 void BattleHero::switchToNextPhase()
 {
-	if(phase != nextPhase)
+	phase = nextPhase;
+	currentFrame = 0.f;
+	if (phaseFinishedCallback)
 	{
-		phase = nextPhase;
-
-		firstFrame = 0;
-
-		lastFrame = static_cast<int>(animation->size(phase));
+		phaseFinishedCallback();
+		phaseFinishedCallback = std::function<void()>();
 	}
-
-	currentFrame = firstFrame;
 }
 
 BattleHero::BattleHero(const std::string & animationPath, bool flipG, PlayerColor player, const CGHeroInstance * hero, const BattleInterface & owner):
-    flip(flipG),
-    myHero(hero),
-	myOwner(&owner),
-    phase(1),
-    nextPhase(0),
-    flagAnim(0),
-    animCount(0)
+	flip(flipG),
+	myHero(hero),
+	owner(owner),
+	phase(EHeroAnimType::HOLDING),
+	nextPhase(EHeroAnimType::HOLDING),
+	currentFrame(0.f),
+	flagCurrentFrame(0.f)
 {
 	animation = std::make_shared<CAnimation>(animationPath);
 	animation->preload();
-	if(flipG)
+
+	pos.w = 64;
+	pos.h = 136;
+	pos.x = owner.pos.x + (flipG ? (owner.pos.w - pos.w) : 0);
+	pos.y = owner.pos.y;
+
+	if(flip)
 		animation->verticalFlip();
 
 	if(flip)

+ 17 - 9
client/battle/BattleInterfaceClasses.h

@@ -9,6 +9,7 @@
  */
 #pragma once
 
+#include "BattleConstants.h"
 #include "../gui/CIntObject.h"
 #include "../../lib/battle/BattleHex.h"
 #include "../windows/CWindowObject.h"
@@ -77,23 +78,30 @@ public:
 /// Hero battle animation
 class BattleHero : public CIntObject
 {
-	void switchToNextPhase();
-public:
 	bool flip; //false if it's attacking hero, true otherwise
 
+	std::function<void()> phaseFinishedCallback;
 	std::shared_ptr<CAnimation> animation;
 	std::shared_ptr<CAnimation> flagAnimation;
 
 	const CGHeroInstance * myHero; //this animation's hero instance
-	const BattleInterface * myOwner; //battle interface to which this animation is assigned
-	int phase; //stage of animation
-	int nextPhase; //stage of animation to be set after current phase is fully displayed
-	int currentFrame, firstFrame, lastFrame; //frame of animation
+	const BattleInterface & owner; //battle interface to which this animation is assigned
+
+	EHeroAnimType phase; //stage of animation
+	EHeroAnimType nextPhase; //stage of animation to be set after current phase is fully displayed
 
-	size_t flagAnim;
-	ui8 animCount; //for flag animation
+	float currentFrame; //frame of animation
+	float flagCurrentFrame;
+
+	void switchToNextPhase();
+
+public:
 	void render(Canvas & canvas); //prints next frame of animation to to
-	void setPhase(int newPhase); //sets phase of hero animation
+	void setPhase(EHeroAnimType newPhase); //sets phase of hero animation
+
+	float getFrame() const;
+	void onPhaseFinished(const std::function<void()> &);
+
 	void hover(bool on) override;
 	void clickLeft(tribool down, bool previousState) override; //call-in
 	void clickRight(tribool down, bool previousState) override; //call-in

+ 8 - 0
client/gui/Geometries.h

@@ -160,6 +160,14 @@ struct Rect : public SDL_Rect
 	{
 		return Point(x+w,y+h);
 	}
+	Point center() const
+	{
+		return Point(x+w/2,y+h/2);
+	}
+	Point dimensions() const
+	{
+		return Point(w,h);
+	}
 	Rect operator+(const Rect &p) const //moves this rect by p's rect position
 	{
 		return Rect(x+p.x,y+p.y,w,h);