aboutsummaryrefslogtreecommitdiff
path: root/src/world.c
diff options
context:
space:
mode:
authornathansmithsmith <thenathansmithsmith@gmail.com>2023-07-07 23:10:23 -0600
committernathansmithsmith <thenathansmithsmith@gmail.com>2023-07-07 23:10:23 -0600
commite5268813dcbdc0d90a081b2223ebc21749038635 (patch)
tree7c917996749e4123fb1fe49ddd1ed3b8f7e92334 /src/world.c
parenta90e1987de75cfecc2693952625af8cce507ae95 (diff)
Better world
Diffstat (limited to 'src/world.c')
-rw-r--r--src/world.c250
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);
+ }
+}