From aee06f51f09f168ab068b812e2b353dd5bc98491 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 9 Nov 2025 20:55:41 -0600 Subject: [PATCH] Improve worldpos.h --- src/rpg/entity/entity.c | 4 +- src/rpg/rpgcamera.c | 20 +++---- src/rpg/world/chunk.c | 16 +++--- src/rpg/world/chunk.h | 22 +++++--- src/rpg/world/map.c | 109 +++++++++++++++++++------------------ src/rpg/world/map.h | 24 +++----- src/rpg/world/worldpos.h | 13 ++++- src/scene/scene/scenemap.c | 14 ++--- 8 files changed, 115 insertions(+), 107 deletions(-) diff --git a/src/rpg/entity/entity.c b/src/rpg/entity/entity.c index 859e7ee..ba3c32d 100644 --- a/src/rpg/entity/entity.c +++ b/src/rpg/entity/entity.c @@ -67,11 +67,11 @@ void entityWalk(entity_t *entity, const entitydir_t direction) { entity->direction = direction; // Where are we moving? - uint8_t newX, newY; + worldunit_t newX, newY; newX = entity->position.x; newY = entity->position.y; { - int8_t relX, relY; + worldunits_t relX, relY; entityDirGetRelative(direction, &relX, &relY); newX += relX; newY += relY; diff --git a/src/rpg/rpgcamera.c b/src/rpg/rpgcamera.c index 96688be..2d8b16b 100644 --- a/src/rpg/rpgcamera.c +++ b/src/rpg/rpgcamera.c @@ -19,11 +19,11 @@ void rpgCameraInit(void) { void rpgCameraUpdate(void) { switch(RPG_CAMERA.mode) { case RPG_CAMERA_MODE_FREE: - mapPositionSet( - (int16_t)(RPG_CAMERA.free.x / CHUNK_WIDTH) - (MAP_CHUNK_WIDTH / 2), - (int16_t)(RPG_CAMERA.free.y / CHUNK_HEIGHT) - (MAP_CHUNK_HEIGHT / 2), - (int16_t)(RPG_CAMERA.free.z / CHUNK_DEPTH) - (MAP_CHUNK_DEPTH / 2) - ); + mapPositionSet((chunkpos_t){ + .x = (RPG_CAMERA.free.x / CHUNK_WIDTH) - (MAP_CHUNK_WIDTH / 2), + .y = (RPG_CAMERA.free.y / CHUNK_HEIGHT) - (MAP_CHUNK_HEIGHT / 2), + .z = (RPG_CAMERA.free.z / CHUNK_DEPTH) - (MAP_CHUNK_DEPTH / 2) + }); break; case RPG_CAMERA_MODE_FOLLOW_ENTITY: { @@ -32,11 +32,11 @@ void rpgCameraUpdate(void) { // 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 - mapPositionSet( - (int16_t)(entity->position.x / CHUNK_WIDTH) - (MAP_CHUNK_WIDTH / 2), - (int16_t)(entity->position.y / CHUNK_HEIGHT) - (MAP_CHUNK_HEIGHT / 2), - (int16_t)(entity->position.z / CHUNK_DEPTH) - (MAP_CHUNK_DEPTH / 2) - ); + mapPositionSet((chunkpos_t){ + .x = (entity->position.x / CHUNK_WIDTH) - (MAP_CHUNK_WIDTH / 2), + .y = (entity->position.y / CHUNK_HEIGHT) - (MAP_CHUNK_HEIGHT / 2), + .z = (entity->position.z / CHUNK_DEPTH) - (MAP_CHUNK_DEPTH / 2) + }); break; } diff --git a/src/rpg/world/chunk.c b/src/rpg/world/chunk.c index 3ef63d1..19a9999 100644 --- a/src/rpg/world/chunk.c +++ b/src/rpg/world/chunk.c @@ -7,14 +7,14 @@ #include "chunk.h" -uint32_t chunkGetTileIndex( - const uint8_t relativeTileX, - const uint8_t relativeTileY, - const uint8_t relativeTileZ -) { +uint32_t chunkGetTileIndex(const chunkpos_t position) { return ( - (relativeTileZ * CHUNK_WIDTH * CHUNK_HEIGHT) + - (relativeTileY * CHUNK_WIDTH) + - relativeTileX + (position.z * CHUNK_WIDTH * CHUNK_HEIGHT) + + (position.y * CHUNK_WIDTH) + + position.x ); +} + +bool_t chunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b) { + return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); } \ No newline at end of file diff --git a/src/rpg/world/chunk.h b/src/rpg/world/chunk.h index d1a016b..ea0de92 100644 --- a/src/rpg/world/chunk.h +++ b/src/rpg/world/chunk.h @@ -7,6 +7,7 @@ #pragma once #include "rpg/world/tile.h" +#include "worldpos.h" #define CHUNK_WIDTH 4 #define CHUNK_HEIGHT 4 @@ -14,20 +15,23 @@ #define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) typedef struct chunk_s { - int16_t x, y, z; + chunkpos_t position; tile_t tiles[CHUNK_TILE_COUNT]; } chunk_t; /** * Gets the tile index for a tile position within a chunk. * - * @param relativeTileX The X coordinate of the tile within the chunk. - * @param relativeTileY The Y coordinate of the tile within the chunk. - * @param relativeTileZ The Z coordinate of the tile within the chunk. + * @param position The position within the chunk. * @return The tile index within the chunk. */ -uint32_t chunkGetTileIndex( - const uint8_t relativeTileX, - const uint8_t relativeTileY, - const uint8_t relativeTileZ -); \ No newline at end of file +uint32_t chunkGetTileIndex(const chunkpos_t position); + +/** + * Checks if two chunk positions are equal. + * + * @param a The first chunk position. + * @param b The second chunk position. + * @return true if equal, false otherwise. + */ +bool_t chunkPositionIsEqual(const chunkpos_t a, const chunkpos_t b); \ No newline at end of file diff --git a/src/rpg/world/map.c b/src/rpg/world/map.c index 0bafd0e..a194199 100644 --- a/src/rpg/world/map.c +++ b/src/rpg/world/map.c @@ -15,14 +15,14 @@ void mapInit() { // Init the default chunks. In future I'll probably make this based on where // the player spawns in to save an initial mapSet. - 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++) { + chunkindex_t index = 0; + for(chunkunit_t z = 0; z < MAP_CHUNK_DEPTH; z++) { + for(chunkunit_t y = 0; y < MAP_CHUNK_HEIGHT; y++) { + for(chunkunit_t x = 0; x < MAP_CHUNK_WIDTH; x++) { chunk_t *chunk = &MAP.chunks[index]; - chunk->x = x; - chunk->y = y; - chunk->z = z; + chunk->position.x = x; + chunk->position.y = y; + chunk->position.z = z; MAP.chunkOrder[index] = chunk; mapChunkLoad(chunk); index++; @@ -31,26 +31,29 @@ void mapInit() { } } -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; +void mapPositionSet(const chunkpos_t newPos) { + const chunkpos_t curPos = MAP.chunkPosition; + if(chunkPositionIsEqual(curPos, newPos)) return; // Determine which chunks remain loaded - int32_t chunksRemaining[MAP_CHUNK_COUNT] = {0}; - int32_t chunksFreed[MAP_CHUNK_COUNT] = {0}; + chunkindex_t chunksRemaining[MAP_CHUNK_COUNT] = {0}; + chunkindex_t chunksFreed[MAP_CHUNK_COUNT] = {0}; uint32_t remainingCount = 0; uint32_t freedCount = 0; - for(uint32_t i = 0; i < MAP_CHUNK_COUNT; i++) { + for(chunkindex_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 + chunk->position.x >= newPos.x && + chunk->position.x < newPos.x + MAP_CHUNK_WIDTH && + + chunk->position.y >= newPos.y && + chunk->position.y < newPos.y + MAP_CHUNK_HEIGHT && + + chunk->position.z >= newPos.z && + chunk->position.z < newPos.z + MAP_CHUNK_DEPTH ) { // Stays loaded chunksRemaining[remainingCount++] = i; @@ -62,28 +65,26 @@ void mapPositionSet(const int16_t x, const int16_t y, const int16_t z) { } // Unload the freed chunks - for(uint32_t i = 0; i < freedCount; i++) { + for(chunkindex_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; + chunkindex_t orderIndex = 0; + for(chunkunit_t zOff = 0; zOff < MAP_CHUNK_DEPTH; zOff++) { + for(chunkunit_t yOff = 0; yOff < MAP_CHUNK_HEIGHT; yOff++) { + for(chunkunit_t xOff = 0; xOff < MAP_CHUNK_WIDTH; xOff++) { + const chunkpos_t newChunkPos = { + newPos.x + xOff, newPos.y + yOff, newPos.z + zOff + }; // Is this chunk already loaded (was not unloaded earlier)? - int32_t chunkIndex = -1; - for(uint32_t i = 0; i < remainingCount; i++) { + chunkindex_t chunkIndex = -1; + for(chunkindex_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; + if(!chunkPositionIsEqual(chunk->position, newChunkPos)) continue; chunkIndex = chunksRemaining[i]; break; } @@ -93,9 +94,7 @@ void mapPositionSet(const int16_t x, const int16_t y, const int16_t z) { // Find a freed chunk to reuse chunkIndex = chunksFreed[--freedCount]; chunk_t *chunk = &MAP.chunks[chunkIndex]; - chunk->x = chunkX; - chunk->y = chunkY; - chunk->z = chunkZ; + chunk->position = newChunkPos; mapChunkLoad(chunk); } @@ -105,18 +104,26 @@ void mapPositionSet(const int16_t x, const int16_t y, const int16_t z) { } // Update map position - MAP.x = x; - MAP.y = y; - MAP.z = z; + MAP.chunkPosition = newPos; } void mapUpdate() { } void mapChunkUnload(chunk_t* chunk) { + printf("Unloading chunk at (%d, %d, %d)\n", + chunk->position.x, + chunk->position.y, + chunk->position.z + ); } void mapChunkLoad(chunk_t* chunk) { + printf("Loading chunk at (%d, %d, %d)\n", + chunk->position.x, + chunk->position.y, + chunk->position.z + ); memoryZero(chunk->tiles, sizeof(tile_t) * CHUNK_TILE_COUNT); uint8_t x, y, z; @@ -131,27 +138,25 @@ void mapChunkLoad(chunk_t* chunk) { ] = (tile_t){ .id = 1 }; } -uint8_t mapGetChunkIndexAt( - const int16_t chunkX, - const int16_t chunkY, - const int16_t chunkZ -) { - int16_t relX = chunkX - MAP.x; - int16_t relY = chunkY - MAP.y; - int16_t relZ = chunkZ - MAP.z; +chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) { + chunkpos_t relPos = { + position.x - MAP.chunkPosition.x, + position.y - MAP.chunkPosition.y, + position.z - MAP.chunkPosition.z + }; if( - relX < 0 || relX >= MAP_CHUNK_WIDTH || - relY < 0 || relY >= MAP_CHUNK_HEIGHT || - relZ < 0 || relZ >= MAP_CHUNK_DEPTH + relPos.x < 0 || relPos.x >= MAP_CHUNK_WIDTH || + relPos.y < 0 || relPos.y >= MAP_CHUNK_HEIGHT || + relPos.z < 0 || relPos.z >= MAP_CHUNK_DEPTH ) { - return UINT8_MAX; + return -1; } return ( - (relZ * MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT) + - (relY * MAP_CHUNK_WIDTH) + - relX + (relPos.z * MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT) + + (relPos.y * MAP_CHUNK_WIDTH) + + relPos.x ); } diff --git a/src/rpg/world/map.h b/src/rpg/world/map.h index 9796cb8..dc0b3a6 100644 --- a/src/rpg/world/map.h +++ b/src/rpg/world/map.h @@ -16,7 +16,7 @@ typedef struct map_s { chunk_t chunks[MAP_CHUNK_COUNT]; chunk_t *chunkOrder[MAP_CHUNK_COUNT]; - int16_t x, y, z; + chunkpos_t chunkPosition; } map_t; extern map_t MAP; @@ -34,11 +34,9 @@ void mapUpdate(); /** * Sets the map position and updates chunks accordingly. * - * @param x The new X position. - * @param y The new Y position. - * @param z The new Z position. + * @param newPos The new chunk position. */ -void mapPositionSet(const int16_t x, const int16_t y, const int16_t z); +void mapPositionSet(const chunkpos_t newPos); /** * Unloads a chunk. @@ -55,18 +53,12 @@ void mapChunkUnload(chunk_t* chunk); void mapChunkLoad(chunk_t* chunk); /** - * Gets the index of a chunk at the specified CHUNK coordinates. - * - * @param chunkX The X coordinate of the chunk (in CHUNK units). - * @param chunkY The Y coordinate of the chunk (in CHUNK units). - * @param chunkZ The Z coordinate of the chunk (in CHUNK units). - * @return The index of the chunk, or UINT8_MAX if out of bounds. + * Gets the index of a chunk, within the world, at the given position. + * + * @param position The chunk position. + * @return The index of the chunk, or -1 if out of bounds. */ -uint8_t mapGetChunkIndexAt( - const int16_t chunkX, - const int16_t chunkY, - const int16_t chunkZ -); +chunkindex_t mapGetChunkIndexAt(const chunkpos_t position); /** * Gets a chunk by its index. diff --git a/src/rpg/world/worldpos.h b/src/rpg/world/worldpos.h index 935f349..5022a0d 100644 --- a/src/rpg/world/worldpos.h +++ b/src/rpg/world/worldpos.h @@ -8,10 +8,17 @@ #pragma once #include "dusk.h" -typedef uint8_t worldunit_t; +typedef int32_t worldunit_t; typedef int16_t chunkunit_t; -typedef int8_t worldunits_t; +typedef int32_t chunkindex_t; + +typedef int32_t worldunits_t; +typedef int32_t chunkunits_t; typedef struct worldpos_s { worldunit_t x, y, z; -} worldpos_t; \ No newline at end of file +} worldpos_t; + +typedef struct chunkpos_t { + chunkunit_t x, y, z; +} chunkpos_t; \ No newline at end of file diff --git a/src/scene/scene/scenemap.c b/src/scene/scene/scenemap.c index 360dcc5..f71cc71 100644 --- a/src/scene/scene/scenemap.c +++ b/src/scene/scene/scenemap.c @@ -61,7 +61,7 @@ void sceneMapEntityGetPosition(const entity_t *entity, vec3 outPosition) { float_t animPercentage = entity->animTime / ENTITY_ANIM_WALK_DURATION; // Get facing rel, we know we moved from the inverse direction. - int8_t x, y; + worldunits_t x, y; entityDirGetRelative(entity->direction, &x, &y); x = -x, y = -y; @@ -163,9 +163,9 @@ void sceneMapRenderMap() { chunk_t *chunk = MAP.chunkOrder[i]; vec3 min, max; - min[0] = chunk->x * CHUNK_WIDTH * TILE_SIZE; - min[1] = chunk->y * CHUNK_HEIGHT * TILE_SIZE; - min[2] = chunk->z * CHUNK_DEPTH * TILE_SIZE; + min[0] = chunk->position.x * CHUNK_WIDTH * TILE_SIZE; + min[1] = chunk->position.y * CHUNK_HEIGHT * TILE_SIZE; + min[2] = chunk->position.z * CHUNK_DEPTH * TILE_SIZE; // center tile min[0] -= TILE_SIZE / 2.0f; @@ -177,10 +177,10 @@ void sceneMapRenderMap() { max[2] = min[2]; color_t color = COLOR_WHITE; - if(chunk->x % 2 == 0) { - color = (chunk->y % 2 == 0) ? COLOR_BLACK : COLOR_WHITE; + if(chunk->position.x % 2 == 0) { + color = (chunk->position.y % 2 == 0) ? COLOR_BLACK : COLOR_WHITE; } else { - color = (chunk->y % 2 == 0) ? COLOR_WHITE : COLOR_BLACK; + color = (chunk->position.y % 2 == 0) ? COLOR_WHITE : COLOR_BLACK; } spriteBatchPush3D(