diff options
author | nathansmithsmith <thenathansmithsmith@gmail.com> | 2023-07-07 23:10:23 -0600 |
---|---|---|
committer | nathansmithsmith <thenathansmithsmith@gmail.com> | 2023-07-07 23:10:23 -0600 |
commit | e5268813dcbdc0d90a081b2223ebc21749038635 (patch) | |
tree | 7c917996749e4123fb1fe49ddd1ed3b8f7e92334 /src/world.c | |
parent | a90e1987de75cfecc2693952625af8cce507ae95 (diff) |
Better world
Diffstat (limited to 'src/world.c')
-rw-r--r-- | src/world.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/src/world.c b/src/world.c index ea50eca..d76a2d3 100644 --- a/src/world.c +++ b/src/world.c @@ -1 +1,251 @@ #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) + --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, i); + } +} + +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, i); + } +} |