From 668fa9a57d5124994877afc16387e3c630661eaf Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sat, 7 Mar 2026 17:00:05 +0800 Subject: [PATCH] feat: add world class --- CMakeLists.txt | 2 + include/Cubed/config.hpp | 5 +- include/Cubed/gameplay/block.hpp | 23 ++++ include/Cubed/gameplay/chuck.hpp | 23 ++++ include/Cubed/gameplay/chuck_status.hpp | 15 +++ include/Cubed/gameplay/world.hpp | 21 ++++ src/gameplay/chuck.cpp | 28 +++++ src/gameplay/world.cpp | 76 ++++++++++++++ src/main.cpp | 81 ++++++-------- src/map_table.cpp | 6 +- src/texture_manager.cpp | 9 +- src/tools/shader_tools.cpp | 134 +++++++++++++----------- 12 files changed, 303 insertions(+), 120 deletions(-) create mode 100644 include/Cubed/gameplay/block.hpp create mode 100644 include/Cubed/gameplay/chuck.hpp create mode 100644 include/Cubed/gameplay/chuck_status.hpp create mode 100644 include/Cubed/gameplay/world.hpp create mode 100644 src/gameplay/chuck.cpp create mode 100644 src/gameplay/world.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a36bebc..b903707 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,9 @@ set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) add_executable(${PROJECT_NAME} src/main.cpp src/camera.cpp + src/gameplay/chuck.cpp src/gameplay/player.cpp + src/gameplay/world.cpp src/map_table.cpp src/texture_manager.cpp src/tools/shader_tools.cpp diff --git a/include/Cubed/config.hpp b/include/Cubed/config.hpp index 578a580..2cde977 100644 --- a/include/Cubed/config.hpp +++ b/include/Cubed/config.hpp @@ -1,4 +1,7 @@ #pragma once constexpr int WORLD_SIZE_X = 32; constexpr int WORLD_SIZE_Z = 32; -constexpr int MAX_BLOCK_NUM = 1; \ No newline at end of file +constexpr int WORLD_SIZE_Y = 16; +constexpr int MAX_BLOCK_NUM = 2; +constexpr int CHUCK_SIZE = 16; +constexpr int DISTANCE = 1; \ No newline at end of file diff --git a/include/Cubed/gameplay/block.hpp b/include/Cubed/gameplay/block.hpp new file mode 100644 index 0000000..cd02ffd --- /dev/null +++ b/include/Cubed/gameplay/block.hpp @@ -0,0 +1,23 @@ +#pragma once +#include +#include +#include +#include + + + +struct BlockTexture { + std::string name; + unsigned id; + std::vector texture; +}; + +struct Block : public BlockTexture{ + +}; + +struct BlockRenderData { + glm::vec3 pos; + std::vector draw_face; + unsigned block_id; +}; \ No newline at end of file diff --git a/include/Cubed/gameplay/chuck.hpp b/include/Cubed/gameplay/chuck.hpp new file mode 100644 index 0000000..6ed83a9 --- /dev/null +++ b/include/Cubed/gameplay/chuck.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include +#include +#include + + + +class Chuck { +private: + + // the index is a array of block id + std::vector m_blocks; + +public: + Chuck(); + ~Chuck(); + const std::vector& get_chuck_blocks() const; + void init_chuck(); + static int get_index(int x, int y, int z); +}; \ No newline at end of file diff --git a/include/Cubed/gameplay/chuck_status.hpp b/include/Cubed/gameplay/chuck_status.hpp new file mode 100644 index 0000000..6ff204a --- /dev/null +++ b/include/Cubed/gameplay/chuck_status.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +struct ChuckPos { + int x; + int y; + bool operator==(const ChuckPos&) const = default; + struct Hash { + std::size_t operator()(const ChuckPos& pos) const{ + std::size_t h1 = std::hash{}(pos.x); + std::size_t h2 = std::hash{}(pos.y); + return h1 ^ (h2 << 1); + } + }; +}; + diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp new file mode 100644 index 0000000..a3c55c9 --- /dev/null +++ b/include/Cubed/gameplay/world.hpp @@ -0,0 +1,21 @@ +#pragma once +#include + +#include + +class World { +private: + BlockRenderData m_block_render_data; + std::unordered_map m_chucks; + +public: + + World(); + ~World(); + + const BlockRenderData& get_block_render_data(int x, int y ,int z); + void init_world(); + void render(); + + +}; \ No newline at end of file diff --git a/src/gameplay/chuck.cpp b/src/gameplay/chuck.cpp new file mode 100644 index 0000000..aa61a51 --- /dev/null +++ b/src/gameplay/chuck.cpp @@ -0,0 +1,28 @@ +#include + +Chuck::Chuck() { + init_chuck(); +} + +Chuck::~Chuck() { + +} + +const std::vector& Chuck::get_chuck_blocks() const{ + return m_blocks; +} + +void Chuck::init_chuck() { + m_blocks.assign(CHUCK_SIZE * CHUCK_SIZE * CHUCK_SIZE, 0); + for (int x = 0; x < CHUCK_SIZE; x++) { + for (int y = 0; y < 2; y++) { + for (int z = 0; z < CHUCK_SIZE; z++) { + m_blocks[get_index(x, y, z)] = 1; + } + } + } +} + +int Chuck::get_index(int x, int y, int z) { + return x * CHUCK_SIZE * CHUCK_SIZE + y * CHUCK_SIZE + z; +} diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp new file mode 100644 index 0000000..e505406 --- /dev/null +++ b/src/gameplay/world.cpp @@ -0,0 +1,76 @@ +#include +#include +World::World() { + +} + +World::~World() { + +} +static int chuck_x, chuck_z; +const BlockRenderData& World::get_block_render_data(int world_x, int world_y ,int world_z) { + + chuck_x = world_x / CHUCK_SIZE; + chuck_z = world_z / CHUCK_SIZE; + + auto it = m_chucks.find((ChuckPos){chuck_x, chuck_z}); + CUBED_ASSERT_MSG(it != m_chucks.end(), "Chuck not find"); + + const auto& chuck_blocks = it->second.get_chuck_blocks(); + int x, y, z; + y = world_y; + x = world_x - chuck_x * CHUCK_SIZE; + z = world_z - chuck_z * CHUCK_SIZE; + // block id + m_block_render_data.block_id = chuck_blocks[Chuck::get_index(x, y, z)]; + // draw_face + m_block_render_data.draw_face.assign(6, true); + if (x > 0 ) { + if (x > 0 && chuck_blocks[Chuck::get_index(x - 1, y, z)]) { + m_block_render_data.draw_face[3] = false; + } + } + if (x < CHUCK_SIZE - 1) { + if (x < DISTANCE * CHUCK_SIZE - 1 && chuck_blocks[Chuck::get_index(x + 1, y, z)]) { + m_block_render_data.draw_face[1] = false; + } + } + if (z > 0 ) { + if (z > 0 && chuck_blocks[Chuck::get_index(x, y, z - 1)]) { + m_block_render_data.draw_face[2] = false; + } + } + if (z < CHUCK_SIZE - 1) { + if (z < DISTANCE * CHUCK_SIZE - 1 && chuck_blocks[Chuck::get_index(x, y, z + 1)]) { + m_block_render_data.draw_face[0] = false; + } + } + if (y > 0 ) { + if (y > 0 && chuck_blocks[Chuck::get_index(x, y - 1, z)]) { + m_block_render_data.draw_face[5] = false; + } + } + if (y < CHUCK_SIZE - 1) { + if (y < CHUCK_SIZE - 1 && chuck_blocks[Chuck::get_index(x, y + 1, z)]) { + m_block_render_data.draw_face[4] = false; + } + } + + + return m_block_render_data; +} + +void World::init_world() { + for (int s = 0; s < DISTANCE; s++) { + for (int t = 0; t < DISTANCE; t++) { + ChuckPos pos{s, t}; + Chuck chuck; + m_chucks[pos] = chuck; + } + } + +} + +void World::render() { + +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 50a2d3c..7a4a22c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -11,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +19,7 @@ constexpr int NUM_VAO = 1; constexpr int NUM_VBO = 3; -bool block_present[WORLD_SIZE_X][WORLD_SIZE_Z] = {false}; + GLuint rendering_program; GLuint vao[NUM_VAO]; GLuint vbo[NUM_VBO]; @@ -31,10 +31,11 @@ float inc = 0.01f; float tf = 0.0f; double last_time = 0.0f; double delta_time = 0.0f; -std::vector grass_block_texture; + Player player; Camera camera; TextureManager texture_manager; +World world; void setup_vertices(void) { float vertices_pos[108] = { // ===== front (z = +1) ===== @@ -164,15 +165,6 @@ void init(GLFWwindow* window) { aspect = (float)width / (float)height; glViewport(0, 0, width, height); p_mat = glm::perspective(glm::radians(60.0f), aspect, 0.1f, 1000.0f); - // Must call after texture_manager.init_texture(); - grass_block_texture = texture_manager.get_block_texture("grass_block").texture; - - for (int i = 0; i < 6; i++) { - glBindTexture(GL_TEXTURE_2D, grass_block_texture[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glGenerateMipmap(GL_TEXTURE_2D); - } glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); @@ -203,11 +195,6 @@ void display(GLFWwindow* window, double current_time) { player.update(delta_time); camera.update_move_camera(); - for (int i = 0; i < WORLD_SIZE_X; i++) { - for (int j = 0; j < WORLD_SIZE_Z; j++) { - block_present[i][j] = true; - } - } glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); @@ -226,45 +213,36 @@ void display(GLFWwindow* window, double current_time) { glEnableVertexAttribArray(1); glActiveTexture(GL_TEXTURE0); - for (int x = 0; x < WORLD_SIZE_X; x++) { - for (int z = 0; z < WORLD_SIZE_Z; z++) { + for (int x = 0; x < DISTANCE * CHUCK_SIZE; x++) { + for (int z = 0; z < DISTANCE * CHUCK_SIZE; z++) { + for (int y = 0; y < CHUCK_SIZE; y++) { - int wx = x - WORLD_SIZE_X / 2; - int wz = z - WORLD_SIZE_Z / 2; + m_mat = glm::translate(glm::mat4(1.0f), glm::vec3((float)x, y, (float)z)); + v_mat = camera.get_camera_lookat(); + mv_mat = v_mat * m_mat; + glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat)); + glUniformMatrix4fv(proj_loc, 1 ,GL_FALSE, glm::value_ptr(p_mat)); - m_mat = glm::translate(glm::mat4(1.0f), glm::vec3((float)wx, 0.0f, (float)wz)); - v_mat = camera.get_camera_lookat(); - mv_mat = v_mat * m_mat; - glUniformMatrix4fv(mv_loc, 1, GL_FALSE, glm::value_ptr(mv_mat)); - glUniformMatrix4fv(proj_loc, 1 ,GL_FALSE, glm::value_ptr(p_mat)); - - bool draw_face[6] = {true, true, true, true, true, true}; - - if (z < WORLD_SIZE_Z - 1&& block_present[x][z + 1]) { - draw_face[0] = false; - } - if (x < WORLD_SIZE_X - 1 && block_present[x + 1][z]) { - draw_face[1] = false; - } - if (z > 0 && block_present[x][z - 1]) { - draw_face[2] = false; - } - if (x > 0 && block_present[x - 1][z]) { - draw_face[3] = false; - } - - - for (int face = 0; face < 6; face++) { - if (!draw_face[face]) { + const auto& block_render_data = world.get_block_render_data(x, y, z); + // air + if (block_render_data.block_id == 0) { continue; } - glBindTexture(GL_TEXTURE_2D, grass_block_texture[face]); - - - //glPointSize(30.0f); - - glDrawArrays(GL_TRIANGLES, face * 6, 6); + for (int face = 0; face < 6; face++) { + if (!block_render_data.draw_face[face]) { + continue; + } + glBindTexture(GL_TEXTURE_2D, + texture_manager.get_block_texture( + block_render_data + .block_id) + .texture[face] + ); + + glDrawArrays(GL_TRIANGLES, face * 6, 6); + } } + } } @@ -314,6 +292,7 @@ int main() { glfwSetCursorPosCallback(window, cursor_position_callback); MapTable::init_map(); texture_manager.init_texture(); + world.init_world(); init(window); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); diff --git a/src/map_table.cpp b/src/map_table.cpp index cef7fa6..9033855 100644 --- a/src/map_table.cpp +++ b/src/map_table.cpp @@ -20,8 +20,10 @@ const unsigned MapTable::get_id_from_name(const std::string& name) { void MapTable::init_map() { id_to_name_map.reserve(MAX_BLOCK_NUM); name_to_id_map.reserve(MAX_BLOCK_NUM); - id_to_name_map[0] = "grass_block"; - name_to_id_map[HASH::str("grass_block")] = 0; + id_to_name_map[0] = "air"; + name_to_id_map[HASH::str("air")] = 0; + id_to_name_map[1] = "grass_block"; + name_to_id_map[HASH::str("grass_block")] = 1; } diff --git a/src/texture_manager.cpp b/src/texture_manager.cpp index 267db11..9fb7418 100644 --- a/src/texture_manager.cpp +++ b/src/texture_manager.cpp @@ -4,7 +4,7 @@ #include #include TextureManager::TextureManager() { - + } TextureManager::~TextureManager() { @@ -40,7 +40,12 @@ void TextureManager::delet_texture() { void TextureManager::load_block_texture(const std::string& block_name) { auto id = MapTable::get_id_from_name(block_name); - + m_block_textures[id].name = block_name; + m_block_textures[id].id = id; + // air don`t need texture + if (id == 0) { + return; + } std::string block_texture_path = "assets/texture/block/" + block_name; m_block_textures[id].texture.emplace_back(Shader::load_texture(block_texture_path + "/front.png")); m_block_textures[id].texture.emplace_back(Shader::load_texture(block_texture_path + "/right.png")); diff --git a/src/tools/shader_tools.cpp b/src/tools/shader_tools.cpp index 52fecba..05f6999 100644 --- a/src/tools/shader_tools.cpp +++ b/src/tools/shader_tools.cpp @@ -5,74 +5,80 @@ #include +namespace Shader { + void print_shader_log(GLuint shader) { + int len = 0; + int ch_written = 0; + char *log; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); + if (len > 0) { + log = (char*)malloc(len); + glGetShaderInfoLog(shader, len, &ch_written, log); + LOG::info("Shader Info Log: {}", log); + free(log); + } -void print_shader_log(GLuint shader) { - int len = 0; - int ch_written = 0; - char *log; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); - if (len > 0) { - log = (char*)malloc(len); - glGetShaderInfoLog(shader, len, &ch_written, log); - LOG::info("Shader Info Log: {}", log); - free(log); + } + + + void print_program_info(int prog) { + int len = 0; + int ch_written = 0; + char *log; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len); + if (len > 0) { + log = (char*)malloc(len); + glGetProgramInfoLog(prog, len, &ch_written, log); + LOG::info("Program Info Log: {}", log); + free(log); + } } -} + bool check_opengl_error() { + bool found_error = false; + int gl_err = glGetError(); + while (gl_err != GL_NO_ERROR) { + LOG::error("glEorr: {}", gl_err); + found_error = true; + gl_err = glGetError(); + } + + return found_error; + } -void print_program_info(int prog) { - int len = 0; - int ch_written = 0; - char *log; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len); - if (len > 0) { - log = (char*)malloc(len); - glGetProgramInfoLog(prog, len, &ch_written, log); - LOG::info("Program Info Log: {}", log); - free(log); + std::string read_shader_source(const char* file_path) { + std::string content; + std::ifstream file_stream(file_path, std::ios::in); + + if (!file_stream.is_open()) { + LOG::error("{} not exist", file_path); + } + + std::string line = ""; + while (!file_stream.eof()) { + + getline(file_stream, line); + content.append(line + "\n"); + } + file_stream.close(); + return content; + } + + GLuint load_texture(const std::string& tex_image_path) { + return load_texture(tex_image_path.c_str()); + } + + GLuint load_texture(const char* tex_image_path) { + GLuint texture_id; + texture_id = SOIL_load_OGL_texture(tex_image_path, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y); + std::string error_info = std::string("Could not load texture ") + tex_image_path; + CUBED_ASSERT_MSG(texture_id, error_info.c_str()); + // generate mipmap + glBindTexture(GL_TEXTURE_2D, texture_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glGenerateMipmap(GL_TEXTURE_2D); + return texture_id; } } - -bool check_opengl_error() { - bool found_error = false; - int gl_err = glGetError(); - while (gl_err != GL_NO_ERROR) { - LOG::error("glEorr: {}", gl_err); - found_error = true; - gl_err = glGetError(); - } - - return found_error; -} - - -std::string read_shader_source(const char* file_path) { - std::string content; - std::ifstream file_stream(file_path, std::ios::in); - - if (!file_stream.is_open()) { - LOG::error("{} not exist", file_path); - } - - std::string line = ""; - while (!file_stream.eof()) { - - getline(file_stream, line); - content.append(line + "\n"); - } - file_stream.close(); - return content; -} - -GLuint load_texture(const std::string& tex_image_path) { - return load_texture(tex_image_path.c_str()); -} - -GLuint load_texture(const char* tex_image_path) { - GLuint texture_id; - texture_id = SOIL_load_OGL_texture(tex_image_path, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y); - std::string error_info = std::string("Could not load texture") + tex_image_path; - CUBED_ASSERT_MSG(texture_id, error_info.c_str()); - return texture_id; -} \ No newline at end of file