#ifndef BECS_H #define BECS_H #include #include #include #define MAX_ENTITIES 100 #define NUM_COMPONENTS 2 #ifdef MAX_ENTITIES #ifdef NUM_COMPONENTS #ifdef BECS_IMPLEMENTATION #define BECS_NULL_INDEX MAX_ENTITIES + 1 struct Entity { uint64_t componentBitMask; }; struct BECS_Properties { uint32_t componentSizes[NUM_COMPONENTS]; }; struct BECS_ComponentArray { uint32_t lastEntityAdded; size_t unitSize; uint32_t sparseArray[MAX_ENTITIES]; void *denseArray; uint32_t denseArraylength; }; struct BECS_ECS { Entity entities[MAX_ENTITIES]; BECS_Properties props; BECS_ComponentArray componentArrays[NUM_COMPONENTS]; }; size_t BECS_GetMinMemorySize(BECS_Properties props) { size_t totalSize = 0; totalSize += sizeof(BECS_ECS); totalSize += sizeof(BECS_ComponentArray) * NUM_COMPONENTS; for (uint32_t i = 0; i < NUM_COMPONENTS; i++) { totalSize += props.componentSizes[i] * MAX_ENTITIES; } return totalSize; } void BECS_InitComponentArray(BECS_ECS *ecs, size_t size, uint32_t componentIndex) { ecs->componentArrays[componentIndex] = {}; ecs->componentArrays[componentIndex].lastEntityAdded = BECS_NULL_INDEX; ecs->componentArrays[componentIndex].unitSize = size; ecs->componentArrays[componentIndex].denseArraylength= 0; ecs->componentArrays[componentIndex].denseArray = NULL; } BECS_ECS *BECS_Init (void *memory, size_t size, BECS_Properties props) { BECS_ECS *ecs = (BECS_ECS *)memory; *ecs = {}; ecs->props = props; for (uint32_t i = 0; i < NUM_COMPONENTS; i++) { ecs->componentArrays[i] = {}; ecs->componentArrays[i].lastEntityAdded = BECS_NULL_INDEX; ecs->componentArrays[i].unitSize = props.componentSizes[i]; ecs->componentArrays[i].denseArraylength = 0; for (uint32_t j = 0; i < MAX_ENTITIES; i++) { ecs->componentArrays[i].sparseArray[j] = BECS_NULL_INDEX; } } uintptr_t startOfComponentArrays = (uintptr_t)(ecs + 1); for (uint32_t i = 0; i < NUM_COMPONENTS; i++) { startOfComponentArrays += props.componentSizes[i] * MAX_ENTITIES; ecs->componentArrays[i].denseArray = (void *)startOfComponentArrays; } return ecs; } void *BECS_AddComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex) { if (entityID > MAX_ENTITIES) { return NULL; } uint64_t componentBitMask = 0 | (1 << (componentIndex + 1)); if (ecs->entities[entityID].componentBitMask & componentBitMask) { return NULL; } ecs->entities[entityID].componentBitMask |= componentBitMask; BECS_ComponentArray *componentArray = &ecs->componentArrays[componentIndex]; componentArray->sparseArray[entityID] = componentArray->denseArraylength; size_t componentSize = ecs->props.componentSizes[componentIndex]; uint32_t componentOffset = componentSize * componentArray->sparseArray[entityID]; void *component = (void *)((uintptr_t)componentArray->denseArray + componentOffset); componentArray->denseArraylength++; componentArray->lastEntityAdded = entityID; return component; } int32_t BECS_RemoveComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex) { if (entityID > MAX_ENTITIES) { return 1; } uint64_t componentBitMask = 0 | (1 << (componentIndex + 1)); if (!(ecs->entities[entityID].componentBitMask & componentBitMask)) { return 2; } BECS_ComponentArray * componentArray = &ecs->componentArrays[componentIndex]; if (entityID == componentArray->lastEntityAdded) { componentArray->sparseArray[entityID] = BECS_NULL_INDEX; componentArray->denseArraylength--; for (uint32_t i = 0; i < MAX_ENTITIES; i++) { if (componentArray->sparseArray[i] == componentArray->denseArraylength - 1) { componentArray->lastEntityAdded = componentArray->sparseArray[i]; break; } } return 0; } uint32_t lastEntityAddedIndex = componentArray->sparseArray[componentArray->lastEntityAdded]; uint32_t deletedCompIndex = componentArray->sparseArray[entityID]; uintptr_t denseArray = (uintptr_t)componentArray->denseArray; uintptr_t lastEntityAdded = denseArray + (lastEntityAddedIndex * componentArray->unitSize); uintptr_t deletedComp = denseArray + (lastEntityAddedIndex * componentArray->unitSize); memcpy((void *)deletedComp, (void*)lastEntityAdded, componentArray->unitSize); componentArray->denseArraylength--; componentArray->sparseArray[entityID] = lastEntityAddedIndex; return 0; } void *BECS_GetComponent(BECS_ECS *ecs, uint32_t entityID, uint32_t componentIndex) { void *component = NULL; if (componentIndex > NUM_COMPONENTS) return component; BECS_ComponentArray *componentArray = &ecs->componentArrays[componentIndex]; uint32_t componentDenseIndex = componentArray->sparseArray[entityID]; if (componentDenseIndex == BECS_NULL_INDEX) { return component; } else { component = componentArray->denseArray; } return component; } #endif #endif #endif #endif