#include "animation_sprite.h" #include "debug.h" #include "program.h" struct AnimationSprite { Spritesheet* sheet; Sprite* sprite_target; AnimationSpriteLoopMode loop_mode; float frame_interval; float start_time; }; AnimationSprite* animation_sprite_new(Sprite* target_sprite, Spritesheet* sheet, float framerate, AnimationSpriteLoopMode loop_mode) { AnimationSprite* self = malloc(sizeof(AnimationSprite)); ASSERT_RETURN(self != NULL, NULL, "Failed to allocate memory for AnimationSprite"); *self = (AnimationSprite){ .sheet = sheet, .frame_interval = 1.0f / framerate, .loop_mode = loop_mode, .start_time = game_time(), .sprite_target = target_sprite }; return self; } void animation_sprite_destroy(AnimationSprite* self) { spritesheet_destroy(self->sheet); free(self); } void animation_sprite_play_from(AnimationSprite* self, float normalized_time) { self->start_time = game_time() - normalized_time * animation_sprite_get_length(self); } void animation_sprite_draw(AnimationSprite* self, Transform* transform) { const size_t frame_count = spritesheet_get_tile_count(self->sheet); const float time = game_time() - self->start_time; size_t frame = time / self->frame_interval; switch(self->loop_mode) { case LoopMode_Hide: if(frame >= frame_count) return; else break; case LoopMode_Loop: frame %= frame_count; break; case LoopMode_PingPong: frame %= frame_count * 2; if(frame >= frame_count) frame = frame_count - (frame - frame_count); return; case LoopMode_Stop: if(frame >= frame_count) frame = frame_count - 1; } sprite_set_spritesheet(self->sprite_target, self->sheet); sprite_set_tile(self->sprite_target, frame); sprite_draw(self->sprite_target, *transform); } float animation_sprite_get_length(AnimationSprite* self) { return (float)spritesheet_get_tile_count(self->sheet) * self->frame_interval; } void animation_sprite_set_framerate(AnimationSprite* self, float framerate) { self->frame_interval = 1.0f / framerate; } float animation_sprite_get_framerate(const AnimationSprite* self) { return 1.0f / self->frame_interval; } Sprite* animation_sprite_get_sprite(AnimationSprite* self) { return self->sprite_target; } float animation_sprite_get_time(AnimationSprite* self) { return game_time() - self->start_time; } float animation_sprite_get_time_normalized(AnimationSprite* self) { return animation_sprite_get_time(self) / animation_sprite_get_length(self); }