Docs
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user