From 056b50c43108c696dae540f9ef630f9266cfc493 Mon Sep 17 00:00:00 2001 From: En Yi Date: Mon, 19 Aug 2024 18:26:08 +0800 Subject: [PATCH] Separate out component memory pools definition Changelog: - Refactor the EC header files to put struct in more sensible locations: - Sprite and Particle Emitter + Configs are now assets, as they should be - Components type are now unsigned int, thus it is not sensitive to any component enums - Components enums are now pure index store. There are two sets of components: Basic for engine use, Extended for game-specific ones - Component memory pools are now defined on outside of engine. Majority of the components will be game-specific, so it should be on the game to define the components and the mempools for all of them. --- engine/EC.h | 257 +++++++----------------------------------- engine/assets.h | 32 +++++- engine/entManager.c | 6 +- engine/mempool.c | 6 +- engine/mempool.h | 7 +- engine/particle_sys.h | 21 +--- scenes/components.h | 173 ++++++++++++++++++++++++++++ scenes/engine_impl.c | 2 + scenes/ent_impl.h | 2 +- 9 files changed, 262 insertions(+), 244 deletions(-) create mode 100644 scenes/components.h diff --git a/engine/EC.h b/engine/EC.h index 60b28ea..1873648 100644 --- a/engine/EC.h +++ b/engine/EC.h @@ -11,36 +11,39 @@ typedef struct EntityManager EntityManager_t; typedef struct Entity Entity_t; -typedef enum ComponentEnum { - CBBOX_COMP_T = 0, - CTRANSFORM_COMP_T, - CTILECOORD_COMP_T, - CMOVEMENTSTATE_T, - CJUMP_COMP_T, - CPLAYERSTATE_T, - CCONTAINER_T, - CHITBOXES_T, - CHURTBOX_T, - CSPRITE_T, - CMOVEABLE_T, - CLIFETIMER_T, - CWATERRUNNER_T, - CAIRTIMER_T, - CEMITTER_T, -} ComponentEnum_t; +typedef enum AnchorPoint { + AP_TOP_LEFT, + AP_TOP_CENTER, + AP_TOP_RIGHT, + AP_MID_LEFT, + AP_MID_CENTER, + AP_MID_RIGHT, + AP_BOT_LEFT, + AP_BOT_CENTER, + AP_BOT_RIGHT, +} AnchorPoint_t; typedef enum MovementMode { REGULAR_MOVEMENT = 0, KINEMATIC_MOVEMENT, }MovementMode_t; -typedef struct _CBBox_t { - Vector2 size; - Vector2 offset; - Vector2 half_size; - bool solid; - bool fragile; -} CBBox_t; +/** Fundamental components: +// - Transform +// - BBox +// - TileCoords +**/ +/** The component enums are purely a index store. Here, there are 3 basic component, that is necessary for the engine to function (mostly collisions) + * To extend the component list, define another set of enums as pure integer store and begin the enum at N_BASIC_COMPS + * These integers are also used by the component mempool as indices. Thus, the mempool must have the first 3 components as the basic components + **/ +#define N_BASIC_COMPS 3 + +enum BasicComponentEnum { + CBBOX_COMP_T = 0, + CTRANSFORM_COMP_T, + CTILECOORD_COMP_T, +}; typedef struct _CTransform_t { Vector2 prev_position; @@ -55,194 +58,13 @@ typedef struct _CTransform_t { bool active; } CTransform_t; -typedef struct _CMovementState_t { - uint8_t ground_state; - uint8_t water_state; - uint8_t x_dir; - float water_overlap; -} CMovementState_t; - -// This is to store the occupying tiles -// Limits to store 4 tiles at a tile, -// Thus the size of the entity cannot be larger than the tile -typedef struct _CTileCoord_t { - unsigned int tiles[8]; - unsigned int n_tiles; -} CTileCoord_t; - -typedef struct _CJump_t { - int jump_speed; - uint8_t jumps; - uint8_t max_jumps; - uint8_t coyote_timer; - bool jumped; - bool jump_ready; - bool short_hop; - bool jump_released; -} CJump_t; - -typedef enum PlayerState { - GROUNDED, - AIR, -} PlayerState_t; - -typedef struct _CPlayerState_t { - Vector2 player_dir; - uint8_t jump_pressed; - uint8_t is_crouch; - bool ladder_state; - bool locked; // Whether to respond to inputs -} CPlayerState_t; - -typedef enum ContainerItem { - CONTAINER_EMPTY, - CONTAINER_LEFT_ARROW, - CONTAINER_RIGHT_ARROW, - CONTAINER_UP_ARROW, - CONTAINER_DOWN_ARROW, - CONTAINER_COIN, - CONTAINER_BOMB, - CONTAINER_EXPLOSION, -} ContainerItem_t; - -typedef enum ContainerMaterial { - WOODEN_CONTAINER, - METAL_CONTAINER, -} ContainerMaterial_t; - -typedef struct _CContainer_t { - ContainerMaterial_t material; - ContainerItem_t item; -} CContainer_t; - -typedef struct _CHitBoxes_t { - Rectangle boxes[2]; - uint8_t n_boxes; - uint8_t atk; - bool one_hit; -} CHitBoxes_t; - -typedef struct _CHurtbox_t { - Vector2 offset; +typedef struct _CBBox_t { Vector2 size; - uint8_t def; - unsigned int damage_src; -} CHurtbox_t; - -typedef struct _CLifeTimer_t { - float life_time; -} CLifeTimer_t; - -typedef struct _CAirTimer_t { - float max_ftimer; - float curr_ftimer; - float decay_rate; - uint8_t max_count; - uint8_t curr_count; -} CAirTimer_t; - -typedef struct _BFSTile { - int32_t to; - int32_t from; - bool reachable; -}BFSTile_t; - -typedef struct _BFSTileMap { - BFSTile_t* tilemap; - int32_t width; - int32_t height; - int32_t len; -}BFSTileMap_t; - -typedef enum _WaterRunnerState -{ - BFS_RESET = 0, - BFS_START, - LOWEST_POINT_SEARCH, - LOWEST_POINT_MOVEMENT, - REACHABILITY_SEARCH, - SCANLINE_FILL, - FILL_COMPLETE, -}WaterRunerState_t; - -typedef struct _CWaterRunner { - BFSTileMap_t bfs_tilemap; - WaterRunerState_t state; - struct sc_queue_32 bfs_queue; - bool* visited; - int32_t current_tile; - int32_t target_tile; - int32_t fill_idx; - int16_t fill_range[2]; - uint8_t movement_delay; - int8_t movement_speed; - int16_t counter; - float fractional; -}CWaterRunner_t; - -// Credits to bedroomcoders.co.uk for this -typedef struct Sprite { - Texture2D* texture; - Vector2 frame_size; - Vector2 origin; // TL of the frame - Vector2 anchor; // Where transformation anchors on - uint8_t frame_per_row; - int frame_count; - int speed; - char* name; -} Sprite_t; - -typedef unsigned int (*sprite_transition_func_t)(Entity_t *ent); // Transition requires knowledge of the entity - -typedef enum AnchorPoint { - AP_TOP_LEFT, - AP_TOP_CENTER, - AP_TOP_RIGHT, - AP_MID_LEFT, - AP_MID_CENTER, - AP_MID_RIGHT, - AP_BOT_LEFT, - AP_BOT_CENTER, - AP_BOT_RIGHT, -} AnchorPoint_t; - -typedef struct _SpriteRenderInfo -{ - Sprite_t* sprite; Vector2 offset; - AnchorPoint_t src_anchor; - AnchorPoint_t dest_anchor; -} SpriteRenderInfo_t; - -typedef struct _CSprite_t { - SpriteRenderInfo_t* sprites; - sprite_transition_func_t transition_func; - unsigned int current_idx; - bool flip_x; - bool flip_y; - bool pause; - int current_frame; - float fractional; - float rotation; // Degree - float rotation_speed; // Degree / s - int elapsed; - Vector2 offset; - Color colour; -} CSprite_t; - -typedef struct _CMoveable_t { - uint16_t move_speed; - Vector2 prev_pos; - Vector2 target_pos; - bool gridmove; -} CMoveable_t; - -typedef uint16_t EmitterHandle; -typedef struct _CEmitter_t -{ - EmitterHandle handle; - Vector2 offset; -} CEmitter_t; + Vector2 half_size; + bool solid; + bool fragile; +} CBBox_t; static inline void set_bbox(CBBox_t* p_bbox, unsigned int x, unsigned int y) { @@ -251,6 +73,13 @@ static inline void set_bbox(CBBox_t* p_bbox, unsigned int x, unsigned int y) p_bbox->half_size.x = (unsigned int)(x / 2); p_bbox->half_size.y = (unsigned int)(y / 2); } +// This is to store the occupying tiles +// Limits to store 4 tiles at a tile, +// Thus the size of the entity cannot be larger than the tile +typedef struct _CTileCoord_t { + unsigned int tiles[8]; + unsigned int n_tiles; +} CTileCoord_t; struct Entity { Vector2 position; @@ -271,7 +100,7 @@ enum EntityUpdateEvent struct EntityUpdateEventInfo { unsigned long e_id; - ComponentEnum_t comp_type; + unsigned int comp_type; unsigned long c_id; enum EntityUpdateEvent evt_type; }; @@ -299,8 +128,8 @@ Entity_t* add_entity(EntityManager_t* p_manager, unsigned int tag); void remove_entity(EntityManager_t* p_manager, unsigned long id); Entity_t *get_entity(EntityManager_t* p_manager, unsigned long id); -void* add_component(Entity_t *entity, ComponentEnum_t comp_type); -void* get_component(Entity_t *entity, ComponentEnum_t comp_type); -void remove_component(Entity_t* entity, ComponentEnum_t comp_type); +void* add_component(Entity_t *entity, unsigned int comp_type); +void* get_component(Entity_t *entity, unsigned int comp_type); +void remove_component(Entity_t* entity, unsigned int comp_type); #endif // __ENTITY_H diff --git a/engine/assets.h b/engine/assets.h index ab50a87..920ee49 100644 --- a/engine/assets.h +++ b/engine/assets.h @@ -4,7 +4,7 @@ #include "EC.h" #include "raylib.h" #include "rres.h" -#include "particle_sys.h" + #define N_ASSETS_TYPE 6 typedef enum AssetType { @@ -16,6 +16,24 @@ typedef enum AssetType AST_EMITTER_CONF, }AssetType_t; +typedef enum PartEmitterType +{ + EMITTER_UNKNOWN = 0, + EMITTER_BURST, + EMITTER_STREAM, +} PartEmitterType_t; + +typedef struct EmitterConfig +{ + float launch_range[2]; + float speed_range[2]; + float angle_range[2]; + float rotation_range[2]; + float particle_lifetime[2]; + float initial_spawn_delay; + PartEmitterType_t type; + bool one_shot; +}EmitterConfig_t; typedef struct Assets { @@ -49,6 +67,18 @@ typedef struct LevelPack LevelMap_t* levels; }LevelPack_t; +// Credits to bedroomcoders.co.uk for this +typedef struct Sprite { + Texture2D* texture; + Vector2 frame_size; + Vector2 origin; // TL of the frame + Vector2 anchor; // Where transformation anchors on + uint8_t frame_per_row; + int frame_count; + int speed; + char* name; +} Sprite_t; + typedef struct RresFileInfo { rresCentralDir dir; diff --git a/engine/entManager.c b/engine/entManager.c index 89a6d61..8213760 100644 --- a/engine/entManager.c +++ b/engine/entManager.c @@ -144,7 +144,7 @@ Entity_t* get_entity(EntityManager_t* p_manager, unsigned long id) return p_entity; } -void* add_component(Entity_t* p_entity, ComponentEnum_t comp_type) +void* add_component(Entity_t* p_entity, unsigned int comp_type) { if (p_entity->components[comp_type] == MAX_COMP_POOL_SIZE) { @@ -163,7 +163,7 @@ void* add_component(Entity_t* p_entity, ComponentEnum_t comp_type) return get_component(p_entity, comp_type); } -void* get_component(Entity_t *p_entity, ComponentEnum_t comp_type) +void* get_component(Entity_t *p_entity, unsigned int comp_type) { unsigned long comp_type_idx = (unsigned long)comp_type; unsigned long c_idx = p_entity->components[comp_type_idx]; @@ -171,7 +171,7 @@ void* get_component(Entity_t *p_entity, ComponentEnum_t comp_type) return get_component_wtih_id(comp_type, c_idx); } -void remove_component(Entity_t *p_entity, ComponentEnum_t comp_type) +void remove_component(Entity_t *p_entity, unsigned int comp_type) { if (p_entity->components[comp_type] == MAX_COMP_POOL_SIZE) return; struct EntityUpdateEventInfo evt = (struct EntityUpdateEventInfo){p_entity->m_id, comp_type, p_entity->components[comp_type] , COMP_DELETION}; diff --git a/engine/mempool.c b/engine/mempool.c index 8308220..b9d57fc 100644 --- a/engine/mempool.c +++ b/engine/mempool.c @@ -134,7 +134,7 @@ void free_entity_to_mempool(unsigned long idx) } } -void* new_component_from_mempool(ComponentEnum_t comp_type, unsigned long* idx) +void* new_component_from_mempool(unsigned int comp_type, unsigned long* idx) { void* comp = NULL; assert(comp_type < N_COMPONENTS); @@ -147,7 +147,7 @@ void* new_component_from_mempool(ComponentEnum_t comp_type, unsigned long* idx) return comp; } -void* get_component_wtih_id(ComponentEnum_t comp_type, unsigned long idx) +void* get_component_wtih_id(unsigned int comp_type, unsigned long idx) { void * comp = NULL; assert(comp_type < N_COMPONENTS); @@ -158,7 +158,7 @@ void* get_component_wtih_id(ComponentEnum_t comp_type, unsigned long idx) return comp; } -void free_component_to_mempool(ComponentEnum_t comp_type, unsigned long idx) +void free_component_to_mempool(unsigned int comp_type, unsigned long idx) { assert(comp_type < N_COMPONENTS); // This just free the component from the memory pool diff --git a/engine/mempool.h b/engine/mempool.h index 13a0d7a..040aec8 100644 --- a/engine/mempool.h +++ b/engine/mempool.h @@ -20,15 +20,16 @@ typedef struct MemPool { ULongCircBuffer_t free_list; } MemPool_t; +// Game needs to implement this somewhere extern MemPool_t comp_mempools[N_COMPONENTS]; Entity_t* new_entity_from_mempool(unsigned long* e_idx_ptr); Entity_t* get_entity_wtih_id(unsigned long idx); void free_entity_to_mempool(unsigned long idx); -void* new_component_from_mempool(ComponentEnum_t comp_type, unsigned long* idx); -void* get_component_wtih_id(ComponentEnum_t comp_type, unsigned long idx); -void free_component_to_mempool(ComponentEnum_t comp_type, unsigned long idx); +void* new_component_from_mempool(unsigned int comp_type, unsigned long* idx); +void* get_component_wtih_id(unsigned int comp_type, unsigned long idx); +void free_component_to_mempool(unsigned int comp_type, unsigned long idx); void print_mempool_stats(char* buffer); uint32_t get_num_of_free_entities(void); diff --git a/engine/particle_sys.h b/engine/particle_sys.h index 591d948..eda76f0 100644 --- a/engine/particle_sys.h +++ b/engine/particle_sys.h @@ -3,16 +3,11 @@ #include "raylib.h" #include "engine_conf.h" #include "sc_queue.h" -#include "EC.h" +#include "assets.h" #include #include -typedef enum PartEmitterType -{ - EMITTER_UNKNOWN = 0, - EMITTER_BURST, - EMITTER_STREAM, -} PartEmitterType_t; +typedef uint16_t EmitterHandle; typedef struct Particle { @@ -32,18 +27,6 @@ typedef struct ParticleEmitter ParticleEmitter_t; typedef void (*particle_update_func_t)(Particle_t* part, void* user_data, float delta_time); typedef bool (*emitter_check_func_t)(const ParticleEmitter_t* emitter, float delta_time); -typedef struct EmitterConfig -{ - float launch_range[2]; - float speed_range[2]; - float angle_range[2]; - float rotation_range[2]; - float particle_lifetime[2]; - float initial_spawn_delay; - PartEmitterType_t type; - bool one_shot; -}EmitterConfig_t; - struct ParticleEmitter { const EmitterConfig_t* config; diff --git a/scenes/components.h b/scenes/components.h new file mode 100644 index 0000000..354523f --- /dev/null +++ b/scenes/components.h @@ -0,0 +1,173 @@ +#include "EC.h" +#include "particle_sys.h" // includes assets + +enum ComponentEnum { + CMOVEMENTSTATE_T = N_BASIC_COMPS, + CJUMP_COMP_T, + CPLAYERSTATE_T, + CCONTAINER_T, + CHITBOXES_T, + CHURTBOX_T, + CSPRITE_T, + CMOVEABLE_T, + CLIFETIMER_T, + CWATERRUNNER_T, + CAIRTIMER_T, + CEMITTER_T, +}; + +typedef struct _CMovementState_t { + uint8_t ground_state; + uint8_t water_state; + uint8_t x_dir; + float water_overlap; +} CMovementState_t; + +typedef struct _CJump_t { + int jump_speed; + uint8_t jumps; + uint8_t max_jumps; + uint8_t coyote_timer; + bool jumped; + bool jump_ready; + bool short_hop; + bool jump_released; +} CJump_t; + +typedef enum PlayerState { + GROUNDED, + AIR, +} PlayerState_t; + +typedef struct _CPlayerState_t { + Vector2 player_dir; + uint8_t jump_pressed; + uint8_t is_crouch; + bool ladder_state; + bool locked; // Whether to respond to inputs +} CPlayerState_t; + +typedef enum ContainerItem { + CONTAINER_EMPTY, + CONTAINER_LEFT_ARROW, + CONTAINER_RIGHT_ARROW, + CONTAINER_UP_ARROW, + CONTAINER_DOWN_ARROW, + CONTAINER_COIN, + CONTAINER_BOMB, + CONTAINER_EXPLOSION, +} ContainerItem_t; + +typedef enum ContainerMaterial { + WOODEN_CONTAINER, + METAL_CONTAINER, +} ContainerMaterial_t; + +typedef struct _CContainer_t { + ContainerMaterial_t material; + ContainerItem_t item; +} CContainer_t; + +typedef struct _CHitBoxes_t { + Rectangle boxes[2]; + uint8_t n_boxes; + uint8_t atk; + bool one_hit; +} CHitBoxes_t; + +typedef struct _CHurtbox_t { + Vector2 offset; + Vector2 size; + uint8_t def; + unsigned int damage_src; +} CHurtbox_t; + +typedef struct _CLifeTimer_t { + float life_time; +} CLifeTimer_t; + +typedef struct _CAirTimer_t { + float max_ftimer; + float curr_ftimer; + float decay_rate; + uint8_t max_count; + uint8_t curr_count; +} CAirTimer_t; + +typedef struct _BFSTile { + int32_t to; + int32_t from; + bool reachable; +}BFSTile_t; + +typedef struct _BFSTileMap { + BFSTile_t* tilemap; + int32_t width; + int32_t height; + int32_t len; +}BFSTileMap_t; + +typedef enum _WaterRunnerState +{ + BFS_RESET = 0, + BFS_START, + LOWEST_POINT_SEARCH, + LOWEST_POINT_MOVEMENT, + REACHABILITY_SEARCH, + SCANLINE_FILL, + FILL_COMPLETE, +}WaterRunerState_t; + +typedef struct _CWaterRunner { + BFSTileMap_t bfs_tilemap; + WaterRunerState_t state; + struct sc_queue_32 bfs_queue; + bool* visited; + int32_t current_tile; + int32_t target_tile; + int32_t fill_idx; + int16_t fill_range[2]; + uint8_t movement_delay; + int8_t movement_speed; + int16_t counter; + float fractional; +}CWaterRunner_t; + +typedef unsigned int (*sprite_transition_func_t)(Entity_t *ent); // Transition requires knowledge of the entity + +typedef struct _SpriteRenderInfo +{ + Sprite_t* sprite; + Vector2 offset; + AnchorPoint_t src_anchor; + AnchorPoint_t dest_anchor; +} SpriteRenderInfo_t; + +typedef struct _CSprite_t { + SpriteRenderInfo_t* sprites; + sprite_transition_func_t transition_func; + unsigned int current_idx; + bool flip_x; + bool flip_y; + bool pause; + int current_frame; + float fractional; + float rotation; // Degree + float rotation_speed; // Degree / s + int elapsed; + Vector2 offset; + Color colour; +} CSprite_t; + +typedef struct _CMoveable_t { + uint16_t move_speed; + Vector2 prev_pos; + Vector2 target_pos; + bool gridmove; +} CMoveable_t; + +typedef struct _CEmitter_t +{ + EmitterHandle handle; + Vector2 offset; +} CEmitter_t; diff --git a/scenes/engine_impl.c b/scenes/engine_impl.c index 0405942..27f75dd 100644 --- a/scenes/engine_impl.c +++ b/scenes/engine_impl.c @@ -1,4 +1,6 @@ #include "mempool.h" +#include "components.h" + // Static allocate buffers static CBBox_t bbox_buffer[MAX_COMP_POOL_SIZE]; static CTransform_t ctransform_buffer[MAX_COMP_POOL_SIZE]; diff --git a/scenes/ent_impl.h b/scenes/ent_impl.h index 1ee069f..826eefa 100644 --- a/scenes/ent_impl.h +++ b/scenes/ent_impl.h @@ -1,7 +1,7 @@ #ifndef __ENT_IMPL_H #define __ENT_IMPL_H -#include "assets.h" #include "assets_tag.h" +#include "components.h" bool init_player_creation(const char* info_file, Assets_t* assets); bool init_player_creation_rres(const char* rres_file, const char* file, Assets_t* assets);