fencer/core/src/animation_sprite.c

91 lines
2.6 KiB
C

#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);
}