Entity loading and unloading implemented somewhat
This commit is contained in:
@ -7,6 +7,7 @@
|
||||
|
||||
#include "entity.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
entity_t ENTITIES[ENTITY_COUNT_MAX] = {0};
|
||||
|
||||
@ -24,6 +25,8 @@ void entityInit(entity_t *entity, const entitytype_t type) {
|
||||
ENTITY_CALLBACKS[type].init,
|
||||
"Entity type has no init callback"
|
||||
);
|
||||
|
||||
memoryZero(entity, sizeof(entity_t));
|
||||
|
||||
entity->type = type;
|
||||
ENTITY_CALLBACKS[type].init(entity);
|
||||
|
@ -172,14 +172,20 @@ void chunkMapSetPosition(const uint16_t x, const uint16_t y) {
|
||||
void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) {
|
||||
assertNotNull(chunk, "Chunk pointer is null");
|
||||
|
||||
// Zero out the chunk data.
|
||||
memoryZero(chunk, sizeof(chunk_t));
|
||||
|
||||
// Set the chunk coordinates.
|
||||
chunk->x = x;
|
||||
chunk->y = y;
|
||||
|
||||
// Only load data if the chunk is within bounds.
|
||||
if(x >= WORLD_WIDTH || y >= WORLD_HEIGHT) {
|
||||
memorySet(chunk->tiles, 0, sizeof(chunk->tiles));
|
||||
return;
|
||||
}
|
||||
|
||||
// Is chunk data defined?
|
||||
const chunkdata_t *chunkData = WORLD_CHUNKS[y * WORLD_WIDTH + x];
|
||||
if(chunkData == NULL) {
|
||||
memorySet(chunk->tiles, 0, sizeof(chunk->tiles));
|
||||
@ -201,15 +207,19 @@ void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) {
|
||||
while(data < chunkData->entities + CHUNK_ENTITY_COUNT_MAX) {
|
||||
if(data->type == ENTITY_TYPE_NULL) break;
|
||||
|
||||
// Store that this chunk owns this entity ID.
|
||||
chunk->entityIDs[chunk->entityCount++] = data->id;
|
||||
|
||||
// Check entity isn't loaded (still).
|
||||
entity = ENTITIES;
|
||||
do {
|
||||
if(entity->id == data->id) break;
|
||||
if(entity->type != ENTITY_TYPE_NULL && entity->id == data->id) break;
|
||||
entity++;
|
||||
} while(entity < ENTITIES + ENTITY_COUNT_MAX);
|
||||
|
||||
if(entity != ENTITIES + ENTITY_COUNT_MAX) {
|
||||
// Entity is already loaded, skip it.
|
||||
printf("Entity ID %u already loaded, skipping...\n", data->id);
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
@ -240,5 +250,54 @@ void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) {
|
||||
}
|
||||
|
||||
void chunkUnload(chunk_t *chunk) {
|
||||
uint8_t i;
|
||||
entity_t *entity;
|
||||
uint32_t id;
|
||||
assertNotNull(chunk, "Chunk pointer is null");
|
||||
|
||||
// Iterate over each entity this chunk owns.
|
||||
i = 0;
|
||||
while(i < chunk->entityCount) {
|
||||
id = chunk->entityIDs[i++];
|
||||
|
||||
// Now, do we need to unload this entity?
|
||||
bool_t shouldUnload = false;
|
||||
|
||||
// Now, find the entity loaded with this ID. It should be impossible for
|
||||
// this entity to be unloaded (but may change in future).
|
||||
entity = ENTITIES;
|
||||
do {
|
||||
if(entity->type != ENTITY_TYPE_NULL && entity->id == id) break;
|
||||
entity++;
|
||||
} while(entity < ENTITIES + ENTITY_COUNT_MAX);
|
||||
|
||||
// If the entity is still within our chunk bounds, it's getting unloaded
|
||||
if(
|
||||
entity->x >= chunk->x * CHUNK_WIDTH * TILE_WIDTH &&
|
||||
entity->x < (chunk->x + 1) * CHUNK_WIDTH * TILE_WIDTH &&
|
||||
entity->y >= chunk->y * CHUNK_HEIGHT * TILE_HEIGHT &&
|
||||
entity->y < (chunk->y + 1) * CHUNK_HEIGHT * TILE_HEIGHT
|
||||
) {
|
||||
shouldUnload = true;
|
||||
} else {
|
||||
assertUnreachable(
|
||||
"Entity has left its chunk bounds, we should not be unloading it but "
|
||||
"I have yet to implement that properly. It will need to self-manage "
|
||||
"its own unloading somehow, and also not be in a null chunk "
|
||||
"when it does so."
|
||||
);
|
||||
}
|
||||
|
||||
// This entity is still in use, leave it loaded.
|
||||
if(!shouldUnload) continue;
|
||||
|
||||
assertTrue(
|
||||
entity < ENTITIES + ENTITY_COUNT_MAX,
|
||||
"Entity ID not found for unloading"
|
||||
);
|
||||
|
||||
// NULL the entity type, effectively unloading it.
|
||||
printf("Unloading entity ID %u\n", entity->id);
|
||||
entity->type = ENTITY_TYPE_NULL;
|
||||
}
|
||||
}
|
@ -20,8 +20,8 @@
|
||||
typedef struct {
|
||||
uint16_t x, y;
|
||||
tile_t tiles[CHUNK_TILE_COUNT];
|
||||
// int32_t entityIDs[CHUNK_ENTITY_COUNT_MAX];
|
||||
// uint8_t entityCount;
|
||||
uint32_t entityIDs[CHUNK_ENTITY_COUNT_MAX];
|
||||
uint8_t entityCount;
|
||||
} chunk_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -41,6 +41,15 @@ void overworldUpdate() {
|
||||
entityUpdate(entity++);
|
||||
} while(entity->type != ENTITY_TYPE_NULL);
|
||||
|
||||
// Testing, follow player
|
||||
entity = &ENTITIES[0]; // Player entity
|
||||
assertTrue(
|
||||
entity->type == ENTITY_TYPE_PLAYER,
|
||||
"First entity must be player"
|
||||
);
|
||||
OVERWORLD_CAMERA_X = (uint32_t)floorf(entity->x);
|
||||
OVERWORLD_CAMERA_Y = (uint32_t)floorf(entity->y);
|
||||
|
||||
uint16_t x, y;
|
||||
if(OVERWORLD_CAMERA_X < RENDER_WIDTH / 2) {
|
||||
x = 0;
|
||||
|
@ -26,13 +26,13 @@ void drawOverworldDraw(void) {
|
||||
if(OVERWORLD_CAMERA_X < RENDER_WIDTH / 2) {
|
||||
DRAW_OVERWORLD_CAMERA.target.x = 0;
|
||||
} else {
|
||||
DRAW_OVERWORLD_CAMERA.target.x = (OVERWORLD_CAMERA_X - RENDER_WIDTH) / 2;
|
||||
DRAW_OVERWORLD_CAMERA.target.x = OVERWORLD_CAMERA_X - (RENDER_WIDTH / 2);
|
||||
}
|
||||
|
||||
if(OVERWORLD_CAMERA_Y < RENDER_HEIGHT / 2) {
|
||||
DRAW_OVERWORLD_CAMERA.target.y = 0;
|
||||
} else {
|
||||
DRAW_OVERWORLD_CAMERA.target.y = (OVERWORLD_CAMERA_Y - RENDER_HEIGHT) / 2;
|
||||
DRAW_OVERWORLD_CAMERA.target.y = OVERWORLD_CAMERA_Y - (RENDER_HEIGHT / 2);
|
||||
}
|
||||
|
||||
BeginMode2D(DRAW_OVERWORLD_CAMERA);
|
||||
|
Reference in New Issue
Block a user