Chunk loading example
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
#include "util/math.h"
|
#include "util/math.h"
|
||||||
#include "rpg/cutscene/cutscenemode.h"
|
#include "rpg/cutscene/cutscenemode.h"
|
||||||
|
#include "rpg/world/map.h"
|
||||||
|
|
||||||
entity_t ENTITIES[ENTITY_COUNT];
|
entity_t ENTITIES[ENTITY_COUNT];
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ void rpgUpdate(void) {
|
|||||||
if(!TIME.fixedUpdate) return;
|
if(!TIME.fixedUpdate) return;
|
||||||
|
|
||||||
// TODO: Do not update if the scene is not the map scene?
|
// TODO: Do not update if the scene is not the map scene?
|
||||||
|
|
||||||
mapUpdate();
|
mapUpdate();
|
||||||
|
|
||||||
// Update overworld ents.
|
// Update overworld ents.
|
||||||
@@ -55,8 +54,8 @@ void rpgUpdate(void) {
|
|||||||
entityUpdate(ent);
|
entityUpdate(ent);
|
||||||
} while(++ent < &ENTITIES[ENTITY_COUNT]);
|
} while(++ent < &ENTITIES[ENTITY_COUNT]);
|
||||||
|
|
||||||
// Tick the cutscene system.
|
|
||||||
cutsceneSystemUpdate();
|
cutsceneSystemUpdate();
|
||||||
|
rpgCameraUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpgDispose(void) {
|
void rpgDispose(void) {
|
||||||
|
|||||||
@@ -8,9 +8,35 @@
|
|||||||
#include "rpgcamera.h"
|
#include "rpgcamera.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "rpg/entity/entity.h"
|
#include "rpg/entity/entity.h"
|
||||||
|
#include "rpg/world/map.h"
|
||||||
|
|
||||||
rpgcamera_t RPG_CAMERA;
|
rpgcamera_t RPG_CAMERA;
|
||||||
|
|
||||||
void rpgCameraInit(void) {
|
void rpgCameraInit(void) {
|
||||||
memoryZero(&RPG_CAMERA, sizeof(rpgcamera_t));
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,3 +30,8 @@ extern rpgcamera_t RPG_CAMERA;
|
|||||||
* Initializes the RPG camera.
|
* Initializes the RPG camera.
|
||||||
*/
|
*/
|
||||||
void rpgCameraInit(void);
|
void rpgCameraInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the RPG camera.
|
||||||
|
*/
|
||||||
|
void rpgCameraUpdate(void);
|
||||||
@@ -7,16 +7,118 @@
|
|||||||
|
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include <stdio.h> // For printf
|
||||||
|
|
||||||
map_t MAP;
|
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() {
|
void mapInit() {
|
||||||
memoryZero(&MAP, sizeof(map_t));
|
memoryZero(&MAP, sizeof(map_t));
|
||||||
|
|
||||||
for(uint32_t i = 0; i < MAP_CHUNK_COUNT; i++) {
|
uint32_t index = 0;
|
||||||
MAP.chunkOrder[i] = &MAP.chunks[i];
|
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() {
|
void mapUpdate() {
|
||||||
|
|
||||||
|
|||||||
@@ -30,3 +30,18 @@ void mapInit();
|
|||||||
* Updates the map.
|
* 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);
|
||||||
Reference in New Issue
Block a user