1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

All projectile animations now use time-based speed

This commit is contained in:
Ivan Savenko 2023-01-05 15:26:29 +02:00
parent a25214ae71
commit 4ca22e652d
4 changed files with 31 additions and 34 deletions

View File

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

View File

@ -33,10 +33,10 @@ struct ProjectileBase
Point from; // initial position on the screen Point from; // initial position on the screen
Point dest; // target position on the screen Point dest; // target position on the screen
int step; // current step counter float progress; // current position of projectile on from->dest line
int steps; // total number of steps/frames to show float speed; // how much progress is gained per second
int shooterID; // ID of shooter stack int shooterID; // ID of shooter stack
bool playing; // if set to true, projectile animation is playing, e.g. flying to target 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 /// 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; const CCreature & getShooter(const CStack * stack) const;
int computeProjectileFrameID( Point from, Point dest, const CStack * stack); 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: public:
BattleProjectileController(BattleInterface & owner); BattleProjectileController(BattleInterface & owner);

View File

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

View File

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