Browse Source

Introduce AnimationDistributionFlags::RepeatedAction

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

2
Source/engine/animationinfo.cpp

@ -54,7 +54,7 @@ int AnimationInfo::GetFrameToUseForRendering() const
void AnimationInfo::SetNewAnimation(uint8_t *pData, int numberOfFrames, int delayLen, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
{
if (pData == this->pData && distributeFramesBeforeFrame != 0 && NumberOfFrames == numberOfFrames && CurrentFrame >= distributeFramesBeforeFrame && CurrentFrame != NumberOfFrames) {
if ((flags & AnimationDistributionFlags::RepeatedAction) == AnimationDistributionFlags::RepeatedAction && 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;

4
Source/engine/animationinfo.h

@ -23,6 +23,10 @@ enum AnimationDistributionFlags : uint8_t {
* @brief Delay of last Frame is ignored (for example, because only Frame and not delay is checked in game_logic)
*/
SkipsDelayOfLastFrame = 1 << 1,
/**
* @brief Repeated Animation (for example same player melee attack, that can be repeated directly after hit frame and doesn't need to show all animation frames)
*/
RepeatedAction = 1 << 2,
};
/*

20
Source/player.cpp

@ -1489,7 +1489,10 @@ void StartAttack(int pnum, direction d)
skippedAnimationFrames = 2;
}
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth, AnimationDistributionFlags::ProcessAnimationPending, skippedAnimationFrames, plr[pnum]._pAFNum);
auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;
if (plr[pnum]._pmode == PM_ATTACK)
animationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction);
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth, animationFlags, skippedAnimationFrames, plr[pnum]._pAFNum);
plr[pnum]._pmode = PM_ATTACK;
FixPlayerLocation(pnum, d);
SetPlayerOld(pnum);
@ -1517,7 +1520,10 @@ void StartRangeAttack(int pnum, direction d, int cx, int cy)
}
}
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth, AnimationDistributionFlags::ProcessAnimationPending, skippedAnimationFrames, plr[pnum]._pAFNum);
auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;
if (plr[pnum]._pmode == PM_RATTACK)
animationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction);
NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth, animationFlags, skippedAnimationFrames, plr[pnum]._pAFNum);
plr[pnum]._pmode = PM_RATTACK;
FixPlayerLocation(pnum, d);
@ -1565,24 +1571,28 @@ void StartSpell(int pnum, direction d, int cx, int cy)
}
if (leveltype != DTYPE_TOWN) {
auto animationFlags = AnimationDistributionFlags::ProcessAnimationPending;
if (plr[pnum]._pmode == PM_SPELL)
animationFlags = static_cast<AnimationDistributionFlags>(animationFlags | AnimationDistributionFlags::RepeatedAction);
switch (spelldata[plr[pnum]._pSpell].sType) {
case STYPE_FIRE:
if ((plr[pnum]._pGFXLoad & PFILE_FIRE) == 0) {
LoadPlrGFX(pnum, PFILE_FIRE);
}
NewPlrAnim(pnum, plr[pnum]._pFAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionFlags::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
NewPlrAnim(pnum, plr[pnum]._pFAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, animationFlags, 0, plr[pnum]._pSFNum);
break;
case STYPE_LIGHTNING:
if ((plr[pnum]._pGFXLoad & PFILE_LIGHTNING) == 0) {
LoadPlrGFX(pnum, PFILE_LIGHTNING);
}
NewPlrAnim(pnum, plr[pnum]._pLAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionFlags::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
NewPlrAnim(pnum, plr[pnum]._pLAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, animationFlags, 0, plr[pnum]._pSFNum);
break;
case STYPE_MAGIC:
if ((plr[pnum]._pGFXLoad & PFILE_MAGIC) == 0) {
LoadPlrGFX(pnum, PFILE_MAGIC);
}
NewPlrAnim(pnum, plr[pnum]._pTAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, AnimationDistributionFlags::ProcessAnimationPending, 0, plr[pnum]._pSFNum);
NewPlrAnim(pnum, plr[pnum]._pTAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth, animationFlags, 0, plr[pnum]._pSFNum);
break;
}
}

2
test/animationinfo_test.cpp

@ -275,7 +275,7 @@ TEST(AnimationInfo, AttackSwordWarriorRepeated)
new RenderingData(0.3f, 10),
// Start of repeated attack, cause plr[pnum].AnimInfo.CurrentFrame > plr[myplr]._pAFNum
new SetNewAnimationData(16, 0, AnimationDistributionFlags::ProcessAnimationPending, 0, 9),
new SetNewAnimationData(16, 0, static_cast<AnimationDistributionFlags>(AnimationDistributionFlags::ProcessAnimationPending | AnimationDistributionFlags::RepeatedAction), 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),

Loading…
Cancel
Save