Skip to content

Commit

Permalink
Fixed SPR_isAnimationDone(.)
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephane-D committed Dec 10, 2024
1 parent 4475553 commit de4c620
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 30 deletions.
8 changes: 4 additions & 4 deletions inc/sprite_eng.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
#define SPR_FLAG_INSERT_HEAD 0x4000
/**
* \brief
* Disable animation auto loop..<br>
* By default animation always restart fater the last frame has been played.
* Disable animation auto loop.<br>
* By default animation always restart after the last frame has been played.
* This flag prevent the animation to restart and so the animation end on the last frame forever (see #SPR_getAnimationDone(..))
*/
#define SPR_FLAG_DISABLE_ANIMATION_LOOP 0x2000
Expand Down Expand Up @@ -844,8 +844,8 @@ bool SPR_getAutoAnimation(Sprite* sprite);
void SPR_setAnimationLoop(Sprite* sprite, bool value);
/**
* \brief
* Return TRUE if the sprite reached the last frame of the current animation.<br>
* When auto animation is enabled (see SPR_setAutoAnimation(..)) the function returns TRUE only when we reach
* Returns TRUE if the sprite reached the end of the current animation.<br>
* When auto animation is enabled (see SPR_setAutoAnimation(..)) the function returns TRUE only when we reached
* the last *tick* of the last animation frame.<br>
* When auto animation is disabled the function returns TRUE as soon we are on last animation frame.
*
Expand Down
8 changes: 4 additions & 4 deletions inc/sprite_eng_legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
#define SPR_FLAG_INSERT_HEAD 0x4000
/**
* \brief
* Disable animation auto loop..<br>
* By default animation always restart fater the last frame has been played.
* Disable animation auto loop.<br>
* By default animation always restart after the last frame has been played.
* This flag prevent the animation to restart and so the animation end on the last frame forever (see #SPR_getAnimationDone(..))
*/
#define SPR_FLAG_DISABLE_ANIMATION_LOOP 0x2000
Expand Down Expand Up @@ -837,8 +837,8 @@ bool SPR_getAutoAnimation(Sprite* sprite);
void SPR_setAnimationLoop(Sprite* sprite, bool value);
/**
* \brief
* Return TRUE if the sprite reached the last frame of the current animation.<br>
* When auto animation is enabled (see SPR_setAutoAnimation(..)) the function returns TRUE only when we reach
* Returns TRUE if the sprite reached the end of the current animation.<br>
* When auto animation is enabled (see SPR_setAutoAnimation(..)) the function returns TRUE only when we reached
* the last *tick* of the last animation frame.<br>
* When auto animation is disabled the function returns TRUE as soon we are on last animation frame.
*
Expand Down
Binary file modified lib/libmd.a
Binary file not shown.
Binary file modified lib/libmd_debug.a
Binary file not shown.
28 changes: 14 additions & 14 deletions src/sprite_eng.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@

#define NEED_UPDATE 0x000F

#define STATE_ANIMATION_DONE 0x0010



// shared from vdp_spr.c unit
extern void logVDPSprite(u16 index);
Expand Down Expand Up @@ -1147,6 +1150,8 @@ void SPR_nextFrame(Sprite* sprite)

// loop
frameInd = anim->loop;
// set animation done state (allows SPR_isAnimationDone(..) to correctly report state when called from frame change callback)
sprite->status |= STATE_ANIMATION_DONE;
}

// set new frame
Expand Down Expand Up @@ -1203,8 +1208,10 @@ bool SPR_isAnimationDone(Sprite* sprite)
// for debug
checkSpriteValid(sprite, "SPR_isAnimationDone");

// last tick on last animation frame (use <= 1 so it also works when AutoAnimation is disabled)
return (sprite->timer <= 1) && (sprite->frameInd == (sprite->animation->numFrame - 1));
// check for animation done state (mainly used for frame change callback) or
return (sprite->status & STATE_ANIMATION_DONE) ||
// if we are on last tick from last frame (if auto animation is disabled then only test for last frame)
((sprite->frameInd == (sprite->animation->numFrame - 1)) && ((sprite->timer == 1) || (sprite->timer == -1)));
}

bool SPR_setVRAMTileIndex(Sprite* sprite, s16 value)
Expand Down Expand Up @@ -1937,6 +1944,9 @@ static u16 updateFrame(Sprite* sprite, u16 status)

// set frame
sprite->frame = frame;
// init timer for this frame *before* frame change callback so it can modify change it if needed.
if (SPR_getAutoAnimation(sprite))
sprite->timer = frame->timer;

// frame change event handler defined ? --> call it
if (sprite->onFrameChange)
Expand All @@ -1945,16 +1955,6 @@ static u16 updateFrame(Sprite* sprite, u16 status)
sprite->status = status;
sprite->onFrameChange(sprite);
status = sprite->status;

// init timer for this frame *after* callback call and only if auto animation is enabled and timer was not manually changed in callback
if (sprite->timer == 0)
sprite->timer = frame->timer;
}
else
{
// init timer for this frame *after* callback call to allow SPR_isAnimationDone(..) to correctly report TRUE when animation is done in the callbacnk
if (SPR_getAutoAnimation(sprite))
sprite->timer = frame->timer;
}

// require tile data upload
Expand All @@ -1964,8 +1964,8 @@ static u16 updateFrame(Sprite* sprite, u16 status)
if (status & SPR_FLAG_AUTO_VISIBILITY)
status |= NEED_VISIBILITY_UPDATE;

// frame update done
status &= ~NEED_FRAME_UPDATE;
// frame update done, also clear ANIMATION_DONE state
status &= ~(NEED_FRAME_UPDATE | STATE_ANIMATION_DONE);

END_PROFIL(PROFIL_UPDATE_FRAME)

Expand Down
21 changes: 13 additions & 8 deletions src/sprite_eng_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@

#define NEED_UPDATE 0x001F

#define STATE_ANIMATION_DONE 0x0020


// shared from vdp_spr.c unit
extern void logVDPSprite(u16 index);
Expand Down Expand Up @@ -1161,6 +1163,8 @@ void SPR_nextFrame(Sprite* sprite)

// loop
frameInd = anim->loop;
// set animation done state (allows SPR_isAnimationDone(..) to correctly report state when called from frame change callback)
sprite->status |= STATE_ANIMATION_DONE;
}

// set new frame
Expand Down Expand Up @@ -1221,8 +1225,10 @@ bool SPR_isAnimationDone(Sprite* sprite)
if (!isSpriteValid(sprite, "SPR_isAnimationDone"))
return FALSE;

// last tick on last animation frame (use <= 1 so it also works when AutoAnimation is disabled)
return (sprite->timer <= 1) && (sprite->frameInd == (sprite->animation->numFrame - 1));
// check for animation done state (mainly used for frame change callback) or
return (sprite->status & STATE_ANIMATION_DONE) ||
// if we are on last tick from last frame (if auto animation is disabled then only test for last frame)
((sprite->frameInd == (sprite->animation->numFrame - 1)) && ((sprite->timer == 1) || (sprite->timer == -1)));
}


Expand Down Expand Up @@ -1895,6 +1901,9 @@ static u16 updateFrame(Sprite* sprite, u16 status)
sprite->lastNumSprite = currentNumSprite;
// set frame
sprite->frame = frame;
// init timer for this frame *before* frame change callback so it can modify change it if needed.
if (SPR_getAutoAnimation(sprite))
sprite->timer = frame->timer;

// frame change event handler defined ? --> call it
if (sprite->onFrameChange)
Expand All @@ -1905,19 +1914,15 @@ static u16 updateFrame(Sprite* sprite, u16 status)
status = sprite->status;
}

// init timer for this frame *after* calling callback (this allows SPR_isAnimationDone(..) to correctly report TRUE when animation is done)
if (SPR_getAutoAnimation(sprite))
sprite->timer = frame->timer;

// require tile data upload
if (status & SPR_FLAG_AUTO_TILE_UPLOAD)
status |= NEED_TILES_UPLOAD;
// require visibility update
if (status & SPR_FLAG_AUTO_VISIBILITY)
status |= NEED_VISIBILITY_UPDATE;

// frame update done
status &= ~NEED_FRAME_UPDATE;
// frame update done, also clear ANIMATION_DONE state
status &= ~(NEED_FRAME_UPDATE | STATE_ANIMATION_DONE);

END_PROFIL(PROFIL_UPDATE_FRAME)

Expand Down

0 comments on commit de4c620

Please sign in to comment.