Browse Source

In repeated Animations show skipped Frames from previous Animation (repeated Attack/RangeAttack/Spell)

pull/1848/head
obligaron 5 years ago committed by Anders Jenbo
parent
commit
b08e0c20dc
  1. 20
      Source/engine/animationinfo.cpp
  2. 4
      Source/engine/animationinfo.h
  3. 40
      test/animationinfo_test.cpp

20
Source/engine/animationinfo.cpp

@ -30,7 +30,14 @@ int AnimationInfo::GetFrameToUseForRendering() const
// 1 added for rounding reasons. float to int cast always truncate.
int absoluteAnimationFrame = 1 + (int)(totalTicksForCurrentAnimationSequence * TickModifier);
if (absoluteAnimationFrame > RelevantFramesForDistributing) {
if (SkippedFramesFromPreviousAnimation > 0) {
// absoluteAnimationFrames contains also the Frames from the previous Animation, so if we want to get the current Frame we have to remove them
absoluteAnimationFrame -= SkippedFramesFromPreviousAnimation;
if (absoluteAnimationFrame <= 0) {
// We still display the remains of the previous Animation
absoluteAnimationFrame = NumberOfFrames + absoluteAnimationFrame;
}
} else if (absoluteAnimationFrame > RelevantFramesForDistributing) {
// this can happen if we are at the last frame and the next game tick is due (gfProgressToNextGameTick >= 1.0f)
if (absoluteAnimationFrame > (RelevantFramesForDistributing + 1)) {
// we should never have +2 frames even if next game tick is due
@ -47,6 +54,14 @@ int AnimationInfo::GetFrameToUseForRendering() const
void AnimationInfo::SetNewAnimation(uint8_t *pData, int numberOfFrames, int delayLen, AnimationDistributionParams params /*= AnimationDistributionParams::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
{
if (pData == this->pData && distributeFramesBeforeFrame != 0 && NumberOfFrames == numberOfFrames && CurrentFrame >= distributeFramesBeforeFrame && CurrentFrame != NumberOfFrames) {
// We showed the same Animation (for example a melee attack) before but truncated the Animation.
// So now we should add them back to the new Animation. This increases the speed of the current Animation but the game logic/ticks isn't affected.
SkippedFramesFromPreviousAnimation = NumberOfFrames - CurrentFrame;
} else {
SkippedFramesFromPreviousAnimation = 0;
}
this->pData = pData;
NumberOfFrames = numberOfFrames;
CurrentFrame = 1;
@ -108,6 +123,9 @@ void AnimationInfo::SetNewAnimation(uint8_t *pData, int numberOfFrames, int dela
relevantAnimationTicksWithSkipping -= delayLen;
}
// The truncated Frames from previous Animation will also be shown, so we also have to distribute them for the given time (game ticks)
relevantAnimationTicksForDistribution += (SkippedFramesFromPreviousAnimation * ticksPerFrame);
// if we skipped Frames we need to expand the game ticks to make one game tick for this Animation "faster"
float tickModifier = (float)relevantAnimationTicksForDistribution / (float)relevantAnimationTicksWithSkipping;

4
Source/engine/animationinfo.h

@ -85,6 +85,10 @@ private:
* @brief Animation Frames that will be adjusted for the skipped Frames/game ticks
*/
int RelevantFramesForDistributing;
/**
* @brief Animation Frames that wasn't shown from previous Animation
*/
int SkippedFramesFromPreviousAnimation;
};
} // namespace devilution

40
test/animationinfo_test.cpp

@ -278,38 +278,38 @@ TEST(AnimationInfo, AttackSwordWarriorRepeated)
new SetNewAnimationData(16, 0, AnimationDistributionParams::ProcessAnimationPending, 0, 9),
// ProcessAnimation directly after StartAttack (in same GameTick). So we don't see any rendering before.
new GameTickData(2, 0),
new RenderingData(0.0f, 11),
new RenderingData(0.3f, 11),
new RenderingData(0.6f, 12),
new RenderingData(0.8f, 12),
new GameTickData(3, 0),
new RenderingData(0.0f, 13),
new RenderingData(0.3f, 13),
new RenderingData(0.6f, 14),
new RenderingData(0.8f, 14),
new GameTickData(4, 0),
new RenderingData(0.0f, 15),
new RenderingData(0.3f, 15),
new RenderingData(0.6f, 16),
new RenderingData(0.8f, 16),
new GameTickData(5, 0),
new RenderingData(0.0f, 1),
new RenderingData(0.3f, 1),
new RenderingData(0.6f, 1),
new RenderingData(0.8f, 1),
new GameTickData(3, 0),
new RenderingData(0.0f, 2),
new RenderingData(0.3f, 2),
new RenderingData(0.6f, 2),
new RenderingData(0.8f, 3),
new GameTickData(4, 0),
new RenderingData(0.8f, 2),
new GameTickData(6, 0),
new RenderingData(0.0f, 3),
new RenderingData(0.3f, 3),
new RenderingData(0.6f, 3),
new RenderingData(0.6f, 4),
new RenderingData(0.8f, 4),
new GameTickData(5, 0),
new RenderingData(0.0f, 4),
new RenderingData(0.3f, 4),
new RenderingData(0.6f, 5),
new RenderingData(0.8f, 5),
new GameTickData(6, 0),
new GameTickData(7, 0),
new RenderingData(0.0f, 5),
new RenderingData(0.3f, 5),
new RenderingData(0.6f, 6),
new RenderingData(0.8f, 6),
new GameTickData(7, 0),
new RenderingData(0.0f, 6),
new RenderingData(0.3f, 7),
new RenderingData(0.6f, 7),
new RenderingData(0.8f, 7),
new GameTickData(8, 0),
new RenderingData(0.0f, 7),
new RenderingData(0.3f, 8),
new RenderingData(0.3f, 7),
new RenderingData(0.6f, 8),
new RenderingData(0.8f, 8),

Loading…
Cancel
Save