Chunk loading example

This commit is contained in:
2025-11-09 12:50:15 -06:00
parent eff5fc3d9a
commit 307f3a9dec
12 changed files with 169 additions and 21 deletions

View File

@@ -11,6 +11,7 @@
#include "time/time.h"
#include "util/math.h"
#include "rpg/cutscene/cutscenemode.h"
#include "rpg/world/map.h"
entity_t ENTITIES[ENTITY_COUNT];

View File

@@ -45,7 +45,6 @@ void rpgUpdate(void) {
if(!TIME.fixedUpdate) return;
// TODO: Do not update if the scene is not the map scene?
mapUpdate();
// Update overworld ents.
@@ -55,8 +54,8 @@ void rpgUpdate(void) {
entityUpdate(ent);
} while(++ent < &ENTITIES[ENTITY_COUNT]);
// Tick the cutscene system.
cutsceneSystemUpdate();
rpgCameraUpdate();
}
void rpgDispose(void) {

View File

@@ -8,9 +8,35 @@
#include "rpgcamera.h"
#include "util/memory.h"
#include "rpg/entity/entity.h"
#include "rpg/world/map.h"
rpgcamera_t RPG_CAMERA;
void rpgCameraInit(void) {
memoryZero(&RPG_CAMERA, sizeof(rpgcamera_t));
}
void rpgCameraUpdate(void) {
switch(RPG_CAMERA.mode) {
case RPG_CAMERA_MODE_FREE:
// Free camera mode; nothing to do.
break;
case RPG_CAMERA_MODE_FOLLOW_ENTITY: {
entity_t *entity = &ENTITIES[RPG_CAMERA.followEntity.followEntityId];
if(entity->type == ENTITY_TYPE_NULL) return;
// Update map position to match camera.
mapPositionSet(
(int16_t)(entity->position.x / CHUNK_WIDTH),
(int16_t)(entity->position.y / CHUNK_HEIGHT),
(int16_t)(entity->position.z / CHUNK_DEPTH)
);
break;
}
default:
// Unknown camera mode; do nothing.
break;
}
}

View File

@@ -29,4 +29,9 @@ extern rpgcamera_t RPG_CAMERA;
/**
* Initializes the RPG camera.
*/
void rpgCameraInit(void);
void rpgCameraInit(void);
/**
* Updates the RPG camera.
*/
void rpgCameraUpdate(void);

View File

@@ -7,17 +7,119 @@
#include "map.h"
#include "util/memory.h"
#include <stdio.h> // For printf
map_t MAP;
// Dummy functions for chunk loading/unloading
void mapChunkUnload(chunk_t* chunk) {
// Placeholder for unloading logic
printf("Unloading chunk at (%d, %d, %d)\n", chunk->x, chunk->y, chunk->z);
}
void mapChunkLoad(chunk_t* chunk) {
// Placeholder for loading logic
printf("Loading chunk at (%d, %d, %d)\n", chunk->x, chunk->y, chunk->z);
}
void mapInit() {
memoryZero(&MAP, sizeof(map_t));
for(uint32_t i = 0; i < MAP_CHUNK_COUNT; i++) {
MAP.chunkOrder[i] = &MAP.chunks[i];
uint32_t index = 0;
for(uint32_t z = 0; z < MAP_CHUNK_DEPTH; z++) {
for(uint32_t y = 0; y < MAP_CHUNK_HEIGHT; y++) {
for(uint32_t x = 0; x < MAP_CHUNK_WIDTH; x++) {
chunk_t *chunk = &MAP.chunks[index];
chunk->x = x;
chunk->y = y;
chunk->z = z;
MAP.chunkOrder[index] = chunk;
mapChunkLoad(chunk);
index++;
}
}
}
}
void mapPositionSet(const int16_t x, const int16_t y, const int16_t z) {
const int16_t curX = MAP.x;
const int16_t curY = MAP.y;
const int16_t curZ = MAP.z;
if(curX == x && curY == y && curZ == z) return;
// Determine which chunks remain loaded
int32_t chunksRemaining[MAP_CHUNK_COUNT] = {0};
int32_t chunksFreed[MAP_CHUNK_COUNT] = {0};
uint32_t remainingCount = 0;
uint32_t freedCount = 0;
for(uint32_t i = 0; i < MAP_CHUNK_COUNT; i++) {
// Will this chunk remain loaded?
chunk_t *chunk = &MAP.chunks[i];
if(
chunk->x >= x && chunk->x < x + MAP_CHUNK_WIDTH &&
chunk->y >= y && chunk->y < y + MAP_CHUNK_HEIGHT &&
chunk->z >= z && chunk->z < z + MAP_CHUNK_DEPTH
) {
// Stays loaded
chunksRemaining[remainingCount++] = i;
continue;
}
// Not remaining loaded
chunksFreed[freedCount++] = i;
}
// Unload the freed chunks
for(uint32_t i = 0; i < freedCount; i++) {
chunk_t *chunk = &MAP.chunks[chunksFreed[i]];
mapChunkUnload(chunk);
}
// This can probably be optimized later, for now we check each chunk and see
// if it needs loading or not, and update the chunk order
uint32_t orderIndex = 0;
for(uint32_t zOff = 0; zOff < MAP_CHUNK_DEPTH; zOff++) {
for(uint32_t yOff = 0; yOff < MAP_CHUNK_HEIGHT; yOff++) {
for(uint32_t xOff = 0; xOff < MAP_CHUNK_WIDTH; xOff++) {
const int16_t chunkX = x + xOff;
const int16_t chunkY = y + yOff;
const int16_t chunkZ = z + zOff;
// Is this chunk already loaded (was not unloaded earlier)?
int32_t chunkIndex = -1;
for(uint32_t i = 0; i < remainingCount; i++) {
chunk_t *chunk = &MAP.chunks[chunksRemaining[i]];
if(chunk->x != chunkX) continue;
if(chunk->y != chunkY) continue;
if(chunk->z != chunkZ) continue;
chunkIndex = chunksRemaining[i];
break;
}
// Need to load this chunk
if(chunkIndex == -1) {
// Find a freed chunk to reuse
chunkIndex = chunksFreed[--freedCount];
chunk_t *chunk = &MAP.chunks[chunkIndex];
chunk->x = chunkX;
chunk->y = chunkY;
chunk->z = chunkZ;
mapChunkLoad(chunk);
}
MAP.chunkOrder[orderIndex++] = &MAP.chunks[chunkIndex];
}
}
}
// Update map position
MAP.x = x;
MAP.y = y;
MAP.z = z;
}
void mapUpdate() {
}

View File

@@ -29,4 +29,19 @@ void mapInit();
/**
* Updates the map.
*/
void mapUpdate();
void mapUpdate();
/**
* Sets the map position and updates chunks accordingly.
*/
void mapPositionSet(const int16_t x, const int16_t y, const int16_t z);
/**
* Dummy: Unloads a chunk.
*/
void mapChunkUnload(chunk_t* chunk);
/**
* Dummy: Loads a chunk.
*/
void mapChunkLoad(chunk_t* chunk);