From 82b8a3b9889703ee769ed1dfa507aea9f8026dcc Mon Sep 17 00:00:00 2001 From: En Yi Date: Sat, 18 Mar 2023 13:55:55 +0800 Subject: [PATCH] Implement simple animation system Changelog: - Add sprite map for player - Add an animation system - Add a placeholder player sprite transition function --- engine/CMakeLists.txt | 1 + engine/EC/components.h | 5 +++++ engine/assets_maps.c | 8 ++++++++ engine/assets_maps.h | 13 +++++++++++++ engine/editor_scene.c | 4 ++++ engine/game_systems.c | 39 +++++++++++++++++++++++++++++++++++++++ engine/game_systems.h | 3 +++ 7 files changed, 73 insertions(+) create mode 100644 engine/assets_maps.c create mode 100644 engine/assets_maps.h diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 49968f6..55fe9e3 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(EC) add_library(lib_scenes STATIC engine.c assets.c + assets_maps.c editor_scene.c menu_scene.c game_systems.c diff --git a/engine/EC/components.h b/engine/EC/components.h index 88a746c..5041eeb 100644 --- a/engine/EC/components.h +++ b/engine/EC/components.h @@ -2,6 +2,7 @@ #define __COMPONENTS_H #include "raylib.h" #include +#include "entity.h" // TODO: Look at sc to use macros to auto generate functions #define N_COMPONENTS 10 @@ -125,10 +126,14 @@ typedef struct Sprite char* name; }Sprite_t; +typedef unsigned int (*sprite_transition_func_t)(Entity_t *ent); // Transition requires knowledge of the entity typedef struct _CSprite_t { + const char * const *sprites_map; //Array of all sprite names associated Sprite_t* sprite; + sprite_transition_func_t transition_func; Vector2 offset; + unsigned int current_idx; }CSprite_t; static inline void set_bbox(CBBox_t* p_bbox, unsigned int x, unsigned int y) diff --git a/engine/assets_maps.c b/engine/assets_maps.c new file mode 100644 index 0000000..ecd5099 --- /dev/null +++ b/engine/assets_maps.c @@ -0,0 +1,8 @@ +#include "assets_maps.h" + + +const char * const player_sprite_map[N_PLAYER_SPRITES] = +{ + "plr_stand", + "plr_run", +}; diff --git a/engine/assets_maps.h b/engine/assets_maps.h new file mode 100644 index 0000000..7accbbd --- /dev/null +++ b/engine/assets_maps.h @@ -0,0 +1,13 @@ +#ifndef __ASSETS_MAPS_H +#define __ASSETS_MAPS_H + +#define N_PLAYER_SPRITES 2 +enum PlayerSpriteEnum +{ + SPR_PLAYER_STAND = 0, + SPR_PLAYER_RUN +}; + +extern const char * const player_sprite_map[N_PLAYER_SPRITES]; + +#endif // __ASSETS_MAPS_H diff --git a/engine/editor_scene.c b/engine/editor_scene.c index ddbb321..be44a0c 100644 --- a/engine/editor_scene.c +++ b/engine/editor_scene.c @@ -1,6 +1,7 @@ #include "scene_impl.h" #include "game_systems.h" #include "constants.h" +#include "assets_maps.h" #include "raylib.h" #include "raymath.h" #include @@ -212,6 +213,8 @@ static void spawn_player(Scene_t *scene) }; CSprite_t* p_cspr = add_component(&scene->ent_manager, p_ent, CSPRITE_T); p_cspr->sprite = get_sprite(&scene->engine->assets, "plr_stand"); + p_cspr->sprites_map = player_sprite_map; + p_cspr->transition_func = &player_sprite_transition_func; } static void toggle_block_system(Scene_t *scene) @@ -336,6 +339,7 @@ void init_level_scene(LevelScene_t *scene) //sc_array_add(&scene->scene.systems, &update_tilemap_system); sc_array_add(&scene->scene.systems, &state_transition_update_system); sc_array_add(&scene->scene.systems, &player_ground_air_transition_system); + sc_array_add(&scene->scene.systems, &sprite_animation_system); sc_array_add(&scene->scene.systems, &toggle_block_system); // This avoid graphical glitch, not essential diff --git a/engine/game_systems.c b/engine/game_systems.c index ee3671d..e7ab286 100644 --- a/engine/game_systems.c +++ b/engine/game_systems.c @@ -1,6 +1,7 @@ #include "game_systems.h" #include "AABB.h" #include "constants.h" +#include "assets_maps.h" #include static const Vector2 TILE_SZ = {TILE_SIZE, TILE_SIZE}; @@ -888,6 +889,39 @@ void hitbox_update_system(Scene_t *scene) } } +void sprite_animation_system(Scene_t *scene) +{ + unsigned int ent_idx; + CSprite_t* p_cspr; + sc_map_foreach(&scene->ent_manager.component_map[CSPRITE_T], ent_idx, p_cspr) + { + Entity_t *p_ent = get_entity(&scene->ent_manager, ent_idx); + // Update animation state + if (p_cspr->transition_func != NULL) + { + unsigned int spr_idx = p_cspr->transition_func(p_ent); + if (p_cspr->current_idx != spr_idx) + { + Sprite_t* new_spr = get_sprite(&scene->engine->assets, p_cspr->sprites_map[spr_idx]); + if (new_spr != NULL) + { + p_cspr->sprite = new_spr; + p_cspr->current_idx = spr_idx; + p_cspr->sprite->current_frame = 0; + } + } + } + // Animate it (handle frame count) + p_cspr->sprite->elapsed++; + if (p_cspr->sprite->elapsed == p_cspr->sprite->speed) + { + p_cspr->sprite->current_frame++; + p_cspr->sprite->current_frame %= p_cspr->sprite->frame_count; + p_cspr->sprite->elapsed = 0; + } + } +} + void init_level_scene_data(LevelSceneData_t *data) { sc_map_init_32(&data->collision_events, 128, 0); @@ -897,3 +931,8 @@ void term_level_scene_data(LevelSceneData_t *data) { sc_map_term_32(&data->collision_events); } + +unsigned int player_sprite_transition_func(Entity_t* ent) +{ + return SPR_PLAYER_RUN; +} diff --git a/engine/game_systems.h b/engine/game_systems.h index cdeb67c..038ec7d 100644 --- a/engine/game_systems.h +++ b/engine/game_systems.h @@ -14,4 +14,7 @@ void player_ground_air_transition_system(Scene_t* scene); void state_transition_update_system(Scene_t *scene); void update_tilemap_system(Scene_t *scene); void hitbox_update_system(Scene_t *scene); +void sprite_animation_system(Scene_t *scene); + +unsigned int player_sprite_transition_func(Entity_t* ent); #endif // __GAME_SYSTEMS_H