fix animation transition issue for hit enemies

Transitioning to the `next` animation frame preserved the priority,
which was a problem for enemies with a next: Hit=Idle or similar
transition, as that would give an infinite Idle loop with high
priority.

This change forces a clear of the animation priority when such a
transition occurs. This relies on the flawed linked list system, which
means that it will not happen if the new animation is just after the
current one in the source file. This is a fundamental issue due to
mixing all frames as single pointers in the anim_t structure. This will
be fixed in engine code eventually.
This commit is contained in:
Lephenixnoir 2022-12-30 15:59:13 +01:00
parent d6221db818
commit e2ba1f51c2
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
8 changed files with 24 additions and 17 deletions

View File

@ -16,10 +16,10 @@ bat_right.aseprite:
gunslinger_left.aseprite:
center: 15, 22
next: Idle=Idle, Walking=Walking, Hit=Idle, Fire=Reloading
next: Idle=Idle, Walking=Walking, Hit=Idle
gunslinger_right.aseprite:
center: 8, 22
next: Idle=Idle, Walking=Walking, Hit=Idle, Fire=Reloading
next: Idle=Idle, Walking=Walking, Hit=Idle
*.txt:
custom-type: aseprite-anim-variation

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.4" orientation="orthogonal" renderorder="right-down" width="24" height="11" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
<map version="1.9" tiledversion="1.9.2" orientation="orthogonal" renderorder="right-down" width="24" height="11" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="1">
<tileset firstgid="1" source="../tilesets/cavern.tsx"/>
<layer id="1" name="Ground" width="24" height="11">
<data encoding="csv">
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,7,15,8,7,8,7,16,8,7,15,7,7,16,8,2,2,2,2,2,
2,2,2,2,2,4,4,14,14,6,3,3,3,3,6,4,4,14,4,2,2,2,2,2,
2,2,2,2,2,14,14,5,3,3,3,5,5,3,3,3,5,4,4,2,2,2,2,2,
2,2,2,2,2,3,5,3,3,3,4,5,5,4,3,3,3,5,3,2,2,2,2,2,
2,2,2,2,2,5,3,3,6,5,5,6,6,5,5,6,3,3,5,2,2,2,2,2,
2,2,2,2,2,3,5,3,3,3,4,5,5,4,3,3,3,5,3,2,2,2,2,2,
2,2,2,2,2,14,14,5,3,3,3,2,2,3,3,3,5,4,4,2,2,2,2,2,
2,2,2,2,2,3,5,3,3,3,2,2,2,2,3,3,3,5,3,2,2,2,2,2,
2,2,2,2,2,5,3,3,6,5,7,2,2,7,5,6,3,3,5,2,2,2,2,2,
2,2,2,2,2,3,5,3,3,3,4,7,23,4,3,3,3,5,3,2,2,2,2,2,
2,2,2,2,2,14,4,5,3,3,3,5,5,3,3,3,5,4,14,2,2,2,2,2,
2,2,2,2,2,4,14,4,4,6,3,3,3,3,6,14,14,4,4,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,

View File

@ -138,14 +138,19 @@ void anim_frame_subrender(int x, int y, anim_frame_t const *frame, int left,
frame->x + left, frame->y + top, width, height, DIMAGE_NONE);
}
void anim_state_update(anim_state_t *state, fixed_t dt)
bool anim_state_update(anim_state_t *state, fixed_t dt)
{
if(!state->frame) return;
if(!state->frame) return false;
state->elapsed += fround(dt * 1000);
if(state->elapsed < state->frame->duration) return;
if(state->elapsed < state->frame->duration) return false;
// TODO: FIXME: This is incorrect if the next animation is just behind
bool transitioning = (state->frame->next != state->frame + 1);
/* Switch to next frame */
state->elapsed -= state->frame->duration;
state->frame = state->frame->next;
return transitioning;
}

View File

@ -61,8 +61,9 @@ void anim_frame_render(int x, int y, anim_frame_t const *frame);
void anim_frame_subrender(int x, int y, anim_frame_t const *frame, int left,
int top, int width, int height);
/* Update an animation to next frame. */
void anim_state_update(anim_state_t *state, fixed_t dt);
/* Update an animation to next frame. Returns true if the update transitioned
to another animation. */
bool anim_state_update(anim_state_t *state, fixed_t dt);
/* List of animations. */
@ -87,9 +88,9 @@ extern anim_t anims_skill_bullet;
ANIM_E1(MACRO, bat, Idle, Hit, Death) \
ANIM_E1(MACRO, albinos_bat, Idle, Hit, Death) \
ANIM_E1(MACRO, crimson_bat, Idle, Hit, Death) \
ANIM_E1(MACRO, gunslinger, Idle, Walking, Reloading, Fire, Hit, Death) \
ANIM_E1(MACRO, gb_gunslinger, Idle, Walking, Reloading, Fire, Hit, Death) \
ANIM_E1(MACRO, master_gunslinger, Idle, Walking,Reloading,Fire,Hit,Death) \
ANIM_E1(MACRO, gunslinger, Idle, Walking, Fire, Hit, Death) \
ANIM_E1(MACRO, gb_gunslinger, Idle, Walking, Fire, Hit, Death) \
ANIM_E1(MACRO, master_gunslinger, Idle, Walking, Fire,Hit,Death) \
ANIM_E1(MACRO, tifucile, Idle, Walking, Hit, Death) \
ANIM_E1(MACRO, washing_machine, Idle, Walking, Attack, Hit, Death)

View File

@ -38,7 +38,8 @@ void visible_update(entity_t *e, fixed_t dt)
if(v->anim.frame == NULL)
return;
anim_state_update(&v->anim, dt);
if(anim_state_update(&v->anim, dt))
v->anim_priority = 0;
if(v->anim.frame == NULL)
v->anim_priority = 0;

View File

@ -504,7 +504,7 @@ void render_arcade(int x, int y, int halign, int value, int color_style)
/* Auto style based on the number of digits */
if(color_style < 0)
color_style = (value >= 10) + (value >= 100);
color_style = (value >= 10) + (value >= 30);
char str[16];
sprintf(str, "%d", value);