Improve worldpos.h
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
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);
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
} worldpos_t;
|
||||
|
||||
typedef struct chunkpos_t {
|
||||
chunkunit_t x, y, z;
|
||||
} chunkpos_t;
|
||||
Reference in New Issue
Block a user