Improve worldpos.h

This commit is contained in:
2025-11-09 20:55:41 -06:00
parent d6c497731f
commit aee06f51f0
8 changed files with 115 additions and 107 deletions

View File

@@ -67,11 +67,11 @@ void entityWalk(entity_t *entity, const entitydir_t direction) {
entity->direction = direction; entity->direction = direction;
// Where are we moving? // Where are we moving?
uint8_t newX, newY; worldunit_t newX, newY;
newX = entity->position.x; newX = entity->position.x;
newY = entity->position.y; newY = entity->position.y;
{ {
int8_t relX, relY; worldunits_t relX, relY;
entityDirGetRelative(direction, &relX, &relY); entityDirGetRelative(direction, &relX, &relY);
newX += relX; newX += relX;
newY += relY; newY += relY;

View File

@@ -19,11 +19,11 @@ void rpgCameraInit(void) {
void rpgCameraUpdate(void) { void rpgCameraUpdate(void) {
switch(RPG_CAMERA.mode) { switch(RPG_CAMERA.mode) {
case RPG_CAMERA_MODE_FREE: case RPG_CAMERA_MODE_FREE:
mapPositionSet( mapPositionSet((chunkpos_t){
(int16_t)(RPG_CAMERA.free.x / CHUNK_WIDTH) - (MAP_CHUNK_WIDTH / 2), .x = (RPG_CAMERA.free.x / CHUNK_WIDTH) - (MAP_CHUNK_WIDTH / 2),
(int16_t)(RPG_CAMERA.free.y / CHUNK_HEIGHT) - (MAP_CHUNK_HEIGHT / 2), .y = (RPG_CAMERA.free.y / CHUNK_HEIGHT) - (MAP_CHUNK_HEIGHT / 2),
(int16_t)(RPG_CAMERA.free.z / CHUNK_DEPTH) - (MAP_CHUNK_DEPTH / 2) .z = (RPG_CAMERA.free.z / CHUNK_DEPTH) - (MAP_CHUNK_DEPTH / 2)
); });
break; break;
case RPG_CAMERA_MODE_FOLLOW_ENTITY: { 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 // 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
mapPositionSet( mapPositionSet((chunkpos_t){
(int16_t)(entity->position.x / CHUNK_WIDTH) - (MAP_CHUNK_WIDTH / 2), .x = (entity->position.x / CHUNK_WIDTH) - (MAP_CHUNK_WIDTH / 2),
(int16_t)(entity->position.y / CHUNK_HEIGHT) - (MAP_CHUNK_HEIGHT / 2), .y = (entity->position.y / CHUNK_HEIGHT) - (MAP_CHUNK_HEIGHT / 2),
(int16_t)(entity->position.z / CHUNK_DEPTH) - (MAP_CHUNK_DEPTH / 2) .z = (entity->position.z / CHUNK_DEPTH) - (MAP_CHUNK_DEPTH / 2)
); });
break; break;
} }

View File

@@ -7,14 +7,14 @@
#include "chunk.h" #include "chunk.h"
uint32_t chunkGetTileIndex( uint32_t chunkGetTileIndex(const chunkpos_t position) {
const uint8_t relativeTileX,
const uint8_t relativeTileY,
const uint8_t relativeTileZ
) {
return ( return (
(relativeTileZ * CHUNK_WIDTH * CHUNK_HEIGHT) + (position.z * CHUNK_WIDTH * CHUNK_HEIGHT) +
(relativeTileY * CHUNK_WIDTH) + (position.y * CHUNK_WIDTH) +
relativeTileX 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);
} }

View File

@@ -7,6 +7,7 @@
#pragma once #pragma once
#include "rpg/world/tile.h" #include "rpg/world/tile.h"
#include "worldpos.h"
#define CHUNK_WIDTH 4 #define CHUNK_WIDTH 4
#define CHUNK_HEIGHT 4 #define CHUNK_HEIGHT 4
@@ -14,20 +15,23 @@
#define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) #define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH)
typedef struct chunk_s { typedef struct chunk_s {
int16_t x, y, z; chunkpos_t position;
tile_t tiles[CHUNK_TILE_COUNT]; tile_t tiles[CHUNK_TILE_COUNT];
} chunk_t; } chunk_t;
/** /**
* Gets the tile index for a tile position within a chunk. * Gets the tile index for a tile position within a chunk.
* *
* @param relativeTileX The X coordinate of the tile within the chunk. * @param position The position 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.
* @return The tile index within the chunk. * @return The tile index within the chunk.
*/ */
uint32_t chunkGetTileIndex( uint32_t chunkGetTileIndex(const chunkpos_t position);
const uint8_t relativeTileX,
const uint8_t relativeTileY, /**
const uint8_t relativeTileZ * 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);

View File

@@ -15,14 +15,14 @@ void mapInit() {
// 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
// the player spawns in to save an initial mapSet. // the player spawns in to save an initial mapSet.
uint32_t index = 0; chunkindex_t index = 0;
for(uint32_t z = 0; z < MAP_CHUNK_DEPTH; z++) { for(chunkunit_t z = 0; z < MAP_CHUNK_DEPTH; z++) {
for(uint32_t y = 0; y < MAP_CHUNK_HEIGHT; y++) { for(chunkunit_t y = 0; y < MAP_CHUNK_HEIGHT; y++) {
for(uint32_t x = 0; x < MAP_CHUNK_WIDTH; x++) { for(chunkunit_t x = 0; x < MAP_CHUNK_WIDTH; x++) {
chunk_t *chunk = &MAP.chunks[index]; chunk_t *chunk = &MAP.chunks[index];
chunk->x = x; chunk->position.x = x;
chunk->y = y; chunk->position.y = y;
chunk->z = z; chunk->position.z = z;
MAP.chunkOrder[index] = chunk; MAP.chunkOrder[index] = chunk;
mapChunkLoad(chunk); mapChunkLoad(chunk);
index++; index++;
@@ -31,26 +31,29 @@ void mapInit() {
} }
} }
void mapPositionSet(const int16_t x, const int16_t y, const int16_t z) { void mapPositionSet(const chunkpos_t newPos) {
const int16_t curX = MAP.x; const chunkpos_t curPos = MAP.chunkPosition;
const int16_t curY = MAP.y; if(chunkPositionIsEqual(curPos, newPos)) return;
const int16_t curZ = MAP.z;
if(curX == x && curY == y && curZ == z) return;
// Determine which chunks remain loaded // Determine which chunks remain loaded
int32_t chunksRemaining[MAP_CHUNK_COUNT] = {0}; chunkindex_t chunksRemaining[MAP_CHUNK_COUNT] = {0};
int32_t chunksFreed[MAP_CHUNK_COUNT] = {0}; chunkindex_t chunksFreed[MAP_CHUNK_COUNT] = {0};
uint32_t remainingCount = 0; uint32_t remainingCount = 0;
uint32_t freedCount = 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? // Will this chunk remain loaded?
chunk_t *chunk = &MAP.chunks[i]; chunk_t *chunk = &MAP.chunks[i];
if( if(
chunk->x >= x && chunk->x < x + MAP_CHUNK_WIDTH && chunk->position.x >= newPos.x &&
chunk->y >= y && chunk->y < y + MAP_CHUNK_HEIGHT && chunk->position.x < newPos.x + MAP_CHUNK_WIDTH &&
chunk->z >= z && chunk->z < z + MAP_CHUNK_DEPTH
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 // Stays loaded
chunksRemaining[remainingCount++] = i; 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 // 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]]; chunk_t *chunk = &MAP.chunks[chunksFreed[i]];
mapChunkUnload(chunk); mapChunkUnload(chunk);
} }
// This can probably be optimized later, for now we check each chunk and see // 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 // if it needs loading or not, and update the chunk order
uint32_t orderIndex = 0; chunkindex_t orderIndex = 0;
for(uint32_t zOff = 0; zOff < MAP_CHUNK_DEPTH; zOff++) { for(chunkunit_t zOff = 0; zOff < MAP_CHUNK_DEPTH; zOff++) {
for(uint32_t yOff = 0; yOff < MAP_CHUNK_HEIGHT; yOff++) { for(chunkunit_t yOff = 0; yOff < MAP_CHUNK_HEIGHT; yOff++) {
for(uint32_t xOff = 0; xOff < MAP_CHUNK_WIDTH; xOff++) { for(chunkunit_t xOff = 0; xOff < MAP_CHUNK_WIDTH; xOff++) {
const int16_t chunkX = x + xOff; const chunkpos_t newChunkPos = {
const int16_t chunkY = y + yOff; newPos.x + xOff, newPos.y + yOff, newPos.z + zOff
const int16_t chunkZ = z + zOff; };
// Is this chunk already loaded (was not unloaded earlier)? // Is this chunk already loaded (was not unloaded earlier)?
int32_t chunkIndex = -1; chunkindex_t chunkIndex = -1;
for(uint32_t i = 0; i < remainingCount; i++) { for(chunkindex_t i = 0; i < remainingCount; i++) {
chunk_t *chunk = &MAP.chunks[chunksRemaining[i]]; chunk_t *chunk = &MAP.chunks[chunksRemaining[i]];
if(chunk->x != chunkX) continue; if(!chunkPositionIsEqual(chunk->position, newChunkPos)) continue;
if(chunk->y != chunkY) continue;
if(chunk->z != chunkZ) continue;
chunkIndex = chunksRemaining[i]; chunkIndex = chunksRemaining[i];
break; 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 // Find a freed chunk to reuse
chunkIndex = chunksFreed[--freedCount]; chunkIndex = chunksFreed[--freedCount];
chunk_t *chunk = &MAP.chunks[chunkIndex]; chunk_t *chunk = &MAP.chunks[chunkIndex];
chunk->x = chunkX; chunk->position = newChunkPos;
chunk->y = chunkY;
chunk->z = chunkZ;
mapChunkLoad(chunk); mapChunkLoad(chunk);
} }
@@ -105,18 +104,26 @@ void mapPositionSet(const int16_t x, const int16_t y, const int16_t z) {
} }
// Update map position // Update map position
MAP.x = x; MAP.chunkPosition = newPos;
MAP.y = y;
MAP.z = z;
} }
void mapUpdate() { void mapUpdate() {
} }
void mapChunkUnload(chunk_t* chunk) { 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) { 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); memoryZero(chunk->tiles, sizeof(tile_t) * CHUNK_TILE_COUNT);
uint8_t x, y, z; uint8_t x, y, z;
@@ -131,27 +138,25 @@ void mapChunkLoad(chunk_t* chunk) {
] = (tile_t){ .id = 1 }; ] = (tile_t){ .id = 1 };
} }
uint8_t mapGetChunkIndexAt( chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) {
const int16_t chunkX, chunkpos_t relPos = {
const int16_t chunkY, position.x - MAP.chunkPosition.x,
const int16_t chunkZ position.y - MAP.chunkPosition.y,
) { position.z - MAP.chunkPosition.z
int16_t relX = chunkX - MAP.x; };
int16_t relY = chunkY - MAP.y;
int16_t relZ = chunkZ - MAP.z;
if( if(
relX < 0 || relX >= MAP_CHUNK_WIDTH || relPos.x < 0 || relPos.x >= MAP_CHUNK_WIDTH ||
relY < 0 || relY >= MAP_CHUNK_HEIGHT || relPos.y < 0 || relPos.y >= MAP_CHUNK_HEIGHT ||
relZ < 0 || relZ >= MAP_CHUNK_DEPTH relPos.z < 0 || relPos.z >= MAP_CHUNK_DEPTH
) { ) {
return UINT8_MAX; return -1;
} }
return ( return (
(relZ * MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT) + (relPos.z * MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT) +
(relY * MAP_CHUNK_WIDTH) + (relPos.y * MAP_CHUNK_WIDTH) +
relX relPos.x
); );
} }

View File

@@ -16,7 +16,7 @@
typedef struct map_s { typedef struct map_s {
chunk_t chunks[MAP_CHUNK_COUNT]; chunk_t chunks[MAP_CHUNK_COUNT];
chunk_t *chunkOrder[MAP_CHUNK_COUNT]; chunk_t *chunkOrder[MAP_CHUNK_COUNT];
int16_t x, y, z; chunkpos_t chunkPosition;
} map_t; } map_t;
extern map_t MAP; extern map_t MAP;
@@ -34,11 +34,9 @@ void mapUpdate();
/** /**
* Sets the map position and updates chunks accordingly. * Sets the map position and updates chunks accordingly.
* *
* @param x The new X position. * @param newPos The new chunk position.
* @param y The new Y position.
* @param z The new Z position.
*/ */
void mapPositionSet(const int16_t x, const int16_t y, const int16_t z); void mapPositionSet(const chunkpos_t newPos);
/** /**
* Unloads a chunk. * Unloads a chunk.
@@ -55,18 +53,12 @@ void mapChunkUnload(chunk_t* chunk);
void mapChunkLoad(chunk_t* chunk); void mapChunkLoad(chunk_t* chunk);
/** /**
* Gets the index of a chunk at the specified CHUNK coordinates. * Gets the index of a chunk, within the world, at the given position.
* *
* @param chunkX The X coordinate of the chunk (in CHUNK units). * @param position The chunk position.
* @param chunkY The Y coordinate of the chunk (in CHUNK units). * @return The index of the chunk, or -1 if out of bounds.
* @param chunkZ The Z coordinate of the chunk (in CHUNK units).
* @return The index of the chunk, or UINT8_MAX if out of bounds.
*/ */
uint8_t mapGetChunkIndexAt( chunkindex_t mapGetChunkIndexAt(const chunkpos_t position);
const int16_t chunkX,
const int16_t chunkY,
const int16_t chunkZ
);
/** /**
* Gets a chunk by its index. * Gets a chunk by its index.

View File

@@ -8,10 +8,17 @@
#pragma once #pragma once
#include "dusk.h" #include "dusk.h"
typedef uint8_t worldunit_t; typedef int32_t worldunit_t;
typedef int16_t chunkunit_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 { typedef struct worldpos_s {
worldunit_t x, y, z; worldunit_t x, y, z;
} worldpos_t; } worldpos_t;
typedef struct chunkpos_t {
chunkunit_t x, y, z;
} chunkpos_t;

View File

@@ -61,7 +61,7 @@ void sceneMapEntityGetPosition(const entity_t *entity, vec3 outPosition) {
float_t animPercentage = entity->animTime / ENTITY_ANIM_WALK_DURATION; float_t animPercentage = entity->animTime / ENTITY_ANIM_WALK_DURATION;
// Get facing rel, we know we moved from the inverse direction. // Get facing rel, we know we moved from the inverse direction.
int8_t x, y; worldunits_t x, y;
entityDirGetRelative(entity->direction, &x, &y); entityDirGetRelative(entity->direction, &x, &y);
x = -x, y = -y; x = -x, y = -y;
@@ -163,9 +163,9 @@ void sceneMapRenderMap() {
chunk_t *chunk = MAP.chunkOrder[i]; chunk_t *chunk = MAP.chunkOrder[i];
vec3 min, max; vec3 min, max;
min[0] = chunk->x * CHUNK_WIDTH * TILE_SIZE; min[0] = chunk->position.x * CHUNK_WIDTH * TILE_SIZE;
min[1] = chunk->y * CHUNK_HEIGHT * TILE_SIZE; min[1] = chunk->position.y * CHUNK_HEIGHT * TILE_SIZE;
min[2] = chunk->z * CHUNK_DEPTH * TILE_SIZE; min[2] = chunk->position.z * CHUNK_DEPTH * TILE_SIZE;
// center tile // center tile
min[0] -= TILE_SIZE / 2.0f; min[0] -= TILE_SIZE / 2.0f;
@@ -177,10 +177,10 @@ void sceneMapRenderMap() {
max[2] = min[2]; max[2] = min[2];
color_t color = COLOR_WHITE; color_t color = COLOR_WHITE;
if(chunk->x % 2 == 0) { if(chunk->position.x % 2 == 0) {
color = (chunk->y % 2 == 0) ? COLOR_BLACK : COLOR_WHITE; color = (chunk->position.y % 2 == 0) ? COLOR_BLACK : COLOR_WHITE;
} else { } else {
color = (chunk->y % 2 == 0) ? COLOR_WHITE : COLOR_BLACK; color = (chunk->position.y % 2 == 0) ? COLOR_WHITE : COLOR_BLACK;
} }
spriteBatchPush3D( spriteBatchPush3D(