#include "world.h" #include "game.h" void initWorld(World * world) { world->entities = NULL; world->entitiesCount = 0; world->lookUp = NULL; world->lookUpSize = 0; world->vacantIds = NULL; world->vacantIdsCount = 0; // Set current fingerprint. SetRandomSeed(time(NULL)); world->currentFingerprint = GetRandomValue( FINGERPRINT_START_RANGE_MIN, FINGERPRINT_START_RANGE_MAX ); } void freeWorld(World * world) { int i; if (world->entities == NULL) return; // Close entities. for (i = 0; i < world->entitiesCount; ++i) closeEntity(&world->entities[i]); KF_FREE(world->entities); KF_FREE(world->lookUp); if (world->vacantIds != NULL) KF_FREE(world->vacantIds); } // Not for direct use. KfError pushVacantId(World * world, EntityId id) { ++world->vacantIdsCount; // Allocate. if (world->vacantIds == NULL) world->vacantIds = (EntityId*)KF_CALLOC(1, sizeof(EntityId)); else world->vacantIds = (EntityId*)KF_REALLOCARRAY( world->vacantIds, world->vacantIdsCount, sizeof(EntityId) ); if (world->vacantIds == NULL) { ALLOCATION_ERROR; return KFERROR; } world->vacantIds[world->vacantIdsCount - 1] = id; return KFSUCCESS; } // Not for direct use. EntityId popVacantId(World * world) { EntityId id; // Already empty. if (world->vacantIds == NULL) return ENTITY_ID_NONE; id = world->vacantIds[world->vacantIdsCount - 1]; // Decrease count. --world->vacantIdsCount; // Free or recallocate. if (world->vacantIdsCount == 0) { KF_FREE(world->vacantIds); world->vacantIds = NULL; } else { world->vacantIds = (EntityId*)KF_REALLOCARRAY( world->vacantIds, world->vacantIdsCount, sizeof(EntityId) ); } return id; } Entity * getEntityFromWorld(World world, EntityId id) { if (world.entities == NULL || id < 0 || id >= world.lookUpSize) return NULL; int pos = world.lookUp[id]; if (pos == ENTITY_ID_NONE) return NULL; return &world.entities[pos]; } EntityId addEntityToWorld(World * world, Entity entity) { EntityId id; EntityId poppedId; Entity entityCopy = entity; // Set fingerprint. entityCopy.fingerprint = world->currentFingerprint; ++world->currentFingerprint; // Not allocated. if (world->entities == NULL) { // Allocate. world->entities = (Entity*)KF_CALLOC(1, sizeof(Entity)); world->lookUp = (EntityId*)KF_CALLOC(1, sizeof(EntityId)); world->entitiesCount = 1; world->lookUpSize = 1; if (world->entities == NULL || world->lookUp == NULL) { ALLOCATION_ERROR; return ENTITY_ID_NONE; } // Set entity and id. world->entities[0] = entityCopy; world->entities[0].id = 0; world->lookUp[0] = 0; return 0; } ++world->entitiesCount; // Resize. world->entities = (Entity*)KF_REALLOCARRAY( world->entities, world->entitiesCount, sizeof(Entity) ); if (world->entities == NULL) { ALLOCATION_ERROR; return ENTITY_ID_NONE; } // Set entity. world->entities[world->entitiesCount - 1] = entityCopy; // Set look up. poppedId = popVacantId(world); // Got popped id. if (poppedId != ENTITY_ID_NONE) { world->lookUp[poppedId] = world->entitiesCount - 1; world->entities[world->entitiesCount - 1].id = poppedId; return poppedId; } ++world->lookUpSize; world->lookUp = (EntityId*)KF_REALLOCARRAY( world->lookUp, world->lookUpSize, sizeof(EntityId) ); if (world->lookUp == NULL) { ALLOCATION_ERROR; return ENTITY_ID_NONE; } // Set id. id = world->lookUpSize - 1; world->entities[world->entitiesCount - 1].id = id; world->lookUp[id] = world->entitiesCount - 1; return id; } KfError removeEntityFromWorld(World * world, EntityId id) { int i; int pos; if (world->entitiesCount == 1) return KFERROR; // Get position in list. pos = world->lookUp[id]; if (pos == ENTITY_ID_NONE) return KFSUCCESS; // Close entity. closeEntity(&world->entities[pos]); // Push id. if (pushVacantId(world, id) != KFSUCCESS) return KFERROR; // Move back entities. for (i = pos; i < world->entitiesCount - 1; ++i) world->entities[i] = world->entities[i + 1]; // Update lookup. for (i = id + 1; i < world->lookUpSize; ++i) if (world->lookUp[i] != ENTITY_ID_NONE) --world->lookUp[i]; world->lookUp[id] = ENTITY_ID_NONE; // Resize entities. --world->entitiesCount; world->entities = (Entity*)KF_REALLOCARRAY( world->entities, world->entitiesCount, sizeof(Entity) ); if (world->entities == NULL) { ALLOCATION_ERROR; return KFERROR; } return KFSUCCESS; } void updateWorld(World * world, Game * game) { int i; Entity * entity; for (i = 0; i < world->entitiesCount; ++i) { entity = &world->entities[i]; // Call update callback. if (entity->updateCb != NULL) entity->updateCb(game, entity); } } void drawWorld(World * world, Game * game) { int i; Entity * entity; for (i = 0; i < world->entitiesCount; ++i) { entity = &world->entities[i]; // Call draw callback. if (entity->drawCb != NULL) entity->drawCb(game, entity); } }