Files
dusk/.claude/rpg/world.md
T
2026-06-18 14:59:21 -05:00

115 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`):
```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` — its `chunkpos_t` in the world grid
- `tiles[CHUNK_TILE_COUNT]` — flat array of `tile_t`, indexed by `chunkGetTileIndex()`
- `vertices[CHUNK_VERTEX_COUNT]` / `mesh` — pre-baked mesh uploaded to GPU on load
- `entities[CHUNK_ENTITY_COUNT_MAX]` — indices into `ENTITIES[]` currently in this chunk (sentinel `0xFF`)
- `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.
```c
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:
1. Determines which of the `MAP_CHUNK_COUNT` slots remain within the new window vs. fall outside it.
2. Calls `mapChunkUnload()` on every chunk that falls outside (nulls its entity slots, zeroes `vertCount`).
3. Reuses freed slots for newly-in-range chunks; calls `mapChunkLoad()` on each.
4. 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
```c
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:
```c
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.