diff --git a/assets/texture/item/block/air.png b/assets/texture/item/block/air.png new file mode 100644 index 0000000..956a029 Binary files /dev/null and b/assets/texture/item/block/air.png differ diff --git a/assets/texture/item/block/dirt.png b/assets/texture/item/block/dirt.png new file mode 100644 index 0000000..b630af8 Binary files /dev/null and b/assets/texture/item/block/dirt.png differ diff --git a/assets/texture/item/block/grass_block.png b/assets/texture/item/block/grass_block.png new file mode 100644 index 0000000..51212c8 Binary files /dev/null and b/assets/texture/item/block/grass_block.png differ diff --git a/assets/texture/item/block/leaf.png b/assets/texture/item/block/leaf.png new file mode 100644 index 0000000..431fb72 Binary files /dev/null and b/assets/texture/item/block/leaf.png differ diff --git a/assets/texture/item/block/log.png b/assets/texture/item/block/log.png new file mode 100644 index 0000000..1608ac6 Binary files /dev/null and b/assets/texture/item/block/log.png differ diff --git a/assets/texture/item/block/sand.png b/assets/texture/item/block/sand.png new file mode 100644 index 0000000..a5083fe Binary files /dev/null and b/assets/texture/item/block/sand.png differ diff --git a/assets/texture/item/block/stone.png b/assets/texture/item/block/stone.png new file mode 100644 index 0000000..ec16393 Binary files /dev/null and b/assets/texture/item/block/stone.png differ diff --git a/include/Cubed/dev_panel.hpp b/include/Cubed/dev_panel.hpp index 1bd9bfe..7168d64 100644 --- a/include/Cubed/dev_panel.hpp +++ b/include/Cubed/dev_panel.hpp @@ -48,6 +48,7 @@ private: void show_settings_tab_item(); void show_world_tab_item(); void show_player_tab_item(); + void show_items_tab_item(); void update_config_view(); void update_player_profile(); diff --git a/include/Cubed/gameplay/player.hpp b/include/Cubed/gameplay/player.hpp index 976c753..81262b3 100644 --- a/include/Cubed/gameplay/player.hpp +++ b/include/Cubed/gameplay/player.hpp @@ -42,6 +42,8 @@ private: float m_xz_speed = 0.0f; + unsigned m_place_block = 1; + glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f); glm::vec3 move_distance{0.0f, 0.0f, 0.0f}; // player is tow block tall, the pos is the lower pos @@ -85,6 +87,7 @@ public: void change_mode(GameMode mode); void hot_reload(); void set_player_pos(const glm::vec3& pos); + void set_place_block(unsigned id); void update(float delta_time); void update_front_vec(float offset_x, float offset_y); void update_player_move_state(int key, int action); @@ -97,6 +100,8 @@ public: float& deceleration(); float& g(); + unsigned place_block() const; + Gait& gait(); GameMode& game_mode(); }; diff --git a/include/Cubed/map_table.hpp b/include/Cubed/map_table.hpp index 618edbe..81b794f 100644 --- a/include/Cubed/map_table.hpp +++ b/include/Cubed/map_table.hpp @@ -1,18 +1,21 @@ #pragma once #include #include - +#include namespace Cubed { class MapTable { private: - static std::unordered_map id_to_name_map; - static std::unordered_map name_to_id_map; + static inline std::unordered_map id_to_name_map; + static inline std::unordered_map name_to_id_map; + static inline std::vector item_id_to_name; public: // please using reference - static const std::string& get_name_from_id(unsigned id); + static std::string_view get_name_from_id(unsigned id); static unsigned get_id_from_name(const std::string& name); + static std::string_view item_name(unsigned id); + static const std::vector& item_map(); static void init_map(); }; diff --git a/include/Cubed/texture_manager.hpp b/include/Cubed/texture_manager.hpp index 63e845a..f0d4c50 100644 --- a/include/Cubed/texture_manager.hpp +++ b/include/Cubed/texture_manager.hpp @@ -13,9 +13,16 @@ private: GLuint m_ui_array; GLfloat m_max_aniso = 0.0f; int m_aniso = 1; + + std::vector m_item_textures; void load_block_status(unsigned status_id); void load_block_texture(unsigned block_id); + void load_item_texture(const std::string& name); void load_ui_texture(unsigned id); + void init_item(); + void init_block(); + void init_ui(); + void init_block_status(); public: TextureManager(); @@ -25,6 +32,7 @@ public: GLuint get_block_status_array() const; GLuint get_texture_array() const; GLuint get_ui_array() const; + const std::vector& item_textures() const; // Must call after MapTable::init_map() and glfwMakeContextCurrent(window); void init_texture(); void hot_reload(); diff --git a/src/dev_panel.cpp b/src/dev_panel.cpp index 32707c5..65f2cfd 100644 --- a/src/dev_panel.cpp +++ b/src/dev_panel.cpp @@ -3,6 +3,7 @@ #include "Cubed/app.hpp" #include "Cubed/config.hpp" #include "Cubed/gameplay/player.hpp" +#include "Cubed/map_table.hpp" #include "Cubed/tools/log.hpp" #include @@ -72,7 +73,9 @@ void DevPanel::render() { show_settings_tab_item(); show_world_tab_item(); show_player_tab_item(); + show_items_tab_item(); show_about_table_bar(); + ImGui::EndTabBar(); } ImGui::End(); @@ -437,6 +440,36 @@ void DevPanel::show_player_tab_item() { ImGui::EndTabItem(); } } + +void DevPanel::show_items_tab_item() { + auto& textures = m_app.texture_manager().item_textures(); + auto& names = MapTable::item_map(); + if (ImGui::BeginTabItem("item")) { + ImGui::Text("Place Block "); + ImGui::SameLine(); + ImGui::Image(static_cast(static_cast( + textures[m_player->place_block()])), + ImVec2{48, 48}); + for (size_t i = 1; i < textures.size(); i++) { + if (ImGui::ImageButton(("##item" + std::to_string(i)).c_str(), + static_cast( + static_cast(textures[i])), + ImVec2{48, 48})) { + m_player->set_place_block(i); + } + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("%s", names[i].c_str()); + ImGui::EndTooltip(); + } + if (i % 10 != 0) { + ImGui::SameLine(); + } + } + ImGui::EndTabItem(); + } +} + void DevPanel::update_config_view() { auto config = Config::get(); m_config.fov = diff --git a/src/gameplay/player.cpp b/src/gameplay/player.cpp index c3bed54..ab5dd5c 100644 --- a/src/gameplay/player.cpp +++ b/src/gameplay/player.cpp @@ -134,6 +134,8 @@ void Player::hot_reload() { void Player::set_player_pos(const glm::vec3& pos) { m_player_pos = pos; } +void Player::set_place_block(unsigned id) { m_place_block = id; } + void Player::update(float delta_time) { update_move(delta_time); @@ -320,7 +322,7 @@ void Player::update_lookup_block() { static_cast(z + 1)}}; AABB player_box = get_aabb(); if (!player_box.intersects(block_box)) { - m_world.set_block(near_pos, 1); + m_world.set_block(near_pos, m_place_block); } } Input::get_input_state().mouse_state.right = false; @@ -524,6 +526,19 @@ void Player::update_scroll(double yoffset) { } } } + if (m_game_mode == CREATIVE) { + if (yoffset < 0) { + m_place_block += 1; + if (m_place_block >= MAX_BLOCK_NUM) { + m_place_block = 1; + } + } else { + m_place_block -= 1; + if (m_place_block <= 0) { + m_place_block = MAX_BLOCK_NUM - 1; + } + } + } } float& Player::max_walk_speed() { return m_max_walk_speed; } @@ -532,6 +547,7 @@ float& Player::max_speed() { return m_max_speed; } float& Player::acceleration() { return m_acceleration; } float& Player::deceleration() { return m_deceleration; } float& Player::g() { return m_g; } +unsigned Player::place_block() const { return m_place_block; }; Gait& Player::gait() { return m_gait; } GameMode& Player::game_mode() { return m_game_mode; } diff --git a/src/map_table.cpp b/src/map_table.cpp index 4a26837..92b41fe 100644 --- a/src/map_table.cpp +++ b/src/map_table.cpp @@ -6,21 +6,26 @@ namespace Cubed { -std::unordered_map MapTable::id_to_name_map; -std::unordered_map MapTable::name_to_id_map; - -const std::string& MapTable::get_name_from_id(unsigned id) { +std::string_view MapTable::get_name_from_id(unsigned id) { auto it = id_to_name_map.find(id); ASSERT_MSG(it != id_to_name_map.end(), "Id: " + std::to_string(id) + " is not exist"); return it->second; } + unsigned MapTable::get_id_from_name(const std::string& name) { auto it = name_to_id_map.find(HASH::str(name)); ASSERT_MSG(it != name_to_id_map.end(), "Name " + name + " is not exist"); return it->second; } +std::string_view MapTable::item_name(unsigned id) { + ASSERT_MSG(id < item_id_to_name.size(), "ID is invalid"); + return item_id_to_name[id]; +} + +const std::vector& MapTable::item_map() { return item_id_to_name; } + void MapTable::init_map() { id_to_name_map.reserve(MAX_BLOCK_NUM); name_to_id_map.reserve(MAX_BLOCK_NUM); @@ -29,6 +34,9 @@ void MapTable::init_map() { id_to_name_map[i] = BLOCK_REISTER[i]; name_to_id_map[HASH::str(BLOCK_REISTER[i])] = i; } + for (auto s : BLOCK_REISTER) { + item_id_to_name.emplace_back(s); + } } } // namespace Cubed diff --git a/src/texture_manager.cpp b/src/texture_manager.cpp index 662ee85..5802bd4 100644 --- a/src/texture_manager.cpp +++ b/src/texture_manager.cpp @@ -16,6 +16,9 @@ TextureManager::~TextureManager() { delet_texture(); } void TextureManager::delet_texture() { glDeleteTextures(1, &m_texture_array); glDeleteTextures(1, &m_block_status_array); + for (auto& id : m_item_textures) { + glDeleteTextures(1, &id); + } Logger::info("Successfully delete all texture"); } @@ -27,6 +30,10 @@ GLuint TextureManager::get_texture_array() const { return m_texture_array; } GLuint TextureManager::get_ui_array() const { return m_ui_array; } +const std::vector& TextureManager::item_textures() const { + return m_item_textures; +} + void TextureManager::load_block_status(unsigned id) { ASSERT_MSG(id < MAX_BLOCK_STATUS, "Exceed the max status sum limit"); @@ -41,7 +48,7 @@ void TextureManager::load_block_status(unsigned id) { void TextureManager::load_block_texture(unsigned id) { ASSERT_MSG(id < MAX_BLOCK_NUM, "Exceed the max block sum limit"); - const std::string& name = MapTable::get_name_from_id(id); + std::string name{MapTable::get_name_from_id(id)}; // air don`t need texture if (id == 0) { return; @@ -66,6 +73,28 @@ void TextureManager::load_block_texture(unsigned id) { } } +void TextureManager::load_item_texture(const std::string& name) { + std::string path = "texture/item/block/" + name + ".png"; + unsigned char* data = nullptr; + data = Tools::load_image_data(path); + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 0, GL_RGBA, + GL_UNSIGNED_BYTE, data); + + 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); + if (m_aniso >= 1) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, + static_cast(m_aniso)); + } + m_item_textures.push_back(texture); + Tools::delete_image_data(data); +} + void TextureManager::load_ui_texture(unsigned id) { ASSERT_MSG(id < MAX_UI_NUM, "Exceed the max ui sum limit"); @@ -78,6 +107,65 @@ void TextureManager::load_ui_texture(unsigned id) { Tools::delete_image_data(image_data); } +void TextureManager::init_item() { + auto& map = MapTable::item_map(); + for (const auto& name : map) { + load_item_texture(name); + } +} +void TextureManager::init_block() { + glGenTextures(1, &m_texture_array); + glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16, MAX_BLOCK_NUM * 6, 0, + GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + for (int i = 0; i < MAX_BLOCK_NUM; i++) { + load_block_texture(i); + } + + glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + glGenerateMipmap(GL_TEXTURE_2D_ARRAY); + if (m_aniso >= 1) { + glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY, + static_cast(m_aniso)); + } + Logger::info("Block Texture Load Success"); +} +void TextureManager::init_ui() { + glGenTextures(1, &m_ui_array); + glBindTexture(GL_TEXTURE_2D_ARRAY, m_ui_array); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16, MAX_UI_NUM, 0, + GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + for (int i = 0; i < MAX_UI_NUM; i++) { + load_ui_texture(i); + } + + glBindTexture(GL_TEXTURE_2D_ARRAY, m_ui_array); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +} +void TextureManager::init_block_status() { + glGenTextures(1, &m_block_status_array); + glBindTexture(GL_TEXTURE_2D_ARRAY, m_block_status_array); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16, MAX_BLOCK_STATUS, 0, + GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + for (int i = 0; i < MAX_BLOCK_STATUS; i++) { + load_block_status(i); + } + + glBindTexture(GL_TEXTURE_2D_ARRAY, m_block_status_array); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR); + glGenerateMipmap(GL_TEXTURE_2D_ARRAY); + + if (m_aniso >= 1) { + glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY, + static_cast(m_aniso)); + } +} void TextureManager::init_texture() { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &m_max_aniso); if (m_max_aniso > 0.0f) { @@ -89,71 +177,11 @@ void TextureManager::init_texture() { Logger::info("Setting Texture Aniso is {}", m_aniso); MapTable::init_map(); Logger::info("Map Init Success"); - glGenTextures(1, &m_texture_array); - Tools::check_opengl_error(); - glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array); - Tools::check_opengl_error(); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16, MAX_BLOCK_NUM * 6, 0, - GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - Tools::check_opengl_error(); - for (int i = 0; i < MAX_BLOCK_NUM; i++) { - load_block_texture(i); - } - Logger::info("Block Texture Load Success"); - glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array); - Tools::check_opengl_error(); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - Tools::check_opengl_error(); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, - GL_LINEAR_MIPMAP_LINEAR); - Tools::check_opengl_error(); - glGenerateMipmap(GL_TEXTURE_2D_ARRAY); - Tools::check_opengl_error(); - if (m_aniso >= 1) { - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY, - static_cast(m_aniso)); - } - glGenTextures(1, &m_block_status_array); - Tools::check_opengl_error(); - glBindTexture(GL_TEXTURE_2D_ARRAY, m_block_status_array); - Tools::check_opengl_error(); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16, MAX_BLOCK_STATUS, 0, - GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - Tools::check_opengl_error(); - for (int i = 0; i < MAX_BLOCK_STATUS; i++) { - load_block_status(i); - } - - glBindTexture(GL_TEXTURE_2D_ARRAY, m_block_status_array); - Tools::check_opengl_error(); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - Tools::check_opengl_error(); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, - GL_LINEAR_MIPMAP_LINEAR); - Tools::check_opengl_error(); - glGenerateMipmap(GL_TEXTURE_2D_ARRAY); - Tools::check_opengl_error(); - - if (m_aniso >= 1) { - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY, - static_cast(m_aniso)); - } - - glGenTextures(1, &m_ui_array); - Tools::check_opengl_error(); - glBindTexture(GL_TEXTURE_2D_ARRAY, m_ui_array); - Tools::check_opengl_error(); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16, MAX_UI_NUM, 0, - GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - Tools::check_opengl_error(); - for (int i = 0; i < MAX_UI_NUM; i++) { - load_ui_texture(i); - } - - glBindTexture(GL_TEXTURE_2D_ARRAY, m_ui_array); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + init_block(); + init_block_status(); + init_ui(); + init_item(); } void TextureManager::update() { diff --git a/src/tools/shader_tools.cpp b/src/tools/shader_tools.cpp index f408114..68ceaab 100644 --- a/src/tools/shader_tools.cpp +++ b/src/tools/shader_tools.cpp @@ -1,6 +1,5 @@ #include "Cubed/tools/shader_tools.hpp" -#include "Cubed/config.hpp" #include "Cubed/tools/cubed_assert.hpp" #include "Cubed/tools/log.hpp"