diff options
| author | Mel <einebeere@gmail.com> | 2022-10-31 06:24:34 +0100 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2022-10-31 06:24:34 +0100 |
| commit | 23b0bc4d1ddc9fad3c32e8257497ddd13ac6a155 (patch) | |
| tree | 16ac3e0fa2964f026c857daa4ff6f0ca11520d46 /src/World/Generator.cpp | |
| parent | 1b2b0069c9b7ad73c6cc6663b020d0fd894f4567 (diff) | |
| download | meowcraft-23b0bc4d1ddc9fad3c32e8257497ddd13ac6a155.tar.zst meowcraft-23b0bc4d1ddc9fad3c32e8257497ddd13ac6a155.zip | |
Proto biomes and new blocks
Diffstat (limited to 'src/World/Generator.cpp')
| -rw-r--r-- | src/World/Generator.cpp | 178 |
1 files changed, 166 insertions, 12 deletions
diff --git a/src/World/Generator.cpp b/src/World/Generator.cpp index ee7ece9..875a79b 100644 --- a/src/World/Generator.cpp +++ b/src/World/Generator.cpp @@ -6,23 +6,46 @@ namespace MC::World { Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) { Chunk chunk(chunk_x, chunk_y); - uint8_t extent = 60; - uint8_t base = 4; + auto ocean_weights = ocean_weights_pass(chunk_x, chunk_y); + auto biome_weights = biome_weights_pass(chunk_x, chunk_y, ocean_weights); + auto heights = height_pass(chunk_x, chunk_y, biome_weights); + auto biomes = flat_biome_pass(biome_weights); - for (int x = 0; x < CHUNK_WIDTH; x++) { - for (int z = 0; z < CHUNK_WIDTH; z++) { - float noise = Math::noise2d( - {(float)chunk_x * CHUNK_WIDTH + x, (float)chunk_y * CHUNK_WIDTH + z} - ) * extent + base; + float extent = 60.0f; + float base = 4.0f; - uint height = std::round(noise); + for (int x = 0; x < Chunk::Width; x++) { + for (int z = 0; z < Chunk::Width; z++) { + uint32_t height = std::round(heights(x, z) * extent + base); - for (int y = 0; y < CHUNK_HEIGHT; y++) { + auto biome = biomes(x, z); + + BlockType top_block{}; + BlockType fill_block{}; + switch (biome) { + case BiomeType::Forest: + case BiomeType::Plains: + top_block = BlockType::Grass; + fill_block = BlockType::Dirt; + break; + case BiomeType::Desert: + top_block = BlockType::Sand; + fill_block = BlockType::Sand; + break; + case BiomeType::Ocean: + top_block = BlockType::Water; + fill_block = BlockType::Dirt; + break; + } + + for (int y = 0; y < Chunk::Height; y++) { BlockType type = BlockType::Air; - if (y < height) { - type = BlockType::Dirt; + if (y < (int32_t)height - 10) { + type = BlockType::Stone; + } else if (y < height) { + type = fill_block; } else if (y == height) { - type = BlockType::Grass; + type = top_block; } chunk.set(x, y, z, type); @@ -33,4 +56,135 @@ Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) { return chunk; } +Matrix<Chunk::Width, Chunk::Width> Generator::ocean_weights_pass(int64_t chunk_x, int64_t chunk_y) { + auto ocean_offset = 1125.0f; + auto ocean_scale = 0.05f; + + Matrix<Chunk::Width, Chunk::Width> ocean_weights{}; + for (int x = 0; x < Chunk::Width; x++) { + for (int y = 0; y < Chunk::Width; y++) { + float ocean_weight = Math::noise2d({ + (chunk_x * Chunk::Width + x) * ocean_scale + ocean_offset, + (chunk_y * Chunk::Width + y) * ocean_scale + ocean_offset + }); + + ocean_weights(x, y) = ocean_weight; + } + } + + return ocean_weights; +} + +Matrix<Chunk::Width, Chunk::Width, Vector<BiomeType::Size>> Generator::biome_weights_pass( + int64_t chunk_x, + int64_t chunk_y, + Matrix<Chunk::Width, Chunk::Width, float> ocean_weights +) { + auto ocean_threshold = 0.4f; + + std::vector<float> biome_offsets = {110.0f, 2450.0f, 5042.0f}; + auto biome_scale = 0.15f; + + Matrix<Chunk::Width, Chunk::Width, Vector<BiomeType::Size>> biome_weights{}; + for (int x = 0; x < Chunk::Width; x++) { + for (int y = 0; y < Chunk::Width; y++) { + Vector<BiomeType::Size> weights{}; + for (auto biome : MC::World::BiomeType::all_ground()) { + float biome_noise = Math::noise2d({ + (chunk_x * Chunk::Width + x) * biome_scale + biome_offsets[biome], + (chunk_y * Chunk::Width + y) * biome_scale + biome_offsets[biome] + }); + + weights[biome] = biome_noise; + } + + bool ocean_weight = ocean_weights(x, y) < ocean_threshold; + weights[MC::World::BiomeType::Ocean] = ocean_weight; + + biome_weights(x,y) = weights; + } + } + + return biome_weights; +} + +Matrix<Chunk::Width, Chunk::Width> Generator::height_pass( + int64_t chunk_x, + int64_t chunk_y, + Matrix<Chunk::Width, Chunk::Width, Vector<BiomeType::Size>> biome_weights +) { + auto height_offset = 6050.0f; + auto height_scale = 0.7f; + + Matrix<Chunk::Width, Chunk::Width> heights{}; + for (int x = 0; x < Chunk::Width; x++) { + for (int y = 0; y < Chunk::Width; y++) { + auto weights = biome_weights(x, y); + + auto total_weight = 0.0f; + for (auto biome : MC::World::BiomeType::all()) { + total_weight += weights[biome]; + } + + std::pair<float, float> total_effect{}; + for (auto biome : MC::World::BiomeType::all()) { + auto weight = weights[biome]; + + std::pair<float, float> effect{}; + switch (biome) { + case MC::World::BiomeType::Forest: + effect = {0.5f, 0.45f}; + break; + case MC::World::BiomeType::Plains: + effect = {0.4f, 0.4f}; + break; + case MC::World::BiomeType::Desert: + effect = {0.6f, 0.35f}; + break; + case MC::World::BiomeType::Ocean: + effect = {0.0f, 0.0f}; + break; + } + + total_effect = { + total_effect.first + effect.first * (weight / total_weight), + total_effect.second + effect.second * (weight / total_weight), + }; + } + + float height = Math::noise2d({ + (chunk_x * Chunk::Width + x) * height_scale + height_offset, + (chunk_y * Chunk::Width + y) * height_scale + height_offset + }) * total_effect.first + total_effect.second; + + heights(x, y) = height; + } + } + + return heights; +} + +Matrix<Chunk::Width, Chunk::Width, BiomeType> Generator::flat_biome_pass( + Matrix<Chunk::Width, Chunk::Width, Vector<BiomeType::Size>> biome_weights +) { + Matrix<Chunk::Width, Chunk::Width, BiomeType> biomes{}; + for (int x = 0; x < Chunk::Width; x++) { + for (int y = 0; y < Chunk::Width; y++) { + auto weights = biome_weights(x, y); + + std::pair<MC::World::BiomeType, float> max_biome{MC::World::BiomeType::Plains, 0.0f}; + for (auto biome : MC::World::BiomeType::all()) { + auto weight = weights[biome]; + if (weight > max_biome.second) { + max_biome = {biome, weight}; + } + } + + biomes(x, y) = max_biome.first; + } + } + + return biomes; +} + } \ No newline at end of file |
