rework animation logic, don't loop increasingly as time goes on

This commit is contained in:
jacob 2024-03-11 13:21:31 -05:00
parent 76c609f8d5
commit 452e922e23
5 changed files with 55 additions and 73 deletions

View File

@ -1,24 +1,3 @@
#include "entity.h" #include "entity.h"
READONLY struct entity _g_entity_nil = { 0 }; READONLY struct entity _g_entity_nil = { 0 };
void entity_enable_prop(struct entity *entity, enum entity_prop prop)
{
u64 index = prop / 64;
u64 bit = prop % 64;
entity->props[index] |= ((u64)1 << bit);
}
void entity_disable_prop(struct entity *entity, enum entity_prop prop)
{
u64 index = prop / 64;
u64 bit = prop % 64;
entity->props[index] &= ~((u64)1 << bit);
}
b32 entity_has_prop(struct entity *entity, enum entity_prop prop)
{
u64 index = prop / 64;
u64 bit = prop % 64;
return !!(entity->props[index] & ((u64)1 << bit));
}

View File

@ -41,9 +41,8 @@ struct entity {
struct entity_handle last; struct entity_handle last;
/* ====================================================================== */ /* ====================================================================== */
/* Translation, rotation, scale in relation to parent entity */
struct xform rel_xform; struct xform rel_xform; /* Transform in relation to parent entity (or the world if entity has no parent) */
struct xform world_xform; /* Calculated post-physics */ struct xform world_xform; /* Calculated post-physics */
/* ====================================================================== */ /* ====================================================================== */
@ -68,8 +67,8 @@ struct entity {
/* Animation */ /* Animation */
/* ENTITY_PROP_ANIMATING */ /* ENTITY_PROP_ANIMATING */
b32 animation_looping; f64 animation_time_in_frame;
f64 animation_start_time; /* Calculated */ u64 animation_frame;
/* ====================================================================== */ /* ====================================================================== */
/* Testing */ /* Testing */
@ -95,8 +94,25 @@ struct entity {
extern READONLY struct entity _g_entity_nil; extern READONLY struct entity _g_entity_nil;
INLINE READONLY struct entity *entity_nil(void) { return &_g_entity_nil; } INLINE READONLY struct entity *entity_nil(void) { return &_g_entity_nil; }
void entity_enable_prop(struct entity *entity, enum entity_prop prop); INLINE void entity_enable_prop(struct entity *entity, enum entity_prop prop)
void entity_disable_prop(struct entity *entity, enum entity_prop prop); {
b32 entity_has_prop(struct entity *entity, enum entity_prop prop); u64 index = prop / 64;
u64 bit = prop % 64;
entity->props[index] |= ((u64)1 << bit);
}
INLINE void entity_disable_prop(struct entity *entity, enum entity_prop prop)
{
u64 index = prop / 64;
u64 bit = prop % 64;
entity->props[index] &= ~((u64)1 << bit);
}
INLINE b32 entity_has_prop(struct entity *entity, enum entity_prop prop)
{
u64 index = prop / 64;
u64 bit = prop % 64;
return !!(entity->props[index] & ((u64)1 << bit));
}
#endif #endif

View File

@ -135,7 +135,6 @@ INTERNAL void game_update(void)
e->player_acceleration = 15.0f; e->player_acceleration = 15.0f;
entity_enable_prop(e, ENTITY_PROP_ANIMATING); entity_enable_prop(e, ENTITY_PROP_ANIMATING);
e->animation_looping = true;
player_ent = e; player_ent = e;
@ -144,8 +143,9 @@ INTERNAL void game_update(void)
} }
/* Child ent */ /* Child ent */
{ for (u64 i = 0; i < 100; ++i) {
struct v2 pos = V2(0, 0.25); //struct v2 pos = V2(0, 0.001);
struct v2 pos = V2(0, 0.25 * (i + 1));
struct v2 size = V2(1, 1); struct v2 size = V2(1, 1);
f32 r = 0; f32 r = 0;
@ -185,7 +185,6 @@ INTERNAL void game_update(void)
//e->player_acceleration = 15.0f; //e->player_acceleration = 15.0f;
entity_enable_prop(e, ENTITY_PROP_ANIMATING); entity_enable_prop(e, ENTITY_PROP_ANIMATING);
e->animation_looping = true;
//entity_enable_prop(e, ENTITY_PROP_TEST); //entity_enable_prop(e, ENTITY_PROP_TEST);
//entity_enable_prop(e, ENTITY_PROP_TEST_FOLLOW_MOUSE); //entity_enable_prop(e, ENTITY_PROP_TEST_FOLLOW_MOUSE);
@ -271,41 +270,34 @@ INTERNAL void game_update(void)
ent->test_start_sprite_xform = ent->sprite_xform; ent->test_start_sprite_xform = ent->sprite_xform;
} }
/* ENTITY_PROP_ANIMATING */
if (entity_has_prop(ent, ENTITY_PROP_ANIMATING) && ent->animation_start_time == 0) {
ent->animation_start_time = L.world.time;
}
/* ========================== * /* ========================== *
* Update animation * Update animation
* ========================== */ * ========================== */
if (ent->animation_start_time > 0) { if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) {
/* Stop animation if past duration and not looping */ f64 time_in_frame = ent->animation_time_in_frame + L.world.dt;
if (!ent->animation_looping) { u64 tag_frame_offset = ent->animation_frame;
f64 time_in_anim = L.world.time - ent->animation_start_time;
struct sheet *sheet = sheet_load(ent->sprite_name); struct sheet *sheet = sheet_load(ent->sprite_name);
if (sheet) { if (sheet) {
struct sheet_tag tag = sheet_get_tag(sheet, ent->sprite_tag_name); struct sheet_tag tag = sheet_get_tag(sheet, ent->sprite_tag_name);
u64 frame_index = tag.start + tag_frame_offset;
struct sheet_frame frame = { 0 }; struct sheet_frame frame = sheet_get_frame(sheet, frame_index);
u64 frame_index = tag.start; while (time_in_frame > frame.duration) {
while (time_in_anim > 0) { time_in_frame -= frame.duration;
frame = sheet_get_frame(sheet, frame_index); ++frame_index;
if (frame_index > tag.end) { if (frame_index > tag.end) {
entity_disable_prop(ent, ENTITY_PROP_ANIMATING); /* Loop animation */
ent->animation_start_time = 0; frame_index = tag.start;
break;
}
time_in_anim -= frame.duration;
++frame_index;
} }
} else { frame = sheet_get_frame(sheet, frame_index);
entity_disable_prop(ent, ENTITY_PROP_ANIMATING);
ent->animation_start_time = 0;
} }
tag_frame_offset = frame_index - tag.start;
} }
ent->animation_time_in_frame = time_in_frame;
ent->animation_frame = tag_frame_offset;
} }
/* ========================== * /* ========================== *

View File

@ -528,6 +528,7 @@ INTERNAL void user_update(void)
e->player_acceleration = math_lerp_f32(e0->player_acceleration, e1->player_acceleration, tick_blend); e->player_acceleration = math_lerp_f32(e0->player_acceleration, e1->player_acceleration, tick_blend);
e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend); e->sprite_xform = xform_lerp(e0->sprite_xform, e1->sprite_xform, tick_blend);
e->animation_time_in_frame = math_lerp_f64(e0->animation_time_in_frame, e1->animation_time_in_frame, (f64)tick_blend);
e->camera_zoom = math_lerp_f32(e0->camera_zoom, e1->camera_zoom, tick_blend); e->camera_zoom = math_lerp_f32(e0->camera_zoom, e1->camera_zoom, tick_blend);
} }
@ -629,22 +630,18 @@ INTERNAL void user_update(void)
if (sheet) { if (sheet) {
struct sheet_tag tag = sheet_get_tag(sheet, ent->sprite_tag_name); struct sheet_tag tag = sheet_get_tag(sheet, ent->sprite_tag_name);
struct sheet_frame frame = sheet_get_frame(sheet, tag.start); u64 frame_index = tag.start + ent->animation_frame;
struct sheet_frame frame = sheet_get_frame(sheet, frame_index);
if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) { if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) {
b32 looping = ent->animation_looping; f64 time_in_frame = ent->animation_time_in_frame;
f64 time_in_anim = L.world.time - ent->animation_start_time; while (time_in_frame > frame.duration) {
time_in_frame -= frame.duration;
u64 frame_index = tag.start;
while (time_in_anim > 0) {
frame = sheet_get_frame(sheet, frame_index);
time_in_anim -= frame.duration;
++frame_index; ++frame_index;
if (frame_index > tag.end) { if (frame_index > tag.end) {
/* Loop animation */
frame_index = tag.start; frame_index = tag.start;
if (!looping) {
break;
}
} }
frame = sheet_get_frame(sheet, frame_index);
} }
} }

View File

@ -16,13 +16,11 @@ struct world {
u64 entities_count; /* Includes 'released' & inactive entities */ u64 entities_count; /* Includes 'released' & inactive entities */
struct entity_handle first_free_entity; struct entity_handle first_free_entity;
/* ====================================================================== */ /* ====================================================================== */
/* Everything after this field is not automatically coppied /* Everything after this field is not dumb-MEMCPY'd by world_copy_replace */
* in world_copy_replace */
u8 _copy_barrier; u8 _copy_barrier;
/* Arenas */ /* Entities array */
struct arena entities_arena; struct arena entities_arena;
struct entity *entities; struct entity *entities;
}; };