basics of ecs written, working on query, needs testing
This commit is contained in:
parent
ba09aff914
commit
c078ce907f
2 changed files with 205 additions and 16 deletions
|
|
@ -5,6 +5,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "arc/std/array.h"
|
||||
#include "arc/std/bool.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
|
|
@ -17,6 +19,14 @@ typedef struct ARC_EntitySystem ARC_EntitySystem;
|
|||
*/
|
||||
typedef uint32_t ARC_Entity;
|
||||
|
||||
/**
|
||||
* @brief an entity component system type
|
||||
*/
|
||||
typedef enum ARC_EntityFlags {
|
||||
ARC_ENTITY_DEAD = 0,
|
||||
ARC_ENTITY_ALIVE = 1
|
||||
} ARC_EntityFlags;
|
||||
|
||||
/**
|
||||
* @brief an entity component system type
|
||||
*/
|
||||
|
|
@ -35,15 +45,51 @@ void ARC_EntitySystem_Create(ARC_EntitySystem **entitySystem);
|
|||
/**
|
||||
* @brief destroys an ARC_EntitySystem
|
||||
*
|
||||
* @param[in] vector ARC_EntitySystem to free
|
||||
* @param[in] entitySystem ARC_EntitySystem to free
|
||||
*/
|
||||
void ARC_EntitySystem_Destroy(ARC_EntitySystem *entitySystem);
|
||||
|
||||
void ARC_EntitySystem_RegisterComponent(ARC_EntitySystem *entitySystem, uint32_t componentSize);
|
||||
/**
|
||||
* @brief registers space for a component and an id for the compenent within the entity system
|
||||
*
|
||||
* @note this function will set arc_errno if the components run out of space
|
||||
*
|
||||
* @param[in] entitySystem the entity system to register the component to
|
||||
* @param[in] componentSize the size of the component to register
|
||||
*
|
||||
* @return an id for for the component
|
||||
*/
|
||||
uint32_t ARC_EntitySystem_RegisterComponent(ARC_EntitySystem *entitySystem, uint32_t componentSize);
|
||||
|
||||
//void ARC_EntitySystem_RunSystem(ARC_EntitySystem *entitySystem, ARC_Component component);
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
ARC_Entity ARC_EntitySystem_InitEntity(ARC_EntitySystem *entitySystem);
|
||||
|
||||
void ARC_EntitySystem_Run(ARC_EntitySystem *entitySystem);
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
void ARC_EntitySystem_ReleaseEntity(ARC_EntitySystem *entitySystem, ARC_Entity entity);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
void ARC_EntitySystem_AddComponent(ARC_EntitySystem *entitySystem, ARC_Entity entity, ARC_EntityComponent component, void *data);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
ARC_Bool ARC_EntitySystem_HasComponent(ARC_EntitySystem *entitySystem, ARC_Entity entity, ARC_EntityComponent component);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
void *ARC_EntitySystem_GetComponentData(ARC_EntitySystem *entitySystem, ARC_Entity entity, ARC_EntityComponent component);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
ARC_Array ARC_EntitySystem_QueryComponentsData(ARC_EntitySystem *entitySystem, uint32_t components);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
167
src/std/entity.c
167
src/std/entity.c
|
|
@ -1,31 +1,174 @@
|
|||
#include "arc/std/entity.h"
|
||||
#include "arc/std/array.h"
|
||||
#include "arc/std/errno.h"
|
||||
#include "arc/std/bool.h"
|
||||
#include "arc/std/vector.h"
|
||||
#include "arc/std/vector/inline.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//TODO: might want to change how vector holds data for speed
|
||||
struct ARC_EntitySystem {
|
||||
ARC_Vector *flagVector;
|
||||
ARC_Vector *maskVector;
|
||||
//entity data
|
||||
ARC_VectorInline *flagVector;
|
||||
ARC_VectorInline *maskVector;
|
||||
|
||||
void *data;
|
||||
//component data
|
||||
ARC_VectorInline *offsetVector;
|
||||
ARC_VectorInline *sizeVector;
|
||||
|
||||
//stored component data
|
||||
ARC_VectorInline *data;
|
||||
|
||||
//TODO: this would probs be better to use a queue
|
||||
ARC_VectorInline *freeEntities;
|
||||
};
|
||||
|
||||
ARC_Bool ARC_EntitySystem_VectorCompareDataFn(void *dataA, void *dataB){
|
||||
return (ARC_Bool)(*(uint32_t *)dataA == *(uint32_t *)dataB);
|
||||
}
|
||||
|
||||
void ARC_EntitySystem_VectorDestroyDataFn(void *data){
|
||||
free((uint32_t *)data);
|
||||
}
|
||||
|
||||
void ARC_EntitySystem_Create(ARC_EntitySystem **entitySystem){
|
||||
*entitySystem = (ARC_EntitySystem *)malloc(sizeof(ARC_EntitySystem));
|
||||
|
||||
ARC_Vector_CompareDataFn compareDataFn = ARC_EntitySystem_VectorCompareDataFn;
|
||||
ARC_Vector_DestroyDataFn destroyDataFn = ARC_EntitySystem_VectorDestroyDataFn;
|
||||
//ARC_Vector_CompareDataFn compareDataFn = ARC_EntitySystem_VectorCompareDataFn;
|
||||
//ARC_Vector_DestroyDataFn destroyDataFn = ARC_EntitySystem_VectorDestroyDataFn;
|
||||
|
||||
ARC_Vector_Create(&((*entitySystem)->flagVector), &compareDataFn, &destroyDataFn);
|
||||
ARC_Vector_Create(&((*entitySystem)->maskVector), &compareDataFn, &destroyDataFn);
|
||||
ARC_VectorInline_Create(&((*entitySystem)->flagVector) , sizeof(uint8_t) , NULL, NULL);
|
||||
ARC_VectorInline_Create(&((*entitySystem)->maskVector) , sizeof(uint32_t), NULL, NULL);
|
||||
ARC_VectorInline_Create(&((*entitySystem)->offsetVector), sizeof(uint32_t), NULL, NULL);
|
||||
ARC_VectorInline_Create(&((*entitySystem)->sizeVector) , sizeof(uint32_t), NULL, NULL);
|
||||
|
||||
//can't create the data vector because no components have been registered
|
||||
(*entitySystem)->data = NULL;
|
||||
|
||||
//TODO: this would probs be better to use a queue
|
||||
ARC_VectorInline_Create(&((*entitySystem)->freeEntities), sizeof(ARC_Entity), NULL, NULL);
|
||||
}
|
||||
|
||||
void ARC_EntitySystem_Destroy(ARC_EntitySystem *entitySystem){
|
||||
if(entitySystem->data != NULL){
|
||||
ARC_VectorInline_Destroy(entitySystem->data);
|
||||
}
|
||||
|
||||
ARC_VectorInline_Destroy(entitySystem->sizeVector);
|
||||
ARC_VectorInline_Destroy(entitySystem->offsetVector);
|
||||
ARC_VectorInline_Destroy(entitySystem->maskVector);
|
||||
ARC_VectorInline_Destroy(entitySystem->flagVector);
|
||||
|
||||
free(entitySystem);
|
||||
}
|
||||
|
||||
uint32_t ARC_EntitySystem_RegisterComponent(ARC_EntitySystem *entitySystem, uint32_t componentSize){
|
||||
//error if componentSize is zero, it must have been an error because a component is a type, and types have size
|
||||
if(componentSize == 0){
|
||||
arc_errno = ARC_ERRNO_NULL;
|
||||
ARC_DEBUG_LOG_ERROR("ARC_EntitySystem_RegisterComponent(entitySystem, componentSize), cannot add a component that does not have a size");
|
||||
return ~(uint32_t)0;
|
||||
}
|
||||
|
||||
//if data exists, free it to recreate it with the new size
|
||||
if(entitySystem->data != NULL){
|
||||
ARC_VectorInline_Destroy(entitySystem->data);
|
||||
}
|
||||
|
||||
//get the total component size
|
||||
uint32_t offsetEndIndex = ARC_VectorInline_GetSize(entitySystem->offsetVector);
|
||||
uint32_t totalSize = *(uint32_t *)ARC_VectorInline_Get(entitySystem->offsetVector, offsetEndIndex);
|
||||
|
||||
//if the new component size would overflow, throw an error
|
||||
if(totalSize > (~(uint32_t)0) - componentSize){
|
||||
arc_errno = ARC_ERRNO_NULL;
|
||||
ARC_DEBUG_LOG_ERROR("ARC_EntitySystem_RegisterComponent(entitySystem, componentSize), cannot add a component because combined size with all the other components is bigger than a uint32_t max val");
|
||||
return ~(uint32_t)0;
|
||||
}
|
||||
|
||||
//add the component size to the total size and the offset vector array
|
||||
ARC_VectorInline_Add(entitySystem->offsetVector, &totalSize);
|
||||
ARC_VectorInline_Add(entitySystem->sizeVector , &componentSize);
|
||||
totalSize += componentSize;
|
||||
|
||||
//create the resized data vector that can now house the registered component
|
||||
ARC_VectorInline_Create(&(entitySystem->data), totalSize, NULL, NULL);
|
||||
|
||||
//get the id (last index) in the offset vector
|
||||
return ARC_VectorInline_GetSize(entitySystem->offsetVector) - 1;
|
||||
}
|
||||
|
||||
ARC_Entity ARC_EntitySystem_InitEntity(ARC_EntitySystem *entitySystem){
|
||||
//check if there is a free id to use
|
||||
if(ARC_VectorInline_GetSize(entitySystem->freeEntities) != 0){
|
||||
//get the next free entity and remove the used id from the free entities
|
||||
ARC_Entity entity = *(ARC_Entity *)ARC_VectorInline_Get(entitySystem->freeEntities, 0);
|
||||
ARC_VectorInline_RemoveIndex(entitySystem->freeEntities, 0);
|
||||
|
||||
//set the flag to make the current entity alive
|
||||
uint8_t *flagData = (uint8_t *)ARC_VectorInline_Get(entitySystem->flagVector, (uint32_t)entity);
|
||||
*flagData = (uint8_t)ARC_ENTITY_ALIVE;
|
||||
|
||||
//reset the mask data to clear all the components
|
||||
uint8_t *maskData = (uint8_t *)ARC_VectorInline_Get(entitySystem->maskVector, (uint32_t)entity);
|
||||
*maskData = 0;
|
||||
|
||||
//return the entity
|
||||
return entity;
|
||||
}
|
||||
|
||||
//get the next free entity
|
||||
ARC_Entity entity = (ARC_Entity)ARC_VectorInline_GetSize(entitySystem->data);
|
||||
//TODO: check if this works
|
||||
ARC_VectorInline_Add(entitySystem->data, NULL);
|
||||
|
||||
//set the flag to make the current entity alive
|
||||
uint8_t *flagData = (uint8_t *)ARC_VectorInline_Get(entitySystem->flagVector, (uint32_t)entity);
|
||||
*flagData = (uint8_t)ARC_ENTITY_ALIVE;
|
||||
|
||||
//reset the mask data to clear all the components
|
||||
uint8_t *maskData = (uint8_t *)ARC_VectorInline_Get(entitySystem->maskVector, (uint32_t)entity);
|
||||
*maskData = 0;
|
||||
|
||||
//return the entity
|
||||
return entity;
|
||||
}
|
||||
|
||||
void ARC_EntitySystem_ReleaseEntity(ARC_EntitySystem *entitySystem, ARC_Entity entity){
|
||||
//set the flag to make the current entity dead
|
||||
uint8_t *flagData = (uint8_t *)ARC_VectorInline_Get(entitySystem->flagVector, (uint32_t)entity);
|
||||
*flagData = (uint8_t)ARC_ENTITY_DEAD;
|
||||
|
||||
//add the entity to the free entities vector
|
||||
ARC_VectorInline_Add(entitySystem->freeEntities, &entity);
|
||||
}
|
||||
|
||||
void ARC_EntitySystem_AddComponent(ARC_EntitySystem *entitySystem, ARC_Entity entity, ARC_EntityComponent component, void *data){
|
||||
//get the component data to set
|
||||
uint32_t componentSize = *(uint32_t *)ARC_VectorInline_Get(entitySystem->sizeVector, (uint32_t)component);
|
||||
void *componentData = ARC_EntitySystem_GetComponentData(entitySystem, entity, component);
|
||||
|
||||
//set the component in the entity mask
|
||||
uint32_t *maskData = (uint32_t *)ARC_VectorInline_Get(entitySystem->maskVector, (uint32_t)entity);
|
||||
*maskData |= 1 << (uint32_t)component;
|
||||
|
||||
//copy the data into the component
|
||||
memcpy(componentData, data, componentSize);
|
||||
}
|
||||
|
||||
ARC_Bool ARC_EntitySystem_HasComponent(ARC_EntitySystem *entitySystem, ARC_Entity entity, ARC_EntityComponent component){
|
||||
//get the mask, then check if it holds a component
|
||||
uint32_t *maskData = (uint32_t *)ARC_VectorInline_Get(entitySystem->maskVector, (uint32_t)entity);
|
||||
return (ARC_Bool)((*maskData & (1 << (uint32_t)component)) != 0);
|
||||
}
|
||||
|
||||
void *ARC_EntitySystem_GetComponentData(ARC_EntitySystem *entitySystem, ARC_Entity entity, ARC_EntityComponent component){
|
||||
//get the entity row, then offset that for the component to get the component data
|
||||
void *data = ARC_VectorInline_Get(entitySystem->data, (uint32_t)entity);
|
||||
return data + *(int32_t *)ARC_VectorInline_Get(entitySystem->offsetVector, (uint32_t)component);
|
||||
}
|
||||
|
||||
|
||||
ARC_Array ARC_EntitySystem_QueryComponentsData(ARC_EntitySystem *entitySystem, uint32_t components){
|
||||
ARC_Array componentsData = { 0, NULL };
|
||||
|
||||
componentsData.size = ARC_VectorInline_GetSize(entitySystem->data) - ARC_VectorInline_GetSize(entitySystem->freeEntities);
|
||||
|
||||
return componentsData;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue