From bb888fd7b7fdbae5847e3327f3b82d258b384323 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sat, 18 Apr 2026 10:59:37 +0800 Subject: [PATCH] feat: add tree generation --- CMakeLists.txt | 2 + assets/texture/block/leaf/back.png | Bin 0 -> 99 bytes assets/texture/block/leaf/base.png | Bin 0 -> 99 bytes assets/texture/block/leaf/front.png | Bin 0 -> 99 bytes assets/texture/block/leaf/left.png | Bin 0 -> 99 bytes assets/texture/block/leaf/right.png | Bin 0 -> 99 bytes assets/texture/block/leaf/top.png | Bin 0 -> 99 bytes assets/texture/block/log/back.png | Bin 0 -> 99 bytes assets/texture/block/log/base.png | Bin 0 -> 99 bytes assets/texture/block/log/front.png | Bin 0 -> 99 bytes assets/texture/block/log/left.png | Bin 0 -> 99 bytes assets/texture/block/log/right.png | Bin 0 -> 99 bytes assets/texture/block/log/top.png | Bin 0 -> 99 bytes include/Cubed/app.hpp | 6 +- include/Cubed/config.hpp | 2 +- include/Cubed/gameplay/biome.hpp | 6 +- include/Cubed/gameplay/chunk.hpp | 2 +- include/Cubed/gameplay/tree.hpp | 12 ++++ include/Cubed/tools/cubed_random.hpp | 21 ++++++ include/Cubed/tools/perlin_noise.hpp | 2 +- src/app.cpp | 17 +++-- src/gameplay/chunk.cpp | 37 ++++++++-- src/gameplay/tree.cpp | 98 +++++++++++++++++++++++++++ src/main.cpp | 2 +- src/map_table.cpp | 4 +- src/tools/cubed_random.cpp | 34 ++++++++++ src/tools/perlin_noise.cpp | 9 ++- 27 files changed, 224 insertions(+), 30 deletions(-) create mode 100644 assets/texture/block/leaf/back.png create mode 100644 assets/texture/block/leaf/base.png create mode 100644 assets/texture/block/leaf/front.png create mode 100644 assets/texture/block/leaf/left.png create mode 100644 assets/texture/block/leaf/right.png create mode 100644 assets/texture/block/leaf/top.png create mode 100644 assets/texture/block/log/back.png create mode 100644 assets/texture/block/log/base.png create mode 100644 assets/texture/block/log/front.png create mode 100644 assets/texture/block/log/left.png create mode 100644 assets/texture/block/log/right.png create mode 100644 assets/texture/block/log/top.png create mode 100644 include/Cubed/gameplay/tree.hpp create mode 100644 include/Cubed/tools/cubed_random.hpp create mode 100644 src/gameplay/tree.cpp create mode 100644 src/tools/cubed_random.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7946714..4b0f96e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,12 +85,14 @@ add_executable(${PROJECT_NAME} src/gameplay/biome.cpp src/gameplay/chunk.cpp src/gameplay/player.cpp + src/gameplay/tree.cpp src/gameplay/world.cpp src/input.cpp src/map_table.cpp src/renderer.cpp src/shader.cpp src/texture_manager.cpp + src/tools/cubed_random.cpp src/tools/math_tools.cpp src/tools/shader_tools.cpp src/tools/font.cpp diff --git a/assets/texture/block/leaf/back.png b/assets/texture/block/leaf/back.png new file mode 100644 index 0000000000000000000000000000000000000000..16d842672f5599661a5fd0ab357814f30f8ac2f1 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le u&)iD?Fu#%MfJ^7IKxQ{y3DX1vNd|@kQ<=)oa~}m6!{F)a=d#Wzp$PzSgTe~DWM4fT4NdN literal 0 HcmV?d00001 diff --git a/assets/texture/block/log/base.png b/assets/texture/block/log/base.png new file mode 100644 index 0000000000000000000000000000000000000000..d05532c95b0399e331e740d29cc62b50b19c1f47 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le veKwo?Iq$%ju*l`}3dY53JyHfUco-OFGBLg{lfBFbRLJ1z>gTe~DWM4fT4NdN literal 0 HcmV?d00001 diff --git a/assets/texture/block/log/front.png b/assets/texture/block/log/front.png new file mode 100644 index 0000000000000000000000000000000000000000..d05532c95b0399e331e740d29cc62b50b19c1f47 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le veKwo?Iq$%ju*l`}3dY53JyHfUco-OFGBLg{lfBFbRLJ1z>gTe~DWM4fT4NdN literal 0 HcmV?d00001 diff --git a/assets/texture/block/log/left.png b/assets/texture/block/log/left.png new file mode 100644 index 0000000000000000000000000000000000000000..d05532c95b0399e331e740d29cc62b50b19c1f47 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le veKwo?Iq$%ju*l`}3dY53JyHfUco-OFGBLg{lfBFbRLJ1z>gTe~DWM4fT4NdN literal 0 HcmV?d00001 diff --git a/assets/texture/block/log/right.png b/assets/texture/block/log/right.png new file mode 100644 index 0000000000000000000000000000000000000000..d05532c95b0399e331e740d29cc62b50b19c1f47 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le veKwo?Iq$%ju*l`}3dY53JyHfUco-OFGBLg{lfBFbRLJ1z>gTe~DWM4fT4NdN literal 0 HcmV?d00001 diff --git a/assets/texture/block/log/top.png b/assets/texture/block/log/top.png new file mode 100644 index 0000000000000000000000000000000000000000..d05532c95b0399e331e740d29cc62b50b19c1f47 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le veKwo?Iq$%ju*l`}3dY53JyHfUco-OFGBLg{lfBFbRLJ1z>gTe~DWM4fT4NdN literal 0 HcmV?d00001 diff --git a/include/Cubed/app.hpp b/include/Cubed/app.hpp index 0dae470..3df83f2 100644 --- a/include/Cubed/app.hpp +++ b/include/Cubed/app.hpp @@ -6,6 +6,7 @@ #include #include #include +namespace Cubed { class App { public: @@ -35,7 +36,6 @@ private: inline static double fps_time_count = 0.0f; inline static int frame_count = 0; inline static int fps = 0; - inline static unsigned int m_seed = 0; void init(); @@ -46,4 +46,6 @@ private: void render(); void run(); void update(); -}; \ No newline at end of file +}; + +} \ No newline at end of file diff --git a/include/Cubed/config.hpp b/include/Cubed/config.hpp index 03dbb5a..2e8e32d 100644 --- a/include/Cubed/config.hpp +++ b/include/Cubed/config.hpp @@ -1,6 +1,6 @@ #pragma once constexpr int WORLD_SIZE_Y = 256; -constexpr int MAX_BLOCK_NUM = 5; +constexpr int MAX_BLOCK_NUM = 7; constexpr int MAX_UI_NUM = 1; constexpr int CHUCK_SIZE = 16; diff --git a/include/Cubed/gameplay/biome.hpp b/include/Cubed/gameplay/biome.hpp index 3492852..54ee2c4 100644 --- a/include/Cubed/gameplay/biome.hpp +++ b/include/Cubed/gameplay/biome.hpp @@ -4,9 +4,9 @@ constexpr float BIOME_NOISE_FREQUENCY = 0.003f; -constexpr float PLAIN_FREQ = 0.5f; -constexpr float FOREST_FREQ = 1.0f; -constexpr float DESERT_FREQ = 1.0f; +constexpr float PLAIN_FREQ = 0.4f; +constexpr float FOREST_FREQ = 1.2f; +constexpr float DESERT_FREQ = 1.2f; constexpr float MOUNTAIN_FREQ = 2.0f; enum class Biome { diff --git a/include/Cubed/gameplay/chunk.hpp b/include/Cubed/gameplay/chunk.hpp index 19944cb..cbe2844 100644 --- a/include/Cubed/gameplay/chunk.hpp +++ b/include/Cubed/gameplay/chunk.hpp @@ -47,7 +47,7 @@ public: const std::vector& get_chunk_blocks() const; static int get_index(int x, int y, int z); - + static int get_index(const glm::vec3& pos); void init_chunk(); void gen_vertex_data(); // 0 : (1, 0) diff --git a/include/Cubed/gameplay/tree.hpp b/include/Cubed/gameplay/tree.hpp new file mode 100644 index 0000000..051e0b5 --- /dev/null +++ b/include/Cubed/gameplay/tree.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +class Chunk; + +struct TreeStructNode { + glm::ivec3 offset{0, 0, 0}; + unsigned id = 0; +}; + +bool build_tree(Chunk& chunk, const glm::ivec3& pos); \ No newline at end of file diff --git a/include/Cubed/tools/cubed_random.hpp b/include/Cubed/tools/cubed_random.hpp new file mode 100644 index 0000000..68f3ba3 --- /dev/null +++ b/include/Cubed/tools/cubed_random.hpp @@ -0,0 +1,21 @@ +#pragma once +#include +namespace Cubed { + +class Random { +public: + Random(); + + static Random& get(); + + bool random_bool(double probability); + std::mt19937& engine(); + unsigned seed(); + +private: + unsigned int m_seed = 0; + std::mt19937 m_engine; +}; + + +} diff --git a/include/Cubed/tools/perlin_noise.hpp b/include/Cubed/tools/perlin_noise.hpp index 5faafa2..578d9f3 100644 --- a/include/Cubed/tools/perlin_noise.hpp +++ b/include/Cubed/tools/perlin_noise.hpp @@ -4,7 +4,7 @@ class PerlinNoise { public: - static void init(unsigned int seed); + static void init(); static float noise(float x, float y, float z); private: static inline bool is_init = false; diff --git a/src/app.cpp b/src/app.cpp index 4cf5cd0..1a3c9e9 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -4,11 +4,14 @@ #include #include #include +#include #include #include #include -#include + +namespace Cubed { + App::App() { @@ -36,10 +39,8 @@ void App::init() { glfwSetWindowFocusCallback(m_window.get_glfw_window(), window_focus_callback); glfwSetWindowSizeCallback(m_window.get_glfw_window(), window_reshape_callback); glfwSetKeyCallback(m_window.get_glfw_window(), key_callback); - std::random_device d; - m_seed = d(); - Logger::info("Seed: {}", m_seed); - PerlinNoise::init(m_seed); + + PerlinNoise::init(); m_renderer.init(); Logger::info("Renderer Init Success"); @@ -204,14 +205,12 @@ int App::start_cubed_application(int argc, char** argv) { return 1; } -unsigned int App::seed() { - return m_seed; -} - float App::delte_time() { return delta_time; } float App::get_fps() { return fps; +} + } \ No newline at end of file diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp index 0edfe1f..d21e8c3 100644 --- a/src/gameplay/chunk.cpp +++ b/src/gameplay/chunk.cpp @@ -1,6 +1,8 @@ #include +#include #include #include +#include #include #include #include @@ -59,6 +61,11 @@ int Chunk::get_index(int x, int y, int z) { } return (x * WORLD_SIZE_Y + y) * CHUCK_SIZE + z; } + +int Chunk::get_index(const glm::vec3& pos) { + return Chunk::get_index(pos.x, pos.y, pos.z); +} + // this is thread-unsafe! void Chunk::gen_vertex_data() { m_vertexs_data.clear(); @@ -274,7 +281,7 @@ void Chunk::resolve_blocks() { } } } - + std::array, SIZE_X> heights; for (int x = 0; x < CHUCK_SIZE; x++) { for (int z = 0; z < CHUCK_SIZE; z++) { @@ -284,12 +291,13 @@ void Chunk::resolve_blocks() { float temp = PerlinNoise::noise(world_x * BIOME_NOISE_FREQUENCY, 0.0f, world_z * BIOME_NOISE_FREQUENCY); float humid = PerlinNoise::noise(world_x * BIOME_NOISE_FREQUENCY, 1.0f, world_z * BIOME_NOISE_FREQUENCY); int height = get_interpolated_height(world_x, world_z, temp, humid); + heights[x][z] = height; auto biome = get_biome_from_noise(temp, humid); for (int y = 5; y < height - 5; y++) { m_blocks[get_index(x, y, z)] = 3; } if (biome == Biome::MOUNTAIN) { - for (int y = height - 5; y < height - 1; y++) { + for (int y = height - 5; y <= height - 1; y++) { if (y > 101) { m_blocks[get_index(x, y, z)] = 3; } else { @@ -297,26 +305,43 @@ void Chunk::resolve_blocks() { } } - if (height - 1 > 101) { + if (height > 101) { m_blocks[get_index(x, height - 1, z)] = 3; } else { m_blocks[get_index(x, height - 1, z)] = 1; } } else if (biome == Biome::DESERT) { - for (int y = height - 5; y < height; y++) { + for (int y = height - 5; y <= height; y++) { m_blocks[get_index(x, y, z)] = 4; } } else { - for (int y = height - 5; y < height - 1; y++) { + for (int y = height - 5; y <= height - 1; y++) { m_blocks[get_index(x, y, z)] = 2; } - for (int y = height - 1; y < height; y++) { + for (int y = height; y <= height; y++) { m_blocks[get_index(x, y, z)] = 1; } } } } + if (m_biome == Biome::FOREST) { + std::array x_arr; + std::ranges::iota(x_arr, 0); + std::shuffle(x_arr.begin(), x_arr.end(), Cubed::Random::get().engine()); + std::array z_arr; + std::ranges::iota(z_arr, 0); + std::shuffle(z_arr.begin(), z_arr.end(), Cubed::Random::get().engine()); + for (auto x : x_arr) { + for (auto z : z_arr) { + if (Cubed::Random::get().random_bool(0.8)) { + build_tree(*this, {x, heights[x][z], z}); + } + + } + } + } + mark_dirty(); } diff --git a/src/gameplay/tree.cpp b/src/gameplay/tree.cpp new file mode 100644 index 0000000..23b361b --- /dev/null +++ b/src/gameplay/tree.cpp @@ -0,0 +1,98 @@ +#include + +#include + +#include + +using glm::ivec3; + +static constexpr std::array TREE {{ + {{0, 1, 0}, 5}, + {{0, 2, 0}, 5}, + {{0, 3, 0}, 5}, + {{0, 4, 0}, 5}, + {{0, 5, 0}, 5}, + {{0, 6, 0}, 6}, + {{0, 5, 1}, 6}, + {{1, 5, 0}, 6}, + {{0, 5, -1}, 6}, + {{-1, 5, 0}, 6}, + {{1, 5, 1}, 6}, + {{1, 5, -1}, 6}, + {{-1, 5, -1}, 6}, + {{-1, 5, 1}, 6}, + {{0, 4, 1}, 6}, + {{1, 4, 0}, 6}, + {{0, 4, -1}, 6}, + {{-1, 4, 0}, 6}, + {{1, 4, 1}, 6}, + {{1, 4, -1}, 6}, + {{-1, 4, -1}, 6}, + {{-1, 4, 1}, 6}, + {{0, 4, 2}, 6}, + {{2, 4, 0}, 6}, + {{0, 4, -2}, 6}, + {{-2, 4, 0}, 6}, + {{2, 4, 2}, 6}, + {{2, 4, -2}, 6}, + {{-2, 4, -2}, 6}, + {{-2, 4, 2}, 6}, + {{1, 4, 2}, 6}, + {{2, 4, 1}, 6}, + {{-1, 4, 2}, 6}, + {{2, 4, -1}, 6}, + {{1, 4, -2}, 6}, + {{-2, 4, 1}, 6}, + {{-1, 4, -2}, 6}, + {{-2, 4, -1}, 6}, + {{0, 3, 1}, 6}, + {{1, 3, 0}, 6}, + {{0, 3, -1}, 6}, + {{-1, 3, 0}, 6}, + {{1, 3, 1}, 6}, + {{1, 3, -1}, 6}, + {{-1, 3, -1}, 6}, + {{-1, 3, 1}, 6}, + {{0, 3, 2}, 6}, + {{2, 3, 0}, 6}, + {{0, 3, -2}, 6}, + {{-2, 3, 0}, 6}, + {{2, 3, 2}, 6}, + {{2, 3, -2}, 6}, + {{-2, 3, -2}, 6}, + {{-2, 3, 2}, 6}, + {{1, 3, 2}, 6}, + {{2, 3, 1}, 6}, + {{-1, 3, 2}, 6}, + {{2, 3, -1}, 6}, + {{1, 3, -2}, 6}, + {{-2, 3, 1}, 6}, + {{-1, 3, -2}, 6}, + {{-2, 3, -1}, 6}, +}}; + +bool build_tree(Chunk& chunk, const glm::ivec3& pos) { + auto& block = chunk.get_chunk_blocks(); + + if (block[Chunk::get_index(pos)] != 1) { + Logger::info("Root is not Grass Block"); + return false; + } + for (const auto& d : TREE) { + auto tree_node = pos + d.offset; + int x = tree_node.x; + int y = tree_node.y; + int z = tree_node.z; + if (x < 0 || y < 0 || z < 0 || x >= CHUCK_SIZE || y >= WORLD_SIZE_Y || z >= CHUCK_SIZE) { + return false; + } + if (block[Chunk::get_index(tree_node)] != 0) { + return false; + } + } + for (const auto& d : TREE) { + auto tree_node = pos + d.offset; + chunk.set_chunk_block(Chunk::get_index(tree_node), d.id); + } + return true; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4aed757..8d70a54 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include int main(int argc, char** argv) { - return App::start_cubed_application(argc, argv); + return Cubed::App::start_cubed_application(argc, argv); } diff --git a/src/map_table.cpp b/src/map_table.cpp index 52ffdfd..3448b59 100644 --- a/src/map_table.cpp +++ b/src/map_table.cpp @@ -13,7 +13,9 @@ constexpr std::array BLOCK_REISTER{ "grass_block", "dirt", "stone", - "sand" + "sand", + "log", + "leaf" }; diff --git a/src/tools/cubed_random.cpp b/src/tools/cubed_random.cpp new file mode 100644 index 0000000..7a346e1 --- /dev/null +++ b/src/tools/cubed_random.cpp @@ -0,0 +1,34 @@ +#include + +#include + +namespace Cubed { + +Random::Random() { + std::random_device d; + m_seed = d(); + Logger::info("Seed: {}", m_seed); + m_engine.seed(m_seed); +} + +Random& Random::get() { + static Random instance; + return instance; +} + +bool Random::random_bool(double probability) { + std::bernoulli_distribution dist(probability); + return dist(m_engine); +} + +std::mt19937& Random::engine() { + return m_engine; +} + +unsigned Random::seed() { + return m_seed; +} + + + +} \ No newline at end of file diff --git a/src/tools/perlin_noise.cpp b/src/tools/perlin_noise.cpp index a73d273..66ac858 100644 --- a/src/tools/perlin_noise.cpp +++ b/src/tools/perlin_noise.cpp @@ -2,17 +2,16 @@ #include #include - +#include #include #include -#include -void PerlinNoise::init(unsigned int seed) { + +void PerlinNoise::init() { p.resize(256); std::iota(p.begin(), p.end(), 0); - std::mt19937 engine(seed); - std::shuffle(p.begin(), p.end(), engine); + std::shuffle(p.begin(), p.end(), Cubed::Random::get().engine()); p.insert(p.end(), p.begin(), p.end()); is_init = true;