Chunk loading improvements

This commit is contained in:
2025-11-11 19:36:04 -06:00
parent 5c8b314689
commit d39ed1ea5a
12 changed files with 97 additions and 32 deletions

View File

@@ -167,6 +167,14 @@ errorret_t assetInit(void) {
errorOk(); errorOk();
} }
bool_t assetFileExists(const char_t *filename) {
assertStrLenMax(filename, FILENAME_MAX, "Filename too long.");
zip_int64_t idx = zip_name_locate(ASSET.zip, filename, 0);
if(idx < 0) return false;
return true;
}
errorret_t assetLoad(const char_t *filename, void *output) { errorret_t assetLoad(const char_t *filename, void *output) {
assertStrLenMax(filename, FILENAME_MAX, "Filename too long."); assertStrLenMax(filename, FILENAME_MAX, "Filename too long.");
assertNotNull(output, "Output pointer cannot be NULL."); assertNotNull(output, "Output pointer cannot be NULL.");

View File

@@ -69,6 +69,14 @@ static asset_t ASSET;
*/ */
errorret_t assetInit(void); errorret_t assetInit(void);
/**
* Checks if an asset file exists.
*
* @param filename The filename of the asset to check.
* @return true if the asset file exists, false otherwise.
*/
bool_t assetFileExists(const char_t *filename);
/** /**
* Loads an asset by its filename, the output type depends on the asset type. * Loads an asset by its filename, the output type depends on the asset type.
* *

View File

@@ -32,6 +32,12 @@ errorret_t assetChunkLoad(assetcustom_t custom) {
assertNotNull(custom.zipFile, "Zip file pointer cannot be NULL"); assertNotNull(custom.zipFile, "Zip file pointer cannot be NULL");
chunk_t *chunk = (chunk_t *)custom.output; chunk_t *chunk = (chunk_t *)custom.output;
printf(
"Loading chunk asset at position (%d, %d, %d)...\n",
chunk->position.x,
chunk->position.y,
chunk->position.z
);
// Read header // Read header
assetchunkheader_t header; assetchunkheader_t header;

View File

@@ -42,8 +42,8 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
errorret_t engineUpdate(void) { errorret_t engineUpdate(void) {
timeUpdate(); timeUpdate();
inputUpdate(); inputUpdate();
rpgUpdate(); errorChain(rpgUpdate());
uiUpdate(); uiUpdate();
sceneManagerUpdate(); sceneManagerUpdate();
errorChain(displayUpdate()); errorChain(displayUpdate());

View File

@@ -20,7 +20,7 @@ errorret_t rpgInit(void) {
// Init cutscene subsystem // Init cutscene subsystem
cutsceneSystemInit(); cutsceneSystemInit();
mapInit(); errorChain(mapInit());
rpgCameraInit(); rpgCameraInit();
rpgTextboxInit(); rpgTextboxInit();
@@ -41,9 +41,11 @@ errorret_t rpgInit(void) {
errorOk(); errorOk();
} }
void rpgUpdate(void) { errorret_t rpgUpdate(void) {
#if TIME_FIXED == 0 #if TIME_FIXED == 0
if(TIME.dynamicUpdate) return; if(TIME.dynamicUpdate) {
errorOk();
}
#endif #endif
// TODO: Do not update if the scene is not the map scene? // TODO: Do not update if the scene is not the map scene?
@@ -57,9 +59,10 @@ void rpgUpdate(void) {
} while(++ent < &ENTITIES[ENTITY_COUNT]); } while(++ent < &ENTITIES[ENTITY_COUNT]);
cutsceneSystemUpdate(); cutsceneSystemUpdate();
rpgCameraUpdate(); errorChain(rpgCameraUpdate());
errorOk();
} }
void rpgDispose(void) { void rpgDispose(void) {
mapDispose();
} }

View File

@@ -21,8 +21,10 @@ errorret_t rpgInit(void);
/** /**
* Update the RPG subsystem. * Update the RPG subsystem.
*
* @return An error code.
*/ */
void rpgUpdate(void); errorret_t rpgUpdate(void);
/** /**
* Dispose of the RPG subsystem. * Dispose of the RPG subsystem.

View File

@@ -17,7 +17,7 @@ void rpgCameraInit(void) {
memoryZero(&RPG_CAMERA, sizeof(rpgcamera_t)); memoryZero(&RPG_CAMERA, sizeof(rpgcamera_t));
} }
void rpgCameraUpdate(void) { errorret_t rpgCameraUpdate(void) {
chunkpos_t chunkPos; chunkpos_t chunkPos;
switch(RPG_CAMERA.mode) { switch(RPG_CAMERA.mode) {
@@ -27,7 +27,9 @@ void rpgCameraUpdate(void) {
case RPG_CAMERA_MODE_FOLLOW_ENTITY: { case RPG_CAMERA_MODE_FOLLOW_ENTITY: {
entity_t *entity = &ENTITIES[RPG_CAMERA.followEntity.followEntityId]; entity_t *entity = &ENTITIES[RPG_CAMERA.followEntity.followEntityId];
if(entity->type == ENTITY_TYPE_NULL) return; if(entity->type == ENTITY_TYPE_NULL) {
errorOk();
}
// Update map position to match camera. By default map wants to know the // Update map position to match camera. By default map wants to know the
// top left but we want to set the center, so we need to sub half map size // top left but we want to set the center, so we need to sub half map size
@@ -39,9 +41,10 @@ void rpgCameraUpdate(void) {
assertUnreachable("Invalid RPG camera mode"); assertUnreachable("Invalid RPG camera mode");
} }
mapPositionSet((chunkpos_t){ errorChain(mapPositionSet((chunkpos_t){
.x = chunkPos.x - (MAP_CHUNK_WIDTH / 2), .x = chunkPos.x - (MAP_CHUNK_WIDTH / 2),
.y = chunkPos.y - (MAP_CHUNK_HEIGHT / 2), .y = chunkPos.y - (MAP_CHUNK_HEIGHT / 2),
.z = chunkPos.z - (MAP_CHUNK_DEPTH / 2) .z = chunkPos.z - (MAP_CHUNK_DEPTH / 2)
}); }));
errorOk();
} }

View File

@@ -7,6 +7,7 @@
#pragma once #pragma once
#include "rpg/world/worldpos.h" #include "rpg/world/worldpos.h"
#include "error/error.h"
typedef enum { typedef enum {
RPG_CAMERA_MODE_FREE, RPG_CAMERA_MODE_FREE,
@@ -33,5 +34,7 @@ void rpgCameraInit(void);
/** /**
* Updates the RPG camera. * Updates the RPG camera.
*
* @return An error code.
*/ */
void rpgCameraUpdate(void); errorret_t rpgCameraUpdate(void);

View File

@@ -12,7 +12,7 @@
map_t MAP; map_t MAP;
void mapInit() { errorret_t mapInit() {
memoryZero(&MAP, sizeof(map_t)); memoryZero(&MAP, sizeof(map_t));
// Init the default chunks. In future I'll probably make this based on where // Init the default chunks. In future I'll probably make this based on where
@@ -26,16 +26,20 @@ void mapInit() {
chunk->position.y = y; chunk->position.y = y;
chunk->position.z = z; chunk->position.z = z;
MAP.chunkOrder[index] = chunk; MAP.chunkOrder[index] = chunk;
mapChunkLoad(chunk); errorChain(mapChunkLoad(chunk));
index++; index++;
} }
} }
} }
errorOk();
} }
void mapPositionSet(const chunkpos_t newPos) { errorret_t mapPositionSet(const chunkpos_t newPos) {
const chunkpos_t curPos = MAP.chunkPosition; const chunkpos_t curPos = MAP.chunkPosition;
if(chunkPositionIsEqual(curPos, newPos)) return; if(chunkPositionIsEqual(curPos, newPos)) {
errorOk();
}
// Determine which chunks remain loaded // Determine which chunks remain loaded
chunkindex_t chunksRemaining[MAP_CHUNK_COUNT] = {0}; chunkindex_t chunksRemaining[MAP_CHUNK_COUNT] = {0};
@@ -97,7 +101,7 @@ void mapPositionSet(const chunkpos_t newPos) {
chunkIndex = chunksFreed[--freedCount]; chunkIndex = chunksFreed[--freedCount];
chunk_t *chunk = &MAP.chunks[chunkIndex]; chunk_t *chunk = &MAP.chunks[chunkIndex];
chunk->position = newChunkPos; chunk->position = newChunkPos;
mapChunkLoad(chunk); errorChain(mapChunkLoad(chunk));
} }
MAP.chunkOrder[orderIndex++] = &MAP.chunks[chunkIndex]; MAP.chunkOrder[orderIndex++] = &MAP.chunks[chunkIndex];
@@ -107,22 +111,44 @@ void mapPositionSet(const chunkpos_t newPos) {
// Update map position // Update map position
MAP.chunkPosition = newPos; MAP.chunkPosition = newPos;
errorOk();
} }
void mapUpdate() { void mapUpdate() {
} }
void mapDispose() {
for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) {
mapChunkUnload(&MAP.chunks[i]);
}
}
void mapChunkUnload(chunk_t* chunk) { void mapChunkUnload(chunk_t* chunk) {
printf("Unloading chunk at (%d, %d, %d)\n", for(uint8_t i = 0; i < chunk->meshCount; i++) {
meshDispose(&chunk->meshes[i]);
}
}
errorret_t mapChunkLoad(chunk_t* chunk) {
char_t buffer[64];
chunk->meshCount = 0;
snprintf(buffer, sizeof(buffer), "map/map/%d_%d_%d.dcf",
chunk->position.x, chunk->position.x,
chunk->position.y, chunk->position.y,
chunk->position.z chunk->position.z
); );
}
void mapChunkLoad(chunk_t* chunk) { if(!assetFileExists(buffer)) {
errorCatch(errorPrint(assetLoad("map/map/0_0.dcf", chunk))); memoryZero(chunk->tiles, sizeof(chunk->tiles));
errorOk();
}
errorChain(assetLoad(buffer, chunk));
errorOk();
} }
chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) { chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) {

View File

@@ -18,20 +18,28 @@ extern map_t MAP;
/** /**
* Initializes the map. * Initializes the map.
*
* @return An error code.
*/ */
void mapInit(); errorret_t mapInit();
/** /**
* Updates the map. * Updates the map.
*/ */
void mapUpdate(); void mapUpdate();
/**
* Disposes of the map.
*/
void mapDispose();
/** /**
* Sets the map position and updates chunks accordingly. * Sets the map position and updates chunks accordingly.
* *
* @param newPos The new chunk position. * @param newPos The new chunk position.
* @return An error code.
*/ */
void mapPositionSet(const chunkpos_t newPos); errorret_t mapPositionSet(const chunkpos_t newPos);
/** /**
* Unloads a chunk. * Unloads a chunk.
@@ -44,8 +52,9 @@ void mapChunkUnload(chunk_t* chunk);
* Loads a chunk. * Loads a chunk.
* *
* @param chunk The chunk to load. * @param chunk The chunk to load.
* @return An error code.
*/ */
void mapChunkLoad(chunk_t* chunk); errorret_t mapChunkLoad(chunk_t* chunk);
/** /**
* Gets the index of a chunk, within the world, at the given position. * Gets the index of a chunk, within the world, at the given position.

View File

@@ -14,16 +14,13 @@ TILE_WIDTH = 16.0
TILE_HEIGHT = 16.0 TILE_HEIGHT = 16.0
TILE_DEPTH = 11.36 TILE_DEPTH = 11.36
def createQuadForTile(tileIndex, x=0, y=0, z=0): def processTile(tileIndex, x=0, y=0, z=0):
vertices = [] vertices = []
indices = [] indices = []
# Tile 0, nothing # Tile 0, nothing
if tileIndex == 0: if tileIndex == 0:
return { return None
'vertices': vertices,
'indices': indices
}
# Determine color for checkerboard pattern # Determine color for checkerboard pattern
color = (255,255,255) if (x + y) % 2 == 0 else (0,0,0) color = (255,255,255) if (x + y) % 2 == 0 else (0,0,0)
@@ -82,8 +79,8 @@ def processChunk(path):
z = i // (CHUNK_WIDTH * CHUNK_HEIGHT) z = i // (CHUNK_WIDTH * CHUNK_HEIGHT)
# Add tile 3D model # Add tile 3D model
result = createQuadForTile(tile, x, y, z) result = processTile(tile, x, y, z)
if len(result['vertices']) > 0: if result is not None and len(result['vertices']) > 0:
base = len(baseModel['vertices']) base = len(baseModel['vertices'])
quad_indices = [base + idx for idx in result['indices']] quad_indices = [base + idx for idx in result['indices']]
baseModel['vertices'].extend(result['vertices']) baseModel['vertices'].extend(result['vertices'])