Jelajahi Sumber

All projectile animations now use time-based speed

Ivan Savenko 2 tahun lalu
induk
melakukan
4ca22e652d

+ 22 - 24
client/battle/BattleProjectileController.cpp

@@ -53,8 +53,6 @@ void ProjectileMissile::show(Canvas & canvas)
 
 	if(image)
 	{
-		float progress = float(step) / steps;
-
 		Point pos {
 			vstd::lerp(from.x, dest.x, progress) - image->width() / 2,
 			vstd::lerp(from.y, dest.y, progress) - image->height() / 2,
@@ -62,7 +60,9 @@ void ProjectileMissile::show(Canvas & canvas)
 
 		canvas.draw(image, pos);
 	}
-	++step;
+
+	float timePassed = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f;
+	progress += timePassed * speed;
 }
 
 void ProjectileAnimatedMissile::show(Canvas & canvas)
@@ -82,8 +82,6 @@ void ProjectileCatapult::show(Canvas & canvas)
 
 	if(image)
 	{
-		float progress = float(step) / steps;
-
 		int posX = vstd::lerp(from.x, dest.x, progress);
 		int posY = calculateCatapultParabolaY(from, dest, posX);
 		Point pos(posX, posY);
@@ -92,13 +90,13 @@ void ProjectileCatapult::show(Canvas & canvas)
 
 		frameNum = (frameNum + 1) % animation->size(0);
 	}
-	++step;
+
+	float timePassed = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f;
+	progress += timePassed * speed;
 }
 
 void ProjectileRay::show(Canvas & canvas)
 {
-	float progress = float(step) / steps;
-
 	Point curr {
 		vstd::lerp(from.x, dest.x, progress),
 		vstd::lerp(from.y, dest.y, progress),
@@ -142,7 +140,9 @@ void ProjectileRay::show(Canvas & canvas)
 			canvas.drawLine(Point(x1 + i, y1), Point(x2 + i, y2), beginColor, endColor);
 		}
 	}
-	++step;
+
+	float timePassed = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f;
+	progress += timePassed * speed;
 }
 
 BattleProjectileController::BattleProjectileController(BattleInterface & owner):
@@ -231,7 +231,7 @@ void BattleProjectileController::showProjectiles(Canvas & canvas)
 	}
 
 	vstd::erase_if(projectiles, [&](const std::shared_ptr<ProjectileBase> & projectile){
-		return projectile->step > projectile->steps;
+		return projectile->progress > 1.0f;
 	});
 }
 
@@ -249,15 +249,14 @@ bool BattleProjectileController::hasActiveProjectile(const CStack * stack, bool
 	return false;
 }
 
-int BattleProjectileController::computeProjectileFlightTime( Point from, Point dest, double animSpeed)
+float BattleProjectileController::computeProjectileFlightTime( Point from, Point dest, double animSpeed)
 {
-	double distanceSquared = (dest.x - from.x) * (dest.x - from.x) + (dest.y - from.y) * (dest.y - from.y);
-	double distance = sqrt(distanceSquared);
-	int steps = std::round(distance / animSpeed);
+	float distanceSquared = (dest.x - from.x) * (dest.x - from.x) + (dest.y - from.y) * (dest.y - from.y);
+	float distance = sqrt(distanceSquared);
+
+	assert(distance > 1.f);
 
-	if (steps > 0)
-		return steps;
-	return 1;
+	return animSpeed / std::max( 1.f, distance);
 }
 
 int BattleProjectileController::computeProjectileFrameID( Point from, Point dest, const CStack * stack)
@@ -297,12 +296,11 @@ void BattleProjectileController::createCatapultProjectile(const CStack * shooter
 
 	catapultProjectile->animation = getProjectileImage(shooter);
 	catapultProjectile->frameNum  = 0;
-	catapultProjectile->step      = 0;
-	catapultProjectile->steps     = computeProjectileFlightTime(from, dest, AnimationControls::getCatapultSpeed());
+	catapultProjectile->progress  = 0;
+	catapultProjectile->speed     = computeProjectileFlightTime(from, dest, AnimationControls::getCatapultSpeed());
 	catapultProjectile->from      = from;
 	catapultProjectile->dest      = dest;
 	catapultProjectile->shooterID = shooter->ID;
-	catapultProjectile->step      = 0;
 	catapultProjectile->playing   = false;
 
 	projectiles.push_back(std::shared_ptr<ProjectileBase>(catapultProjectile));
@@ -335,11 +333,11 @@ void BattleProjectileController::createProjectile(const CStack * shooter, Point
 		missileProjectile->frameNum = computeProjectileFrameID(from, dest, shooter);
 	}
 
-	projectile->steps     = computeProjectileFlightTime(from, dest, AnimationControls::getProjectileSpeed());
+	projectile->speed     = computeProjectileFlightTime(from, dest, AnimationControls::getProjectileSpeed());
 	projectile->from      = from;
 	projectile->dest      = dest;
 	projectile->shooterID = shooter->ID;
-	projectile->step      = 0;
+	projectile->progress  = 0;
 	projectile->playing   = false;
 
 	projectiles.push_back(projectile);
@@ -363,8 +361,8 @@ void BattleProjectileController::createSpellProjectile(const CStack * shooter, P
 		projectile->from          = from;
 		projectile->dest          = dest;
 		projectile->shooterID     = shooter ? shooter->ID : -1;
-		projectile->step          = 0;
-		projectile->steps         = computeProjectileFlightTime(from, dest, AnimationControls::getSpellEffectSpeed());
+		projectile->progress      = 0;
+		projectile->speed         = computeProjectileFlightTime(from, dest, AnimationControls::getProjectileSpeed());
 		projectile->playing       = false;
 
 		projectiles.push_back(std::shared_ptr<ProjectileBase>(projectile));

+ 5 - 5
client/battle/BattleProjectileController.h

@@ -33,10 +33,10 @@ struct ProjectileBase
 	Point from; // initial position on the screen
 	Point dest; // target position on the screen
 
-	int step;      // current step counter
-	int steps;     // total number of steps/frames to show
-	int shooterID; // ID of shooter stack
-	bool playing;  // if set to true, projectile animation is playing, e.g. flying to target
+	float progress; // current position of projectile on from->dest line
+	float speed;    // how much progress is gained per second
+	int shooterID;  // ID of shooter stack
+	bool playing;   // if set to true, projectile animation is playing, e.g. flying to target
 };
 
 /// Projectile for most shooters - render pre-selected frame moving in straight line from origin to destination
@@ -97,7 +97,7 @@ class BattleProjectileController
 	const CCreature & getShooter(const CStack * stack) const;
 
 	int computeProjectileFrameID( Point from, Point dest, const CStack * stack);
-	int computeProjectileFlightTime( Point from, Point dest, double speed);
+	float computeProjectileFlightTime( Point from, Point dest, double speed);
 
 public:
 	BattleProjectileController(BattleInterface & owner);

+ 2 - 2
client/battle/CreatureAnimation.cpp

@@ -115,12 +115,12 @@ float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, c
 
 float AnimationControls::getProjectileSpeed()
 {
-	return static_cast<float>(settings["battle"]["animationSpeed"].Float() * 100);
+	return static_cast<float>(settings["battle"]["animationSpeed"].Float() * 4000);
 }
 
 float AnimationControls::getCatapultSpeed()
 {
-	return static_cast<float>(settings["battle"]["animationSpeed"].Float() * 20);
+	return static_cast<float>(settings["battle"]["animationSpeed"].Float() * 1000);
 }
 
 float AnimationControls::getSpellEffectSpeed()

+ 2 - 3
client/battle/CreatureAnimation.h

@@ -31,11 +31,10 @@ namespace AnimationControls
 	/// returns animation speed of specific group, taking in mind game setting (in frames per second)
 	float getCreatureAnimationSpeed(const CCreature * creature, const CreatureAnimation * anim, ECreatureAnimType groupID);
 
-	/// returns how far projectile should move each frame
-	/// TODO: make it time-based
+	/// returns how far projectile should move per second
 	float getProjectileSpeed();
 
-	/// returns speed of catapult projectile
+	/// returns speed of catapult projectile, in pixels per second (horizontal axis only)
 	float getCatapultSpeed();
 
 	/// returns speed of any spell effects, including any special effects like morale (in frames per second)