Rework component addition/deletion procedure
Changelog: - Defer component updates as iterator invalidation can occur - Add new struct for this + queue on entity manager - Add new component: CLifeTimer - Basically a timer to live for entityscene_man
parent
a4900a001b
commit
c4d8256767
|
@ -7,7 +7,7 @@
|
||||||
#include "sc/queue/sc_queue.h"
|
#include "sc/queue/sc_queue.h"
|
||||||
|
|
||||||
#define N_TAGS 8
|
#define N_TAGS 8
|
||||||
#define N_COMPONENTS 11
|
#define N_COMPONENTS 12
|
||||||
#define MAX_COMP_POOL_SIZE 1024
|
#define MAX_COMP_POOL_SIZE 1024
|
||||||
typedef struct EntityManager EntityManager_t;
|
typedef struct EntityManager EntityManager_t;
|
||||||
typedef struct Entity Entity_t;
|
typedef struct Entity Entity_t;
|
||||||
|
@ -24,6 +24,7 @@ typedef enum ComponentEnum {
|
||||||
CHURTBOX_T,
|
CHURTBOX_T,
|
||||||
CSPRITE_T,
|
CSPRITE_T,
|
||||||
CMOVEABLE_T,
|
CMOVEABLE_T,
|
||||||
|
CLIFETIMER_T,
|
||||||
} ComponentEnum_t;
|
} ComponentEnum_t;
|
||||||
|
|
||||||
typedef enum MovementMode {
|
typedef enum MovementMode {
|
||||||
|
@ -94,6 +95,7 @@ typedef enum ContainerItem {
|
||||||
CONTAINER_DOWN_ARROW,
|
CONTAINER_DOWN_ARROW,
|
||||||
CONTAINER_COIN,
|
CONTAINER_COIN,
|
||||||
CONTAINER_BOMB,
|
CONTAINER_BOMB,
|
||||||
|
CONTAINER_EXPLOSION,
|
||||||
} ContainerItem_t;
|
} ContainerItem_t;
|
||||||
|
|
||||||
typedef enum ContainerMaterial {
|
typedef enum ContainerMaterial {
|
||||||
|
@ -119,6 +121,11 @@ typedef struct _CHurtbox_t {
|
||||||
uint8_t def;
|
uint8_t def;
|
||||||
} CHurtbox_t;
|
} CHurtbox_t;
|
||||||
|
|
||||||
|
typedef struct _CLifeTimer_t {
|
||||||
|
uint8_t timer;
|
||||||
|
uint8_t life_time;
|
||||||
|
} CLifeTimer_t;
|
||||||
|
|
||||||
// Credits to bedroomcoders.co.uk for this
|
// Credits to bedroomcoders.co.uk for this
|
||||||
typedef struct Sprite {
|
typedef struct Sprite {
|
||||||
Texture2D* texture;
|
Texture2D* texture;
|
||||||
|
@ -170,6 +177,22 @@ struct Entity {
|
||||||
EntityManager_t* manager;
|
EntityManager_t* manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EntityUpdateEvent
|
||||||
|
{
|
||||||
|
COMP_ADDTION,
|
||||||
|
COMP_DELETION,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntityUpdateEventInfo
|
||||||
|
{
|
||||||
|
unsigned long e_id;
|
||||||
|
ComponentEnum_t comp_type;
|
||||||
|
unsigned long c_id;
|
||||||
|
enum EntityUpdateEvent evt_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
sc_queue_def(struct EntityUpdateEventInfo, ent_evt);
|
||||||
|
|
||||||
struct EntityManager {
|
struct EntityManager {
|
||||||
// All fields are Read-Only
|
// All fields are Read-Only
|
||||||
struct sc_map_64v entities; // ent id : entity
|
struct sc_map_64v entities; // ent id : entity
|
||||||
|
@ -177,6 +200,7 @@ struct EntityManager {
|
||||||
struct sc_map_64v component_map[N_COMPONENTS]; // [{ent id: comp}, ...]
|
struct sc_map_64v component_map[N_COMPONENTS]; // [{ent id: comp}, ...]
|
||||||
struct sc_queue_uint to_add;
|
struct sc_queue_uint to_add;
|
||||||
struct sc_queue_uint to_remove;
|
struct sc_queue_uint to_remove;
|
||||||
|
struct sc_queue_ent_evt to_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_entity_manager(EntityManager_t* p_manager);
|
void init_entity_manager(EntityManager_t* p_manager);
|
||||||
|
|
|
@ -13,6 +13,7 @@ void init_entity_manager(EntityManager_t* p_manager)
|
||||||
}
|
}
|
||||||
sc_queue_init(&p_manager->to_add);
|
sc_queue_init(&p_manager->to_add);
|
||||||
sc_queue_init(&p_manager->to_remove);
|
sc_queue_init(&p_manager->to_remove);
|
||||||
|
sc_queue_init(&p_manager->to_update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_entity_manager(EntityManager_t* p_manager)
|
void update_entity_manager(EntityManager_t* p_manager)
|
||||||
|
@ -28,16 +29,14 @@ void update_entity_manager(EntityManager_t* p_manager)
|
||||||
if (!p_entity) continue;
|
if (!p_entity) continue;
|
||||||
for (size_t i = 0; i < N_COMPONENTS; ++i)
|
for (size_t i = 0; i < N_COMPONENTS; ++i)
|
||||||
{
|
{
|
||||||
if (p_entity->components[i] == MAX_COMP_POOL_SIZE) continue;
|
remove_component(p_entity, i);
|
||||||
|
|
||||||
free_component_to_mempool((ComponentEnum_t)i, p_entity->components[i]);
|
|
||||||
sc_map_del_64v(&p_manager->component_map[i], e_idx);
|
|
||||||
sc_map_del_64v(&p_manager->entities_map[p_entity->m_tag], e_idx);
|
|
||||||
}
|
}
|
||||||
|
sc_map_del_64v(&p_manager->entities_map[p_entity->m_tag], e_idx);
|
||||||
free_entity_to_mempool(e_idx);
|
free_entity_to_mempool(e_idx);
|
||||||
sc_map_del_64v(&p_manager->entities, e_idx);
|
sc_map_del_64v(&p_manager->entities, e_idx);
|
||||||
}
|
}
|
||||||
sc_queue_clear(&p_manager->to_remove);
|
sc_queue_clear(&p_manager->to_remove);
|
||||||
|
|
||||||
sc_queue_foreach (&p_manager->to_add, e_idx)
|
sc_queue_foreach (&p_manager->to_add, e_idx)
|
||||||
{
|
{
|
||||||
Entity_t *p_entity = get_entity_wtih_id(e_idx);
|
Entity_t *p_entity = get_entity_wtih_id(e_idx);
|
||||||
|
@ -45,6 +44,22 @@ void update_entity_manager(EntityManager_t* p_manager)
|
||||||
sc_map_put_64v(&p_manager->entities_map[p_entity->m_tag], e_idx, (void *)p_entity);
|
sc_map_put_64v(&p_manager->entities_map[p_entity->m_tag], e_idx, (void *)p_entity);
|
||||||
}
|
}
|
||||||
sc_queue_clear(&p_manager->to_add);
|
sc_queue_clear(&p_manager->to_add);
|
||||||
|
|
||||||
|
struct EntityUpdateEventInfo evt;
|
||||||
|
sc_queue_foreach (&p_manager->to_update, evt)
|
||||||
|
{
|
||||||
|
switch(evt.evt_type)
|
||||||
|
{
|
||||||
|
case COMP_ADDTION:
|
||||||
|
sc_map_put_64v(&p_manager->component_map[evt.comp_type], evt.e_id, get_component_wtih_id(evt.comp_type, evt.c_id));
|
||||||
|
break;
|
||||||
|
case COMP_DELETION:
|
||||||
|
sc_map_del_64v(&p_manager->component_map[evt.comp_type], evt.e_id);
|
||||||
|
free_component_to_mempool(evt.comp_type, evt.c_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sc_queue_clear(&p_manager->to_add);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_entity_manager(EntityManager_t* p_manager)
|
void clear_entity_manager(EntityManager_t* p_manager)
|
||||||
|
@ -72,6 +87,7 @@ void free_entity_manager(EntityManager_t* p_manager)
|
||||||
}
|
}
|
||||||
sc_queue_term(&p_manager->to_add);
|
sc_queue_term(&p_manager->to_add);
|
||||||
sc_queue_term(&p_manager->to_remove);
|
sc_queue_term(&p_manager->to_remove);
|
||||||
|
sc_queue_term(&p_manager->to_update);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity_t *add_entity(EntityManager_t* p_manager, unsigned int tag)
|
Entity_t *add_entity(EntityManager_t* p_manager, unsigned int tag)
|
||||||
|
@ -107,17 +123,15 @@ Entity_t* get_entity(EntityManager_t* p_manager, unsigned long id)
|
||||||
return p_entity;
|
return p_entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Components are not expected to be removed
|
|
||||||
// So, no need to extra steps to deal with iterator invalidation
|
|
||||||
void* add_component(Entity_t* p_entity, ComponentEnum_t comp_type)
|
void* add_component(Entity_t* p_entity, ComponentEnum_t comp_type)
|
||||||
{
|
{
|
||||||
unsigned long comp_type_idx = (unsigned long)comp_type;
|
|
||||||
unsigned long comp_idx = 0;
|
unsigned long comp_idx = 0;
|
||||||
void* p_comp = new_component_from_mempool(comp_type, &comp_idx);
|
void* p_comp = new_component_from_mempool(comp_type, &comp_idx);
|
||||||
if (p_comp)
|
if (p_comp)
|
||||||
{
|
{
|
||||||
p_entity->components[comp_type] = comp_idx;
|
p_entity->components[comp_type] = comp_idx;
|
||||||
sc_map_put_64v(&p_entity->manager->component_map[comp_type_idx], p_entity->m_id, p_comp);
|
struct EntityUpdateEventInfo evt = (struct EntityUpdateEventInfo){p_entity->m_id, comp_type, comp_idx, COMP_ADDTION};
|
||||||
|
sc_queue_add_last(&p_entity->manager->to_update, evt);
|
||||||
}
|
}
|
||||||
return p_comp;
|
return p_comp;
|
||||||
}
|
}
|
||||||
|
@ -125,15 +139,14 @@ void* add_component(Entity_t* p_entity, ComponentEnum_t comp_type)
|
||||||
void* get_component(Entity_t *p_entity, ComponentEnum_t comp_type)
|
void* get_component(Entity_t *p_entity, ComponentEnum_t comp_type)
|
||||||
{
|
{
|
||||||
unsigned long comp_type_idx = (unsigned long)comp_type;
|
unsigned long comp_type_idx = (unsigned long)comp_type;
|
||||||
void * p_comp = sc_map_get_64v(&p_entity->manager->component_map[comp_type_idx], p_entity->m_id);
|
unsigned long c_idx = p_entity->components[comp_type_idx];
|
||||||
if (!sc_map_found(&p_entity->manager->component_map[comp_type_idx])) return NULL;
|
if (c_idx == MAX_COMP_POOL_SIZE) return NULL;
|
||||||
return p_comp;
|
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, ComponentEnum_t comp_type)
|
||||||
{
|
{
|
||||||
unsigned long comp_type_idx = (unsigned long)comp_type;
|
|
||||||
if (p_entity->components[comp_type] == MAX_COMP_POOL_SIZE) return;
|
if (p_entity->components[comp_type] == MAX_COMP_POOL_SIZE) return;
|
||||||
sc_map_del_64v(&p_entity->manager->component_map[comp_type_idx], p_entity->m_id);
|
struct EntityUpdateEventInfo evt = (struct EntityUpdateEventInfo){p_entity->m_id, comp_type, p_entity->components[comp_type] , COMP_DELETION};
|
||||||
free_component_to_mempool(comp_type, p_entity->components[comp_type]);
|
sc_queue_add_last(&p_entity->manager->to_update, evt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ static CHitBoxes_t chitboxes_buffer[MAX_COMP_POOL_SIZE];
|
||||||
static CHurtbox_t churtbox_buffer[MAX_COMP_POOL_SIZE];
|
static CHurtbox_t churtbox_buffer[MAX_COMP_POOL_SIZE];
|
||||||
static CSprite_t csprite_buffer[MAX_COMP_POOL_SIZE];
|
static CSprite_t csprite_buffer[MAX_COMP_POOL_SIZE];
|
||||||
static CMoveable_t cmoveable_buffer[MAX_COMP_POOL_SIZE];
|
static CMoveable_t cmoveable_buffer[MAX_COMP_POOL_SIZE];
|
||||||
|
static CLifeTimer_t clifetimer_buffer[MAX_COMP_POOL_SIZE];
|
||||||
|
|
||||||
typedef struct ULongCircBuffer {
|
typedef struct ULongCircBuffer {
|
||||||
unsigned long* buffer; // data buffer
|
unsigned long* buffer; // data buffer
|
||||||
|
@ -88,6 +89,7 @@ static MemPool_t comp_mempools[N_COMPONENTS] = {
|
||||||
{churtbox_buffer, MAX_COMP_POOL_SIZE, sizeof(CHurtbox_t), NULL, {0}},
|
{churtbox_buffer, MAX_COMP_POOL_SIZE, sizeof(CHurtbox_t), NULL, {0}},
|
||||||
{csprite_buffer, MAX_COMP_POOL_SIZE, sizeof(CSprite_t), NULL, {0}},
|
{csprite_buffer, MAX_COMP_POOL_SIZE, sizeof(CSprite_t), NULL, {0}},
|
||||||
{cmoveable_buffer, MAX_COMP_POOL_SIZE, sizeof(CMoveable_t), NULL, {0}},
|
{cmoveable_buffer, MAX_COMP_POOL_SIZE, sizeof(CMoveable_t), NULL, {0}},
|
||||||
|
{clifetimer_buffer, MAX_COMP_POOL_SIZE, sizeof(CLifeTimer_t), NULL, {0}},
|
||||||
};
|
};
|
||||||
static MemPool_t ent_mempool = {
|
static MemPool_t ent_mempool = {
|
||||||
.buffer = entity_buffer,
|
.buffer = entity_buffer,
|
||||||
|
|
Loading…
Reference in New Issue