Design
This commit is contained in:
parent
f851e3c2ec
commit
a984824ec5
5 changed files with 311 additions and 2 deletions
241
source/ecs/ecs.d
Normal file
241
source/ecs/ecs.d
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
module ecs.ecs;
|
||||
|
||||
import std.stdio;
|
||||
|
||||
|
||||
|
||||
alias SytemFuncType = void function(ref SystemCallData data, void* componentsStart);
|
||||
|
||||
struct HasComponentsStore {
|
||||
ulong[4] bits; //256 components
|
||||
|
||||
bool has(HasComponentsStore components) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool notIn(HasComponentsStore components) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int length() {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Informacje o kompnencie
|
||||
struct ComponentInfo {
|
||||
int size;
|
||||
int aligment;
|
||||
SerializeJSON funsSerJ;
|
||||
SerializeBiN funcSerB;
|
||||
}
|
||||
|
||||
struct System {
|
||||
HasComponentsStore requiredComponents;
|
||||
HasComponentsStore absenComponents;
|
||||
HasComponentsStore maybeComponents;
|
||||
bool enabled;
|
||||
int priority;
|
||||
SytemFuncType func;
|
||||
}
|
||||
// Informacje o systemie dla konkretnego entitiesa
|
||||
struct SystemCallData {
|
||||
System* system;
|
||||
int[] componentsDt;
|
||||
}
|
||||
|
||||
// Informacje o entitiesie danego typu
|
||||
struct EntityTypeData {
|
||||
HasComponentsStore components;
|
||||
int[] deltas;
|
||||
int totalSize;
|
||||
int totalAligment = 8;
|
||||
SystemCallData[] systems;
|
||||
}
|
||||
|
||||
struct EntitiesBlock {
|
||||
EntityTypeData* typeData;
|
||||
Entity* freeEntitySlot;
|
||||
EntitiesBlock* nextBlock;
|
||||
}
|
||||
|
||||
struct EntityID {
|
||||
ulong id = ulong.max;
|
||||
static immutable notUsedValue = EntityID(ulong.max);
|
||||
}
|
||||
|
||||
// Dane konkretnego Entitiesa
|
||||
struct Entity {
|
||||
EntityID entityID = EntityID.notUsedValue;
|
||||
union {
|
||||
string name;
|
||||
Entity* nextFreeSlot;
|
||||
}
|
||||
|
||||
//string eventOnDestroy;
|
||||
uint group;
|
||||
EntityID entityID;
|
||||
//ubyte[XX] thereIsComponentsMemory;
|
||||
}
|
||||
|
||||
struct Template {
|
||||
HasComponentsStore hasComp;
|
||||
Entity* entity;
|
||||
}
|
||||
|
||||
struct Manager {
|
||||
EntityAllocator entityArrayAllcoator;
|
||||
|
||||
ComponentInfo[] components;
|
||||
System[] systems;
|
||||
HashMap!(HasComponentsStore, EntitiesBlock*) entitiesDatas;
|
||||
HashMapTwoWays!(string, Entity*) nameMap;
|
||||
HashMapTwoWays!(EntityID, Entity*) idMap;
|
||||
|
||||
EntitiesBlock* getEntitiesBlock(HasComponentsStore hasComponents) {
|
||||
EntitiesBlock* block = entitiesDatas.get(hasComponents, null);
|
||||
if (block is null) {
|
||||
// If such component combination was never present, add it
|
||||
block = addNewBlock(hasComponents, block);
|
||||
return block;
|
||||
}
|
||||
// Iterate over list of components until free slot is found or lists ends
|
||||
do {
|
||||
if (block.freeEntitySlot !is null) {
|
||||
return block;
|
||||
}
|
||||
if (block.nextBlock is null) {
|
||||
block = addNewBlock(hasComponents);
|
||||
return block;
|
||||
}
|
||||
block = block.nextBlock;
|
||||
}
|
||||
while (block.nextBlock !is null);
|
||||
|
||||
}
|
||||
|
||||
EntitiesBlock* addNewBlock(HasComponentsStore hasComponents, EntitiesBlock* firstBlock) {
|
||||
// Get last block so order of blocks is preserved, and first blocks are filled first
|
||||
EntitiesBlock* lastBlock = firstBlock;
|
||||
if (lastBlock !is null) {
|
||||
while (lastBlock.nextBlock !is null) {
|
||||
lastBlock = lastBlock.nextBlock;
|
||||
}
|
||||
}
|
||||
assert(lastBlock is null || lastBlock.nextBlock is null);
|
||||
|
||||
ubyte[] memory = new ubyte[](4096);
|
||||
EntitiesBlock* block = cast(EntitiesBlock*) memory.ptr;
|
||||
if (lastBlock is null) {
|
||||
EntityTypeData* entityTypeData = newEntityTypeData(hasComponents);
|
||||
block.typeData = entityTypeData;
|
||||
block.nextBlock = null;
|
||||
entitiesDatas.add(hasComponents, block);
|
||||
} else {
|
||||
lastBlock.nextBlock = block;
|
||||
block.typeData = lastBlock.typeData;
|
||||
block.nextBlock = null;
|
||||
}
|
||||
}
|
||||
|
||||
void alignNum(ref int num, int aligment) {
|
||||
int reminder = num % aligment;
|
||||
if (reminder != 0) {
|
||||
num += aligment - reminder;
|
||||
}
|
||||
}
|
||||
|
||||
EntityTypeData* newEntityTypeData(HasComponentsStore hasComponents) {
|
||||
EntityTypeData* typeData = new EntityTypeData();
|
||||
typeData.components = hasComponents;
|
||||
ComponentInfo[] components = getComponentsInfo(hasComponents);
|
||||
typeData.deltas.length = hasComponents.length;
|
||||
|
||||
foreach (i, comp; components) {
|
||||
typeData.deltas[i] = typeData.totalSize;
|
||||
typeData.totalAligment.max(comp.aligment);
|
||||
typeData.totalSize += comp.size;
|
||||
alignNum(typeData.totalSize, comp.aligment);
|
||||
}
|
||||
alignNum(typeData.totalSize, typeData.totalAligment);
|
||||
|
||||
foreach (sys; systems) {
|
||||
if (!typeData.hasComp.has(sys.requiredComponents)
|
||||
|| !typeData.hasComp.notIn(sys.absenComponents)) {
|
||||
continue;
|
||||
}
|
||||
entTypeData.systems ~= sys
|
||||
}
|
||||
|
||||
return typeData;
|
||||
}
|
||||
|
||||
void addEntity(Template* templ) {
|
||||
EntitiesBlock* block = getEntitiesBlock(templ.hasComp);
|
||||
Entity* newEntity = block.freeEntitySlot;
|
||||
block.freeEntitySlot = newEntity.nextFreeSlot;
|
||||
// from to size
|
||||
memcpy(temp.entity, newEntity, block.typeData.totalSize);
|
||||
}
|
||||
|
||||
void addSystem(Func)(int priority) {
|
||||
HasComponentsStore requiredComponents;
|
||||
HasComponentsStore absenComponents;
|
||||
HasComponentsStore maybeComponents;
|
||||
|
||||
void systemCaller(ref SystemCallData data, void * componentsStart) {
|
||||
Func(cast(FUnc.par1Type)(componentsStart + data.componentsDt[0]),
|
||||
cast(FUnc.par1Type)(componentsStart + data.componentsDt[1])...);
|
||||
}
|
||||
System* system = new System(&systemCaller, entTypeData);
|
||||
systems~=system;
|
||||
|
||||
foreach (ref entTypeData; entitiesDatas) {
|
||||
if (!entTypeData.hasComp.has(requiredComponents)
|
||||
|| !entTypeData.hasComp.notIn(absenComponents)) {
|
||||
continue;
|
||||
}
|
||||
entTypeData.systems ~= system;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void someSystem(CompA a, CompB b, CompC* c) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
writeln("Edit source/app.d to start your project.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class System{
|
||||
|
||||
void start(){
|
||||
|
||||
}
|
||||
|
||||
void end(){
|
||||
|
||||
}
|
||||
|
||||
void update(ref ObjRend a){
|
||||
|
||||
}
|
||||
|
||||
void useEvent(EventData evvv, ref ObjRend a){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue