From 1354d9c08a605a659305343a835f8d373b9cd83a Mon Sep 17 00:00:00 2001 From: szdytom Date: Sun, 3 Aug 2025 20:20:48 +0800 Subject: [PATCH] feat: remove unused files & code. rename demo Signed-off-by: szdytom --- tilemap/docs/mineral_generation.md | 122 ------------- tilemap/examples/CMakeLists.txt | 6 +- tilemap/examples/mineral_demo.cpp | 167 ------------------ .../{biome_demo.cpp => tilemap_demo.cpp} | 0 tilemap/include/tilemap/tile.h | 21 +-- 5 files changed, 9 insertions(+), 307 deletions(-) delete mode 100644 tilemap/docs/mineral_generation.md delete mode 100644 tilemap/examples/mineral_demo.cpp rename tilemap/examples/{biome_demo.cpp => tilemap_demo.cpp} (100%) diff --git a/tilemap/docs/mineral_generation.md b/tilemap/docs/mineral_generation.md deleted file mode 100644 index edb2cb1..0000000 --- a/tilemap/docs/mineral_generation.md +++ /dev/null @@ -1,122 +0,0 @@ -# 矿物生成系统实现总结 - -## 概述 - -为tilemap库实现了三种新矿石(Hematite赤铁矿、Titanomagnetite钛磁铁矿、Gibbsite三水铝石)的生成系统。该系统基于Oil生成方式的改进版本,专门针对山脉边缘的矿物分布进行了优化。 - -## 设计选择 - -### 为什么选择基于Oil的方案而不是胞元自动机? - -1. **精确控制性**:Poisson disk采样方式能够精确控制矿物密度和分布间距 -2. **效率优势**:单次随机游走比多轮胞元自动机迭代更高效 -3. **参数直观性**:密度、集群大小、最小距离等参数更易于调整和平衡 -4. **稀有资源特性**:矿物作为稀有资源,稀疏分布更符合游戏设计需求 - -## 核心特性 - -### 1. 位置限制 -- 矿物只在 `BaseTileType::Mountain` 且 `SurfaceTileType::Empty` 的瓦片上生成 -- 必须位于山脉边缘(至少有一个相邻瓦片不是山地) -- 确保矿物出现在山脉与其他地形的交界处,便于开采 - -### 2. 分层稀有度 -```cpp -// 默认配置 -hematite_density = 51; // ~0.2 per chunk (最常见) -titanomagnetite_density = 25; // ~0.1 per chunk (中等稀有) -gibbsite_density = 13; // ~0.05 per chunk (最稀有) -``` - -### 3. 集群生成 -- 最小集群大小:2个瓦片 -- 最大集群大小:5个瓦片 -- 使用随机游走算法形成自然的小簇分布 -- 40%概率跳过相邻瓦片,形成合适的密度 - -### 4. 距离控制 -- 基于密度动态计算最小间距 -- 确保矿物集群不会过于密集 -- 最小间距至少8个瓦片 - -## 实现细节 - -### 核心算法 -1. **Poisson disk采样**:生成候选位置,确保合适的分布 -2. **山脉边缘检测**:验证位置是否在山脉边缘 -3. **随机游走集群生长**:从中心点开始生成小簇 -4. **冲突避免**:确保不同矿物集群之间保持距离 - -### 山脉边缘检测逻辑 -```cpp -bool is_mountain_edge(const TileMap &tilemap, TilePos pos) const { - auto neighbors = tilemap.get_neighbors(pos); - for (const auto neighbor_pos : neighbors) { - const Tile &neighbor_tile = tilemap.get_tile(neighbor_pos); - if (neighbor_tile.base != BaseTileType::Mountain) { - return true; // 找到非山地邻居 - } - } - return false; // 所有邻居都是山地,不是边缘 -} -``` - -### 配置参数 -```cpp -struct GenerationConfig { - // 矿物集群生成参数 - std::uint8_t hematite_density = 51; // ~0.2 per chunk - std::uint8_t titanomagnetite_density = 25; // ~0.1 per chunk - std::uint8_t gibbsite_density = 13; // ~0.05 per chunk - - std::uint8_t mineral_cluster_min_size = 2; // 最小集群大小 - std::uint8_t mineral_cluster_max_size = 5; // 最大集群大小 - std::uint8_t mineral_base_probe = 192; // 基础放置概率 -}; -``` - -## 生成流水线集成 - -矿物生成作为独立的pass添加到地形生成流水线的最后阶段: - -```cpp -void TerrainGenerator::operator()(TileMap &tilemap) { - biome_pass(tilemap); - base_tile_type_pass(tilemap); - smoothen_mountains_pass(tilemap); - smoothen_islands_pass(tilemap); - mountain_hole_fill_pass(tilemap); - deepwater_pass(tilemap); - oil_pass(tilemap); - mineral_cluster_pass(tilemap); // 新增的矿物生成pass -} -``` - -## 测试结果 - -通过mineral_demo测试程序验证: -- 8x8 chunk地图 (262,144个瓦片) -- 山地瓦片:35,916个 (13.7%) -- 山脉边缘瓦片:15,881个 (44.2%的山地) -- 生成矿物分布: - - 赤铁矿:47个瓦片 - - 钛磁铁矿:38个瓦片 - - 三水铝石:15个瓦片 -- 山脉边缘矿物覆盖率:0.63% - -## 优势 - -1. **游戏平衡性**:稀有度分层,符合游戏经济设计 -2. **真实感**:矿物出现在山脉边缘,符合地质常识 -3. **可扩展性**:易于添加新的矿物类型和调整参数 -4. **性能优秀**:单次生成,不需要多轮迭代 -5. **确定性**:相同种子产生相同结果,支持多人游戏 - -## 使用建议 - -1. **密度调整**:根据游戏需求调整各矿物的density参数 -2. **集群大小**:可以为不同矿物设置不同的集群大小范围 -3. **生成位置**:如需其他位置生成矿物,可修改`is_suitable_for_mineral`函数 -4. **稀有度平衡**:建议保持gibbsite < titanomagnetite < hematite的稀有度关系 - -这个实现提供了灵活、高效且平衡的矿物生成系统,完全满足了"控制生成数量,以小簇方式生成在山的边缘"的需求。 diff --git a/tilemap/examples/CMakeLists.txt b/tilemap/examples/CMakeLists.txt index 85a6c5f..000a61b 100644 --- a/tilemap/examples/CMakeLists.txt +++ b/tilemap/examples/CMakeLists.txt @@ -4,6 +4,6 @@ cmake_minimum_required(VERSION 3.27) # Each example is built as a separate executable # Biome system demonstration -add_executable(biome_demo biome_demo.cpp) -target_link_libraries(biome_demo PRIVATE istd_tilemap) -target_include_directories(biome_demo PRIVATE ../include) +add_executable(tilemap_demo tilemap_demo.cpp) +target_link_libraries(tilemap_demo PRIVATE istd_tilemap) +target_include_directories(tilemap_demo PRIVATE ../include) diff --git a/tilemap/examples/mineral_demo.cpp b/tilemap/examples/mineral_demo.cpp deleted file mode 100644 index 5f6014d..0000000 --- a/tilemap/examples/mineral_demo.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "bmp.h" -#include "tilemap/generation.h" -#include "tilemap/tilemap.h" -#include - -using namespace istd; - -int main() { - constexpr std::uint8_t map_size = 8; // 8x8 chunks - TileMap tilemap(map_size); - - // Create generation config with adjusted mineral parameters - GenerationConfig config; - config.seed = Seed::from_string("mineral_demo_seed"); - - // Increase mineral density for demo - config.hematite_density = 102; // ~0.4 per chunk - config.titanomagnetite_density = 76; // ~0.3 per chunk - config.gibbsite_density = 51; // ~0.2 per chunk - - // Smaller clusters for better visibility - config.mineral_cluster_min_size = 1; - config.mineral_cluster_max_size = 4; - - // Generate the terrain - map_generate(tilemap, config); - - // Create BMP to visualize the mineral distribution - constexpr std::uint32_t tile_size = 4; // Each tile is 4x4 pixels - std::uint32_t image_size = map_size * Chunk::size * tile_size; - - BmpWriter bmp(image_size, image_size); - - // Define colors for different tile types - auto get_tile_color = [](const Tile &tile) - -> std::tuple { - // Override with mineral colors if present first - switch (tile.surface) { - case SurfaceTileType::Oil: - return {0, 0, 0}; // Black - case SurfaceTileType::Hematite: - return {255, 0, 0}; // Red - case SurfaceTileType::Titanomagnetite: - return {128, 0, 128}; // Purple - case SurfaceTileType::Gibbsite: - return {255, 255, 0}; // Yellow - case SurfaceTileType::Empty: - default: - break; // Fall through to base terrain colors - } - - // Base terrain colors - switch (tile.base) { - case BaseTileType::Land: - return {0, 128, 0}; // Green - case BaseTileType::Mountain: - return {139, 69, 19}; // Brown - case BaseTileType::Sand: - return {238, 203, 173}; // Beige - case BaseTileType::Water: - return {0, 0, 255}; // Blue - case BaseTileType::Ice: - return {173, 216, 230}; // Light Blue - case BaseTileType::Deepwater: - return {0, 0, 139}; // Dark Blue - default: - return {128, 128, 128}; // Gray - } - }; - - // Fill the BMP with tile data - for (std::uint32_t y = 0; y < image_size; ++y) { - for (std::uint32_t x = 0; x < image_size; ++x) { - // Calculate which tile this pixel belongs to - std::uint32_t tile_x = x / tile_size; - std::uint32_t tile_y = y / tile_size; - - TilePos pos = TilePos::from_global(tile_x, tile_y); - const Tile &tile = tilemap.get_tile(pos); - - auto [r, g, b] = get_tile_color(tile); - bmp.set_pixel(x, y, r, g, b); - } - } - - // Save the BMP - bmp.save("mineral_demo.bmp"); - - // Print statistics - std::uint32_t hematite_count = 0; - std::uint32_t titanomagnetite_count = 0; - std::uint32_t gibbsite_count = 0; - std::uint32_t mountain_edge_count = 0; - std::uint32_t total_mountain_count = 0; - - std::uint32_t total_tiles = map_size * Chunk::size * map_size * Chunk::size; - - for (std::uint32_t y = 0; y < map_size * Chunk::size; ++y) { - for (std::uint32_t x = 0; x < map_size * Chunk::size; ++x) { - TilePos pos = TilePos::from_global(x, y); - const Tile &tile = tilemap.get_tile(pos); - - if (tile.base == BaseTileType::Mountain) { - total_mountain_count++; - - // Check if it's a mountain edge - auto neighbors = tilemap.get_neighbors(pos); - bool is_edge = false; - for (const auto neighbor_pos : neighbors) { - const Tile &neighbor_tile = tilemap.get_tile(neighbor_pos); - if (neighbor_tile.base != BaseTileType::Mountain) { - is_edge = true; - break; - } - } - if (is_edge) { - mountain_edge_count++; - } - } - - switch (tile.surface) { - case SurfaceTileType::Hematite: - hematite_count++; - break; - case SurfaceTileType::Titanomagnetite: - titanomagnetite_count++; - break; - case SurfaceTileType::Gibbsite: - gibbsite_count++; - break; - default: - break; - } - } - } - - std::cout << "Mineral Generation Demo Results:\n"; - std::cout << "================================\n"; - std::cout << "Total tiles: " << total_tiles << "\n"; - std::cout << "Mountain tiles: " << total_mountain_count << " (" - << (100.0 * total_mountain_count / total_tiles) << "%)\n"; - std::cout << "Mountain edge tiles: " << mountain_edge_count << " (" - << (100.0 * mountain_edge_count / total_mountain_count) - << "% of mountains)\n"; - std::cout << "\nMineral Distribution:\n"; - std::cout << "Hematite tiles: " << hematite_count << "\n"; - std::cout << "Titanomagnetite tiles: " << titanomagnetite_count << "\n"; - std::cout << "Gibbsite tiles: " << gibbsite_count << "\n"; - std::cout << "Total mineral tiles: " - << (hematite_count + titanomagnetite_count + gibbsite_count) - << "\n"; - - if (mountain_edge_count > 0) { - double mineral_coverage = 100.0 - * (hematite_count + titanomagnetite_count + gibbsite_count) - / mountain_edge_count; - std::cout << "Mineral coverage on mountain edges: " << mineral_coverage - << "%\n"; - } - - std::cout << "\nGenerated mineral_demo.bmp with visualization\n"; - std::cout - << "Colors: Red=Hematite, Purple=Titanomagnetite, Yellow=Gibbsite\n"; - std::cout << " Brown=Mountain, Green=Land, Blue=Water, etc.\n"; - - return 0; -} diff --git a/tilemap/examples/biome_demo.cpp b/tilemap/examples/tilemap_demo.cpp similarity index 100% rename from tilemap/examples/biome_demo.cpp rename to tilemap/examples/tilemap_demo.cpp diff --git a/tilemap/include/tilemap/tile.h b/tilemap/include/tilemap/tile.h index cc6d5f4..21ca86d 100644 --- a/tilemap/include/tilemap/tile.h +++ b/tilemap/include/tilemap/tile.h @@ -6,35 +6,26 @@ namespace istd { enum class BaseTileType : std::uint8_t { + Mountain = 0x0, Land, - Mountain, Sand, Water, Ice, Deepwater, - _count }; enum class SurfaceTileType : std::uint8_t { - Empty, + Empty = 0, Oil, Hematite, Titanomagnetite, Gibbsite, - _count + + // Player built structures + // (not used in generation, but can be placed by player) + Structure = 0xF, }; -constexpr std::uint8_t base_tile_count = static_cast( - BaseTileType::_count -); - -constexpr std::uint8_t surface_tile_count = static_cast( - SurfaceTileType::_count -); - -static_assert(base_tile_count <= 16, "Base tile don't fit in 4 bits"); -static_assert(surface_tile_count <= 16, "Surface tile don't fit in 4 bits"); - struct Tile { BaseTileType base : 4; SurfaceTileType surface : 4;