204 lines
7.7 KiB
Markdown
204 lines
7.7 KiB
Markdown
# Tilemap Library Developer Guide
|
||
|
||
## Project Overview
|
||
|
||
The tilemap library is a C++ terrain generation system that creates tile-based worlds with biome support. It uses a multi-pass generation pipeline to create realistic, balanced terrain.
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
tilemap/
|
||
├── include/ # Public headers
|
||
│ ├── tilemap.h # Main map container
|
||
│ ├── chunk.h # 64x64 tile chunks
|
||
│ ├── tile.h # Individual tile types
|
||
│ ├── generation.h # Generation system
|
||
│ ├── biome.h # Biome system
|
||
│ ├── noise.h # Noise generators
|
||
│ └── xoroshiro.h # RNG implementation
|
||
├── src/ # Implementation files
|
||
│ ├── tilemap.cpp # TileMap implementation
|
||
│ ├── chunk.cpp # Chunk utilities
|
||
│ ├── generation.cpp # Main generation orchestrator
|
||
│ ├── biome.cpp # Biome mapping logic
|
||
│ ├── noise.cpp # Noise implementations
|
||
│ ├── xoroshiro.cpp # Xoroshiro128++ RNG
|
||
│ └── pass/ # Generation passes
|
||
│ ├── biome.cpp # Climate-based biome generation
|
||
│ ├── base_tile_type.cpp # Base terrain generation
|
||
│ ├── smoothen_mountain.cpp # Mountain smoothing
|
||
│ ├── smoothen_island.cpp # Island smoothing
|
||
│ ├── mountain_hole_fill.cpp # Hole filling
|
||
│ ├── deepwater.cpp # Deep water placement
|
||
│ ├── oil.cpp # Oil resource generation
|
||
│ └── mineral_cluster.cpp # Mineral cluster generation
|
||
├── examples/ # Usage examples
|
||
└── docs/ # Documentation
|
||
```
|
||
|
||
## Core Architecture
|
||
|
||
### Data Organization
|
||
|
||
The system uses a hierarchical structure:
|
||
- **TileMap**: n×n grid of chunks
|
||
- **Chunk**: 64×64 tiles with biome metadata
|
||
- **Tile**: Individual terrain cell (1 byte packed)
|
||
|
||
Each chunk also contains a 16×16 grid of sub-chunk biomes, providing efficient biome lookup without per-tile storage.
|
||
|
||
### Pass-Based Generation
|
||
|
||
Terrain generation uses a multi-pass pipeline for modularity and control:
|
||
|
||
1. **Biome Pass**: Generates climate data and assigns biomes to sub-chunks
|
||
2. **Base Tile Type Pass**: Creates base terrain based on biomes
|
||
3. **Mountain Smoothing Pass**: Removes isolated mountain clusters
|
||
4. **Island Smoothing Pass**: Smooths island coastlines using cellular automata
|
||
5. **Hole Fill Pass**: Fills small terrain holes
|
||
6. **Deep Water Pass**: Places deep water areas
|
||
7. **Oil Pass**: Generates sparse oil deposits as surface features
|
||
8. **Mineral Cluster Pass**: Generates mineral clusters (Hematite, Titanomagnetite, Gibbsite) on mountain edges using cellular automata
|
||
9. **Coal Pass**: Generates coal deposits using a cellular automata approach
|
||
|
||
Each pass operates independently with its own RNG state, ensuring deterministic results.
|
||
|
||
## Terrain Generation Pipeline
|
||
|
||
### Climate Generation
|
||
|
||
The biome pass uses dual noise generators for temperature and humidity:
|
||
- Separate Perlin noise for temperature/humidity at sub-chunk resolution
|
||
- Climate values mapped to 9 biome types in a 3×3 grid
|
||
- Sub-chunks store biome data for efficient terrain generation
|
||
|
||
### Noise System
|
||
|
||
The library addresses Perlin noise distribution issues:
|
||
- **Problem**: Raw Perlin noise has bell-curve distribution
|
||
- **Solution**: UniformPerlinNoise calibrates distribution to uniform [0,1]
|
||
- **Result**: Balanced terrain type ratios according to biome properties
|
||
|
||
### Terrain Generation Process
|
||
|
||
1. **Climate Sampling**: Sample temperature/humidity at sub-chunk centers
|
||
2. **Biome Assignment**: Map climate values to biome types
|
||
3. **Terrain Generation**: Generate tiles based on biome properties and noise
|
||
4. **Post-processing**: Apply smoothing and hole-filling algorithms
|
||
|
||
### Connected Component Analysis
|
||
|
||
Several passes use BFS (Breadth-First Search) for terrain analysis:
|
||
- **Mountain Smoothing**: Find and remove small mountain components
|
||
- **Island Smoothing**: Apply cellular automata for natural coastlines
|
||
- **Hole Filling**: Identify and fill isolated terrain holes
|
||
- Components touching map boundaries are preserved
|
||
|
||
### Resource Generation
|
||
|
||
The oil generation pass and mineral generation pass creates sparse resource deposits:
|
||
- **Poisson Disk Sampling**: Ensures minimum distance between oil fields
|
||
- **Biome Preference**: Higher probability in desert and plains biomes
|
||
- **Cluster Growth**: Random walk creates larger tile clusters
|
||
- **Surface Placement**: Oil appears as surface features on land/sand tiles, Minerals on mountain edges
|
||
|
||
## Random Number Generation
|
||
|
||
### Xoroshiro128++ Implementation
|
||
|
||
High-quality PRNG with excellent statistical properties:
|
||
- 128-bit internal state
|
||
- Period of 2^128 - 1
|
||
- Jump functions for parallel generation
|
||
- STL-compatible interface
|
||
|
||
### Seed Management
|
||
|
||
128-bit seeds provide extensive randomness:
|
||
- String-based deterministic seed creation
|
||
- Hardware random seed generation
|
||
- Independent RNG streams for each generation pass
|
||
|
||
## Biome System
|
||
|
||
### Climate Mapping
|
||
|
||
Biomes are determined by temperature/humidity combinations:
|
||
```
|
||
Dry Moderate Wet
|
||
Cold Snowy Snowy Frozen
|
||
Peaks Plains Ocean
|
||
Temp Plains Forest Ocean
|
||
Hot Desert Savanna Luke Ocean
|
||
```
|
||
|
||
### Biome Properties
|
||
|
||
Each biome defines terrain generation ratios:
|
||
- Water/Ice/Sand/Land ratios
|
||
- Noise parameters (octaves, persistence)
|
||
- Used by base terrain generation pass
|
||
|
||
## Performance Considerations
|
||
|
||
### Memory Layout
|
||
|
||
- Tiles packed into 1 byte (4 bits base + 4 bits surface)
|
||
- Chunks use contiguous 64×64 arrays for cache efficiency
|
||
- Sub-chunk biomes reduce memory overhead vs per-tile storage
|
||
|
||
### Generation Efficiency
|
||
|
||
- Sub-chunk resolution for biome generation (16×16 vs 64×64)
|
||
- Single-pass algorithms where possible
|
||
- Efficient connected component analysis using BFS
|
||
|
||
### Determinism
|
||
|
||
- Same seed produces identical results
|
||
- Independent RNG streams prevent cross-pass contamination
|
||
- Floating-point operations use consistent precision
|
||
|
||
## Adding New Generation Passes
|
||
|
||
To add a new generation pass:
|
||
|
||
1. **Create Pass Declaration**: Add a header file in `include/tilemap/pass/`, declaring a Pass class (e.g., `MyCustomPass`) that overloads `void operator()(TileMap &tilemap)`. See existing passes for structure and required members.
|
||
2. **Create Pass Implementation**: Add the corresponding implementation file in `src/tilemap/pass/`, implementing the declared class and its methods.
|
||
3. **Add to Pipeline**: Update `TerrainGenerator::operator()` to invoke your new pass in the desired order.
|
||
4. **RNG Management**: Use jump functions to create an independent RNG stream for your pass, ensuring deterministic results. Pass the RNG to your class constructor as needed.
|
||
5. **Configuration**: If your pass requires configuration parameters, add them to `GenerationConfig` and pass them to your class.
|
||
|
||
**Example header (include/tilemap/pass/my_custom_pass.h):**
|
||
```cpp
|
||
class MyCustomPass {
|
||
public:
|
||
MyCustomPass(const GenerationConfig &config, Xoroshiro128PP rng);
|
||
void operator()(TileMap &tilemap);
|
||
// ...other methods as needed...
|
||
};
|
||
```
|
||
|
||
**Example implementation (src/tilemap/pass/my_custom_pass.cpp):**
|
||
```cpp
|
||
MyCustomPass::MyCustomPass(const GenerationConfig &config, Xoroshiro128PP rng)
|
||
: config_(config), rng_(rng) {}
|
||
|
||
void MyCustomPass::operator()(TileMap &tilemap) {
|
||
// Process tilemap using config_ and rng_
|
||
// ...implementation...
|
||
}
|
||
```
|
||
|
||
**Pipeline integration:**
|
||
```cpp
|
||
void TerrainGenerator::operator()(TileMap &tilemap) {
|
||
// ...existing passes...
|
||
MyCustomPass custom_pass(config_, master_rng_.jump_96());
|
||
custom_pass(tilemap);
|
||
// ...other passes...
|
||
}
|
||
```
|
||
|
||
Refer to existing passes in `include/tilemap/pass/` and `src/tilemap/pass/` for detailed structure, member variables, and best practices.
|