feat: added animation events to animation_sprite
This commit is contained in:
parent
a63cfdd2b0
commit
f67f95fd6a
|
@ -1,6 +1,7 @@
|
||||||
#include "animation_sprite.h"
|
#include "animation_sprite.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
struct AnimationSprite {
|
struct AnimationSprite {
|
||||||
Spritesheet *sheet;
|
Spritesheet *sheet;
|
||||||
|
@ -10,9 +11,14 @@ struct AnimationSprite {
|
||||||
|
|
||||||
float frame_interval;
|
float frame_interval;
|
||||||
float start_time;
|
float start_time;
|
||||||
|
|
||||||
|
size_t event_index;
|
||||||
|
List events;
|
||||||
};
|
};
|
||||||
|
|
||||||
AnimationSprite* animation_sprite_new(Sprite* target_sprite, Spritesheet* sheet, float framerate, AnimationSpriteLoopMode loop_mode) {
|
AnimationSprite *animation_sprite_new(Sprite *target_sprite, Spritesheet *sheet,
|
||||||
|
float framerate, AnimationSpriteLoopMode loop_mode,
|
||||||
|
AnimationEvent *events, size_t event_count) {
|
||||||
AnimationSprite *self = malloc(sizeof(AnimationSprite));
|
AnimationSprite *self = malloc(sizeof(AnimationSprite));
|
||||||
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate memory for AnimationSprite");
|
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate memory for AnimationSprite");
|
||||||
*self = (AnimationSprite){
|
*self = (AnimationSprite){
|
||||||
|
@ -20,9 +26,14 @@ AnimationSprite* animation_sprite_new(Sprite* target_sprite, Spritesheet* sheet,
|
||||||
.frame_interval = 1.0f / framerate,
|
.frame_interval = 1.0f / framerate,
|
||||||
.loop_mode = loop_mode,
|
.loop_mode = loop_mode,
|
||||||
.start_time = game_time(),
|
.start_time = game_time(),
|
||||||
.sprite_target = target_sprite
|
.sprite_target = target_sprite,
|
||||||
|
.event_index = 0,
|
||||||
|
.events = list_with_len(sizeof(AnimationEvent), event_count),
|
||||||
};
|
};
|
||||||
|
if(event_count > 0) {
|
||||||
|
memcpy(self->events.data, events, sizeof(AnimationEvent) * event_count);
|
||||||
|
self->events.len = event_count;
|
||||||
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +42,10 @@ void animation_sprite_destroy(AnimationSprite* self) {
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void animation_sprite_reset(AnimationSprite *self) {
|
||||||
|
self->start_time = game_time();
|
||||||
|
}
|
||||||
|
|
||||||
void animation_sprite_play_from(AnimationSprite *self, float normalized_time) {
|
void animation_sprite_play_from(AnimationSprite *self, float normalized_time) {
|
||||||
self->start_time = game_time() - normalized_time * animation_sprite_get_length(self);
|
self->start_time = game_time() - normalized_time * animation_sprite_get_length(self);
|
||||||
}
|
}
|
||||||
|
@ -38,10 +53,11 @@ void animation_sprite_play_from(AnimationSprite* self, float normalized_time) {
|
||||||
void animation_sprite_draw(AnimationSprite *self, Transform *transform) {
|
void animation_sprite_draw(AnimationSprite *self, Transform *transform) {
|
||||||
const size_t frame_count = spritesheet_get_tile_count(self->sheet);
|
const size_t frame_count = spritesheet_get_tile_count(self->sheet);
|
||||||
const float time = game_time() - self->start_time;
|
const float time = game_time() - self->start_time;
|
||||||
|
|
||||||
size_t frame = (size_t)(time / self->frame_interval);
|
size_t frame = (size_t)(time / self->frame_interval);
|
||||||
|
|
||||||
switch(self->loop_mode) {
|
switch(self->loop_mode) {
|
||||||
|
case LoopMode_Stop:
|
||||||
|
if(frame >= frame_count)
|
||||||
|
frame = frame_count - 1;
|
||||||
case LoopMode_Hide:
|
case LoopMode_Hide:
|
||||||
if(frame >= frame_count)
|
if(frame >= frame_count)
|
||||||
return;
|
return;
|
||||||
|
@ -55,9 +71,6 @@ void animation_sprite_draw(AnimationSprite* self, Transform* transform) {
|
||||||
if(frame >= frame_count)
|
if(frame >= frame_count)
|
||||||
frame = frame_count - (frame - frame_count);
|
frame = frame_count - (frame - frame_count);
|
||||||
return;
|
return;
|
||||||
case LoopMode_Stop:
|
|
||||||
if(frame >= frame_count)
|
|
||||||
frame = frame_count - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite_set_spritesheet(self->sprite_target, self->sheet);
|
sprite_set_spritesheet(self->sprite_target, self->sheet);
|
||||||
|
@ -65,6 +78,17 @@ void animation_sprite_draw(AnimationSprite* self, Transform* transform) {
|
||||||
sprite_draw(self->sprite_target, *transform);
|
sprite_draw(self->sprite_target, *transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void animation_sprite_update_events(AnimationSprite *self) {
|
||||||
|
const float current_time = game_time() - self->start_time;
|
||||||
|
for(;self->event_index <= self->events.len; ++self->event_index) {
|
||||||
|
AnimationEvent *event = list_at_as(AnimationEvent, &self->events, self->event_index);
|
||||||
|
if(event->time < current_time)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
event->fn(event->target, event->arg.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float animation_sprite_get_length(AnimationSprite *self) {
|
float animation_sprite_get_length(AnimationSprite *self) {
|
||||||
return (float)spritesheet_get_tile_count(self->sheet) * self->frame_interval;
|
return (float)spritesheet_get_tile_count(self->sheet) * self->frame_interval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef _fencer_animation_sprite_h
|
#ifndef _fencer_animation_sprite_h
|
||||||
#define _fencer_animation_sprite_h
|
#define _fencer_animation_sprite_h
|
||||||
|
|
||||||
|
#include "drop.h"
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
#include "spritesheet.h"
|
#include "spritesheet.h"
|
||||||
|
|
||||||
|
@ -11,14 +12,26 @@ typedef enum AnimationSpriteLoopMode {
|
||||||
LoopMode_PingPong,
|
LoopMode_PingPong,
|
||||||
} AnimationSpriteLoopMode;
|
} AnimationSpriteLoopMode;
|
||||||
|
|
||||||
|
typedef void (*AnimationEventFn)(void *object, void *arg);
|
||||||
|
|
||||||
|
typedef struct AnimationEvent {
|
||||||
|
float time;
|
||||||
|
void *target;
|
||||||
|
Drop arg;
|
||||||
|
AnimationEventFn fn;
|
||||||
|
} AnimationEvent;
|
||||||
|
|
||||||
typedef struct AnimationSprite AnimationSprite;
|
typedef struct AnimationSprite AnimationSprite;
|
||||||
|
|
||||||
extern AnimationSprite* animation_sprite_new(Sprite* target_sprite, Spritesheet* sheet, float framerate, AnimationSpriteLoopMode loop_mode);
|
extern AnimationSprite *animation_sprite_new(Sprite *target_sprite, Spritesheet *sheet, float framerate, AnimationSpriteLoopMode loop_mode, AnimationEvent *events, size_t event_count);
|
||||||
extern void animation_sprite_destroy(AnimationSprite *self);
|
extern void animation_sprite_destroy(AnimationSprite *self);
|
||||||
|
|
||||||
|
extern void animation_sprite_reset(AnimationSprite *self);
|
||||||
extern void animation_sprite_play_from(AnimationSprite *self, float normalized_time);
|
extern void animation_sprite_play_from(AnimationSprite *self, float normalized_time);
|
||||||
extern void animation_sprite_draw(AnimationSprite *self, Transform *transform);
|
extern void animation_sprite_draw(AnimationSprite *self, Transform *transform);
|
||||||
|
|
||||||
|
extern void animation_sprite_update_events(AnimationSprite *self);
|
||||||
|
|
||||||
extern float animation_sprite_get_length(AnimationSprite *self);
|
extern float animation_sprite_get_length(AnimationSprite *self);
|
||||||
extern void animation_sprite_set_framerate(AnimationSprite *self, float framerate);
|
extern void animation_sprite_set_framerate(AnimationSprite *self, float framerate);
|
||||||
extern float animation_sprite_get_framerate(const AnimationSprite *self);
|
extern float animation_sprite_get_framerate(const AnimationSprite *self);
|
||||||
|
|
|
@ -75,9 +75,9 @@ Enemy* MakeEnemy() {
|
||||||
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
|
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
|
||||||
|
|
||||||
// load and configure animations
|
// load and configure animations
|
||||||
self->idleAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop);
|
self->idleAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop, NULL, 0);
|
||||||
self->walkAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 1.5f, LoopMode_Loop);
|
self->walkAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 1.5f, LoopMode_Loop, NULL, 0);
|
||||||
self->hurtAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Hurt.png", IVectorFrom(512)), 5.f, LoopMode_Stop);
|
self->hurtAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Hurt.png", IVectorFrom(512)), 5.f, LoopMode_Stop, NULL, 0);
|
||||||
self->behaviour = state_machine_init(self, EnemyIdle());
|
self->behaviour = state_machine_init(self, EnemyIdle());
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|
|
@ -93,6 +93,7 @@ Player* MakePlayer() {
|
||||||
.slide = NULL,
|
.slide = NULL,
|
||||||
|
|
||||||
.animationStateMachine = NULL,
|
.animationStateMachine = NULL,
|
||||||
|
.boxes = malloc(sizeof(Hurtbox) * 3),
|
||||||
|
|
||||||
.pushInputTimer = 0.f,
|
.pushInputTimer = 0.f,
|
||||||
.inputLog = list_from_type(PlayerInputFrame),
|
.inputLog = list_from_type(PlayerInputFrame),
|
||||||
|
@ -117,15 +118,15 @@ Player* MakePlayer() {
|
||||||
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
|
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
|
||||||
|
|
||||||
// load and configure animations
|
// load and configure animations
|
||||||
self->idle = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop);
|
self->idle = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop, NULL, 0);
|
||||||
self->walk = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 5.f, LoopMode_Loop);
|
self->walk = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 5.f, LoopMode_Loop, NULL, 0);
|
||||||
self->jump = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jumping.png", IVectorFrom(512)), 1.f, LoopMode_Stop);
|
self->jump = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jumping.png", IVectorFrom(512)), 1.f, LoopMode_Stop, NULL, 0);
|
||||||
self->jab_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_A.png", IVectorFrom(512)), 10.f, LoopMode_Stop);
|
self->jab_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_A.png", IVectorFrom(512)), 10.f, LoopMode_Stop, NULL, 0);
|
||||||
self->jab_b = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_B.png", IVectorFrom(512)), 10.f, LoopMode_Stop);
|
self->jab_b = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_B.png", IVectorFrom(512)), 10.f, LoopMode_Stop, NULL, 0);
|
||||||
self->kick_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Kick_A.png", IVectorFrom(512)), 12.f, LoopMode_Stop);
|
self->kick_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Kick_A.png", IVectorFrom(512)), 12.f, LoopMode_Stop, NULL, 0);
|
||||||
self->slash = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slash.png", IVectorFrom(512)), 12.f, LoopMode_Stop);
|
self->slash = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slash.png", IVectorFrom(512)), 12.f, LoopMode_Stop, NULL, 0);
|
||||||
self->air_heavy = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Air_Heavy.png", IVectorFrom(512)), 10.f, LoopMode_Stop);
|
self->air_heavy = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Air_Heavy.png", IVectorFrom(512)), 10.f, LoopMode_Stop, NULL, 0);
|
||||||
self->slide = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slide.png", IVectorFrom(512)), 1.f, LoopMode_Loop);
|
self->slide = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slide.png", IVectorFrom(512)), 1.f, LoopMode_Loop, NULL, 0);
|
||||||
|
|
||||||
self->animationStateMachine = state_machine_init(self, PlayerIdle());
|
self->animationStateMachine = state_machine_init(self, PlayerIdle());
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef FIGHT_PLAYER_H
|
#ifndef FIGHT_PLAYER_H
|
||||||
#define FIGHT_PLAYER_H
|
#define FIGHT_PLAYER_H
|
||||||
|
|
||||||
|
#include "Hurtbox.h"
|
||||||
#include "dictionary.h"
|
#include "dictionary.h"
|
||||||
#include "state_machine.h"
|
#include "state_machine.h"
|
||||||
#include "mirror.h"
|
#include "mirror.h"
|
||||||
|
@ -56,9 +57,9 @@ typedef struct Player {
|
||||||
AnimationSprite* slide;
|
AnimationSprite* slide;
|
||||||
|
|
||||||
StateMachine* animationStateMachine;
|
StateMachine* animationStateMachine;
|
||||||
|
Hurtbox *boxes;
|
||||||
|
|
||||||
AnimationSprite* currentAnimation;
|
AnimationSprite* currentAnimation;
|
||||||
|
|
||||||
float pushInputTimer;
|
float pushInputTimer;
|
||||||
List inputLog;
|
List inputLog;
|
||||||
PlayerInputFrame nextInputFrame;
|
PlayerInputFrame nextInputFrame;
|
||||||
|
|
Loading…
Reference in a new issue