4.2 KiB
World
Source: src/dusk/rpg/overworld/
Coordinate system
Three nested coordinate spaces, each defined in worldpos.h:
| Type | Description | Unit |
|---|---|---|
worldpos_t |
Tile-level absolute position {x, y, z} |
worldunit_t (int16) |
chunkpos_t |
Chunk-grid position {x, y, z} |
chunkunit_t (int16) |
fixed_t[3] |
Smooth sub-tile position used by entities | Q24.8 fixed-point |
One chunk = CHUNK_WIDTH × CHUNK_HEIGHT × CHUNK_DEPTH tiles (16 × 16 × 8).
The loaded world window = MAP_CHUNK_WIDTH × MAP_CHUNK_HEIGHT × MAP_CHUNK_DEPTH chunks (5 × 5 × 3).
Conversion helpers (all in worldpos.c):
worldPosToChunkPos(&worldPos, &chunkPos); // tile → chunk grid
chunkPosToWorldPos(&chunkPos, &worldPos); // chunk grid → tile origin
worldPosToChunkTileIndex(&worldPos); // tile → index within its chunk
chunkPosToIndex(&chunkPos); // chunk grid → linear index in MAP.chunks[]
worldPosToFixed(&worldPos, fixedOut); // tile → entity fixed position
fixedToWorldPos(fixedPos); // entity fixed → tile (truncates frac)
Tiles
Defined in tile.h as a plain tile_t enum:
TILE_SHAPE_NULL — empty / unloaded
TILE_SHAPE_GROUND — solid flat tile
TILE_SHAPE_RAMP_* — directional ramps (N/S/E/W + diagonals NE/NW/SE/SW)
Key predicates:
tileIsWalkable(tile)— true for GROUND and all ramp shapes.tileIsRamp(tile)— true only for ramp shapes.
Entity walk code (entity.c) checks both the current tile and the target tile to decide whether the entity steps forward flat, raises one Z level (walking up a ramp), or falls one Z level (stepping onto a downward ramp from above).
Chunks
chunk_t (chunk.h) holds:
position— itschunkpos_tin the world gridtiles[CHUNK_TILE_COUNT]— flat array oftile_t, indexed bychunkGetTileIndex()vertices[CHUNK_VERTEX_COUNT]/mesh— pre-baked mesh uploaded to GPU on loadentities[CHUNK_ENTITY_COUNT_MAX]— indices intoENTITIES[]currently in this chunk (sentinel0xFF)testColor— temporary debug color (checkerboard), will be replaced by real tileset data
Tile layout within a chunk is z * W*H + y * W + x (Z-major, row-major in XY).
Map
map_t MAP (map.h) is the single global map instance.
chunk_t chunks[MAP_CHUNK_COUNT]; // flat storage — index is NOT world position
chunk_t *chunkOrder[MAP_CHUNK_COUNT]; // draw-order sorted pointers into chunks[]
chunkpos_t chunkPosition; // world-grid origin of the loaded window
bool_t loaded;
Load / unload
mapInit() allocates chunk meshes and performs the initial load of all chunks in the starting window.
mapPositionSet(newPos) shifts the window:
- Determines which of the
MAP_CHUNK_COUNTslots remain within the new window vs. fall outside it. - Calls
mapChunkUnload()on every chunk that falls outside (nulls its entity slots, zeroesvertCount). - Reuses freed slots for newly-in-range chunks; calls
mapChunkLoad()on each. - Rebuilds
chunkOrder[]in XYZ order for the new position.
Chunk load (current stub)
mapChunkLoad() currently:
- Fills all tiles with
TILE_SHAPE_GROUND - Assigns a checkerboard debug color based on chunk XY parity
- Bakes a flat sprite-batch quad mesh for the z=0 layer and uploads it via
meshFlush() - Skips mesh generation for z > 0 chunks (they're empty)
Tile lookup
tile_t mapGetTile(const worldpos_t position);
Converts position to its chunk, looks up the chunk in chunkOrder, then indexes into chunk->tiles[]. Returns TILE_SHAPE_NULL for any out-of-bounds position or when the map is not loaded.
Camera
rpgcamera_t RPG_CAMERA (rpgcamera.h) has two modes:
RPG_CAMERA_MODE_FREE // free worldpos; camera.free holds the position
RPG_CAMERA_MODE_FOLLOW_ENTITY // tracks ENTITIES[followEntityId]
rpgCameraGetPosition() returns the active world tile position in either mode.
The scene renderer (sceneoverworld.c) uses rpgCameraGetPosition() to build the glm_lookat view matrix. When following an entity, it sub-tile interpolates between entity->lastPosition and entity->position using entity->animTime / ENTITY_ANIM_WALK_DURATION to smooth movement.