From bffeac40995207cec14e3d4f4be52bee654704c8 Mon Sep 17 00:00:00 2001 From: Jay Robson Date: Mon, 15 Jul 2024 23:11:36 +1000 Subject: [PATCH] added tile placement --- assets/image/cross.png | Bin 775 -> 4539 bytes src/graphics/particles.cpp | 3 +- src/graphics/texture.hpp | 2 +- src/graphics/window.cpp | 16 ++++- src/graphics/window.hpp | 1 + src/world/builder.cpp | 116 ++++++++++++++++++++++---------- src/world/builder.hpp | 11 ++- src/world/chunk.cpp | 45 +++++-------- src/world/chunk.hpp | 7 +- src/world/map.cpp | 32 +++++---- src/world/map.hpp | 10 +-- src/world/player.cpp | 8 ++- src/world/state.cpp | 1 - src/world/tile/blue_brick.cpp | 26 ++----- src/world/tile/blue_brick.hpp | 11 ++- src/world/tile/tile_base.cpp | 12 ++++ src/world/tile/tile_base.hpp | 43 +----------- src/world/tile/tile_room.cpp | 84 +++++++++++++++++++++++ src/world/tile/tile_room.hpp | 19 ++++++ src/world/tile/white_brick.cpp | 27 ++------ src/world/tile/white_brick.hpp | 12 ++-- src/world/tile/yellow_brick.cpp | 26 ++----- src/world/tile/yellow_brick.hpp | 12 ++-- 23 files changed, 305 insertions(+), 219 deletions(-) create mode 100644 src/world/tile/tile_base.cpp create mode 100644 src/world/tile/tile_room.cpp create mode 100644 src/world/tile/tile_room.hpp diff --git a/assets/image/cross.png b/assets/image/cross.png index 24c9ce4c6aceb14aa6e27cd5002773f554374156..b01853725ad34f84a15dfeb6d1aa8807b59bf22d 100644 GIT binary patch literal 4539 zcmeHKeQ*=U6+eMNw!t4Ub{JgJ9%o~0!s(=wWJ!l*LnMJkEU=AmoZu!t-G_X^(#g7$ zC2UGciJd|-9s)^dDFbmr($)ksNpKQE31m#hByDMiG6APJWk{H&Gfg4Ee8h#&cPII) zWTxYp=0BfiwR>-W``fp_efy-{Qn_+@T54`8f*@(`a%VNvs8W)r!?)DZGKe6WY_8VL zyWI2^5KP*~)JMh-z@yMOYGy}WnH-1i?_+k@fv{S&>ot&{rskG&^etLaS6dEmfD zU7J66`LU1o&2u+3W!KF}-?*sezPjC!NGK=iy^Ku1c7bbl(N|BnJ6%s}`)+ zU$N}3Ft=v?wCmwz1RYk9~VW79~>=Emqzb?J;_vHJh z?a-8Nvc4zxVxOXW`VYyc{(YjV=K1W4(#4d`y7F5mBmI{wr{+I(yTtf7YrJ}*%GY`3 z{qXEJUhm9WHLEXs%}X1eIK{PHz1QFKi2uvhuV=TXe)1uCR_H+6T#J@IiOh+3E8E(v z2Xc!F$U}PvuVgIV_)HyncwznLwM)_#=J#cMt37ta{EO8)g4Km7gYTZZ-dC7;e%d2x zfBm-f%`ZPr$&5|!KGbpS<0QV!Ey{<^-ILirUDv&M*YCA;|3VzA-eJo-vS0WIaqp%Z z#-UeA^syN;Up;)Z=SI^I!v1dmU|J}Y{Pc5$tplG8+#Wc3yY-cUzhwlH!uw9Wk+TQl zI3{>&jF9hw_oSejjg^(L>P2> zA`l?Pj*w(mGms=4`pyxOcYTN>syRuFgc;7&%mwAVu@uTV8(~nEJ4K?*KlD80#4yn6RA3!WvFGqNJHQV0oun}nnuO2R}>rV*hp?3>Gr^JVriLnLRN>_MzXbcI9uNjIa?q1 zOri6LtiZ4TUufmkkX z6S(4COamSCbC5j};W}&=z9ST9&PUrURu-ojAA|zU8*nSjSa7q2GZ{&r*~glU+*{RClmwJUZIIDcb{r;d%>hF#oq;L}I~&k~4-^TteKXNr?&= zlVo6A+y==Dav?F23=^6uY3F-<5_|DI&H&VtlT1k8Nx3HFnven$0#8QQq+AnHU_#)@ z==#6Ol{$Kz;)3umC<>RQ;)ae3aMhabdvLiExdW{`Kb*f~Bh)FO@`oh^(d8*c6MMO= z8H`%l?Qv@x~q!z?^)FMp}XbT?iUA9d1}_y(;FJ|&iwENHRsQy zcg*ixaP#eN3f5^hAV0d0w&-}$>8ZE+>oqeEl2=!}h+n~8(>}Ujp+BW2%YXFJ z%=Wfjrz_WfI_uWy-uxk<;Be*_DH}guu>D%;TSHrjp6i;fU!BQOFR^adN@w>2^*{R$ D#XA(n delta 676 zcmV;V0$csNBZmf%B$Gq|5`QR>eUUv#!$2IxUsJVGDh?JAamY}0v5Sg0)+!XCLZ}s5 zbuhW~3z{?}DK3tJYr(;f#j1mgv#t)Vf*|+-;_Tq0=prTlFDbN$_29T4@9sVB-T^|r z%rvVj257o%rV?>6lU)@9uLvNB9t>h!W|lE0NlA1ZU-$6w^)AY@I)9)0bM&b>ivd27 zIK~XqCf*>P*|ZJL`@~^ZlvUz$;t7*3Nc_lk#p5^51(yY$88*|YdEzj!SZHIVjakvu zh^L7os-{!EknvdMyv127S6TC({Dq;MzOu}9nj=VH5lfIDLO~TJlwl)Et4@lA6z#`5 z_=jD;L@tF~B`|UMD5y92^2;1fW1Eat-MvbBez1J2^qJr1_vQM5fgfN3W=Bn2 z$tiayM1t=KM3K0YL%a#Rb0sQ~bxzpVSpR>TM69Q0$=pR%Rn%Iv;@MVP0kiBFiBdJI zW|TVw29WvWy+yDJ$x$pz&3 #include +#include #include #include @@ -82,7 +83,7 @@ void Particles::render(const Context& ctx) const { } glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - ctx.set_model_matrix(glm::mat4(1)); + ctx.set_model_matrix(glm::translate(glm::mat4(1), {-ctx.m_transform, 0})); ctx.set_colour_matrix(glm::mat4(1)); glBindVertexArray(m_vao); diff --git a/src/graphics/texture.hpp b/src/graphics/texture.hpp index 964b5f9..b559c13 100644 --- a/src/graphics/texture.hpp +++ b/src/graphics/texture.hpp @@ -6,7 +6,7 @@ namespace Graphics::Texture { inline Image MISSING {"missing.png", Image::Edge::REPEATING}; inline Image WHITE {"white.png", Image::Edge::REPEATING}; - inline Image CROSS {"cross.png", Image::Edge::CLAMP}; + inline Image CROSS {"cross.png", Image::Edge::REPEATING}; inline Image YELLOW_BRICK_WALL {"yellow_brick_wall.png", Image::Edge::REPEATING}; inline Image YELLOW_BRICK_FLOOR {"yellow_brick_floor.png", Image::Edge::REPEATING}; inline Image BLUE_BRICK_WALL {"blue_brick_wall.png", Image::Edge::REPEATING}; diff --git a/src/graphics/window.cpp b/src/graphics/window.cpp index 086d464..7cf0c65 100644 --- a/src/graphics/window.cpp +++ b/src/graphics/window.cpp @@ -37,7 +37,7 @@ static void cb_keypress(GLFWwindow* win, int key, int sc, int action, int mods) static bool clicked_from_cb = false; -void cb_mouse_button(GLFWwindow* win, int button, int action, int mods) { +static void cb_mouse_button(GLFWwindow* win, int button, int action, int mods) { if(button == GLFW_MOUSE_BUTTON_RIGHT) { if(action == GLFW_PRESS) { Window::mouse_locked = true; @@ -53,6 +53,12 @@ void cb_mouse_button(GLFWwindow* win, int button, int action, int mods) { } } +static double scroll_from_cb = 0; + +static void cb_scroll(GLFWwindow* win, double x, double y) { + scroll_from_cb = y; +} + float Window::get_aspect() { return (float)Window::size.x / (float)Window::size.y; } @@ -67,6 +73,7 @@ Window::Window() { glfwSetFramebufferSizeCallback(m_handle, cb_framebuffer_size); glfwSetMouseButtonCallback(m_handle, cb_mouse_button); glfwSetKeyCallback(m_handle, cb_keypress); + glfwSetScrollCallback(m_handle, cb_scroll); glfwSwapInterval(1); assert(glewInit() == GLEW_OK); @@ -100,6 +107,13 @@ void Window::update() const { } else { Window::clicked = false; } + + if(scroll_from_cb) { + Window::scroll = scroll_from_cb; + scroll_from_cb = 0; + } else { + Window::scroll = 0; + } } void Window::swap_buffers() const { diff --git a/src/graphics/window.hpp b/src/graphics/window.hpp index d6b9f6e..177f151 100644 --- a/src/graphics/window.hpp +++ b/src/graphics/window.hpp @@ -11,6 +11,7 @@ namespace Graphics { inline static glm::vec<2, int> size; inline static bool mouse_locked = false; inline static bool clicked = false; + inline static double scroll = 0; GLFWwindow* m_handle; diff --git a/src/world/builder.cpp b/src/world/builder.cpp index 52f4f4d..d0bc67d 100644 --- a/src/world/builder.cpp +++ b/src/world/builder.cpp @@ -1,36 +1,34 @@ #include "builder.hpp" #include "../graphics/window.hpp" -#include "../graphics/texture.hpp" #include "map.hpp" #include "player.hpp" #include "state.hpp" #include "tile/blue_brick.hpp" #include "tile/tile_base.hpp" +#include "tile/white_brick.hpp" +#include "tile/yellow_brick.hpp" +#include "../util/math/mod.hpp" +#include "../graphics/texture.hpp" #include #include +#include #include #include #include -#include using World::Builder; Builder::Builder() { - const Tile::TileBase* neighbours[4] = {nullptr}; - - Graphics::Mesh mesh; - m_tool = std::make_unique(); - m_tool->remesh(mesh, neighbours, {0, 0}); - m_model.set(mesh, GL_STATIC_DRAW); + m_tools.push_back(nullptr); + m_tools.push_back(std::make_unique()); + m_tools.push_back(std::make_unique()); + m_tools.push_back(std::make_unique()); + + remesh_tool(); } -void Builder::update(State& state) { - m_has_intersect = false; - if(Graphics::Window::mouse_locked) { - return; - } - +void Builder::do_click(State& state) { Player& player = state.m_player; Map& map = state.m_map; @@ -40,7 +38,6 @@ void Builder::update(State& state) { glm::vec<3, double> near = glm::unProject(glm::vec3(mpos, -1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size)); glm::vec<3, double> far = glm::unProject(glm::vec3(mpos, 1), player.m_view, player.m_projection, glm::vec4(0, 0, Graphics::Window::size)); glm::vec<3, double> direction = far - near; - const glm::vec<2, double> CHECK_TILES[] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; bool found = false; if(direction.z >= 0) { @@ -48,32 +45,40 @@ void Builder::update(State& state) { } m_intersect = glm::round(glm::vec<2, double>(near - direction / direction.z * near.z) + player.m_pos); + + const Tile::TileBase* tile_cur = map.get_tile(m_intersect); + const Tile::TileBase* tile_next = m_tools[m_tool_index].get(); + + if(tile_next && !tile_next->can_place(tile_cur) || !tile_next && !tile_cur) { + return; + } + m_has_intersect = true; - const Tile::TileBase* tile_old = map.get_tile(m_intersect); - unsigned int texid; - - if(tile_old) { - m_mode = Mode::CLEAR; - } else { - m_mode = Mode::SET; - } - - if(!m_has_intersect || !Graphics::Window::clicked) { + if(!Graphics::Window::clicked) { return; } std::unique_ptr tile; - switch(m_mode) { - case Mode::SET: - tile = m_tool->clone(); - texid = tile->get_texid(); - break; - default: - texid = tile_old->get_texid(); - tile = nullptr; + unsigned int texid; + bool texid_use_old = false; + + if(tile_next) { + tile = tile_next->clone(); + texid = tile_next->get_break_texture(); + } else { + texid_use_old = true; + } + + tile = map.set_tile(m_intersect, std::move(tile)); + + if(texid_use_old) { + if(tile) { + texid = tile->get_break_texture(); + } else { + return; + } } - map.set_tile(m_intersect, std::move(tile)); state.m_particles.add({ .m_pos = {m_intersect, 0.75/2}, @@ -86,6 +91,48 @@ void Builder::update(State& state) { }); } +void Builder::remesh_tool() { + Graphics::Mesh mesh; + if(m_tools[m_tool_index]) { + const Tile::TileBase* neighbours[4] = {nullptr}; + m_tools[m_tool_index]->remesh(mesh, neighbours, {0, 0}); + } else { + Graphics::Primitive<4, 6> prim = { + .m_vertices={ + {.m_pos={-0.5, -0.5, 0.05, 1}, .m_uv={0, 0}}, + {.m_pos={+0.5, -0.5, 0.05, 1}, .m_uv={2, 0}}, + {.m_pos={-0.5, +0.5, 0.05, 1}, .m_uv={0, 2}}, + {.m_pos={+0.5, +0.5, 0.05, 1}, .m_uv={2, 2}}, + }, + .m_indices={ + 0, 3, 2, + 0, 1, 3, + }, + }; + prim.m_texid = Graphics::Texture::CROSS; + mesh.add_primitive(prim); + } + m_model.set(mesh, GL_DYNAMIC_DRAW); +} + +void Builder::select_tool() { + int offset = std::clamp((int)std::round(Graphics::Window::scroll), -1, 1); + if(offset == 0) { + return; + } + + m_tool_index = Util::Math::mod(m_tool_index + offset, m_tools.size()); + remesh_tool(); +} + +void Builder::update(State& state) { + m_has_intersect = false; + if(!Graphics::Window::mouse_locked) { + select_tool(); + do_click(state); + } +} + void Builder::render(const Graphics::Context& ctx) const { if(!m_has_intersect) { return; @@ -95,6 +142,5 @@ void Builder::render(const Graphics::Context& ctx) const { ctx.set_model_matrix(glm::translate(glm::mat4(1), {pos - ctx.m_transform, 0})); ctx.set_colour_matrix(glm::mat4(1)); m_model.render(GL_TRIANGLES); - m_tool->render(); } diff --git a/src/world/builder.hpp b/src/world/builder.hpp index 5c5d294..3f3f24a 100644 --- a/src/world/builder.hpp +++ b/src/world/builder.hpp @@ -14,16 +14,23 @@ namespace World { CLEAR, }; + std::vector> m_tools; + Graphics::GL::Model m_model; glm::vec<2, double> m_intersect; - std::unique_ptr m_tool; bool m_has_intersect = false; - Mode m_mode; + int m_tool_index = 1; Builder(); void update(State& state); void render(const Graphics::Context& ctx) const; + + private: + + void do_click(State& state); + void select_tool(); + void remesh_tool(); }; }; diff --git a/src/world/chunk.cpp b/src/world/chunk.cpp index 55e0c39..ee04277 100644 --- a/src/world/chunk.cpp +++ b/src/world/chunk.cpp @@ -2,13 +2,11 @@ #include #include "chunk.hpp" #include "tile/tile_base.hpp" -#include "../graphics/texture.hpp" #include #include #include #include #include -#include using World::Chunk; using World::Tile::TileBase; @@ -21,38 +19,34 @@ Chunk::Chunk(glm::vec<2, int> pos) { m_pos = pos; } -TileBase* Chunk::get(glm::vec<2, int> p) { - p = get_pos_mod(p); - return m_tiles[p.x * N + p.y].get(); -} - const TileBase* Chunk::get(glm::vec<2, int> p) const { p = get_pos_mod(p); return m_tiles[p.x * N + p.y].get(); } -TileBase* Chunk::set(glm::vec<2, int> p, std::unique_ptr v) { - TileBase* r = v.get(); +TileBase* Chunk::get(glm::vec<2, int> p) { p = get_pos_mod(p); - m_tiles[p.x * N + p.y].swap(v); + return m_tiles[p.x * N + p.y].get(); +} - if(r && !v) { - m_used_tiles += 1; - } - else if(!r && v) { +std::unique_ptr Chunk::set(glm::vec<2, int> p, std::unique_ptr v) { + p = get_pos_mod(p); + + bool is_empty_in = v == nullptr; + std::swap(m_tiles[p.x * N + p.y], v); + + if(is_empty_in && v) { m_used_tiles -= 1; } + else if(!is_empty_in && !v) { + m_used_tiles += 1; + } m_dirty = true; - return r; + return v; } void Chunk::update(Map& map) { - for(auto& tile : m_tiles) { - if(tile) { - tile->update(); - } - } if(!m_dirty) { return; } @@ -73,11 +67,12 @@ void Chunk::update(Map& map) { for(int x = 0; x < N; x++) { for(int y = 0; y < N; y++) { glm::vec<2, int> t_off(x, y); - Tile::TileBase* tile = get(t_off); + const Tile::TileBase* tile = get(t_off); + if(!tile) { continue; } - + const Tile::TileBase* tiles[4]; for(int i = 0; i < std::size(neighbours); i++) { @@ -110,11 +105,5 @@ void Chunk::render(const Graphics::Context& ctx) const { ctx.set_model_matrix(glm::translate(glm::mat4(1), {glm::vec<2, double>(m_pos) - ctx.m_transform, 0})); ctx.set_colour_matrix(glm::mat4(1)); m_model.render(GL_TRIANGLES); - - for(auto& tile : m_tiles) { - if(tile) { - tile->render(); - } - } } diff --git a/src/world/chunk.hpp b/src/world/chunk.hpp index 99ac845..fe6d15d 100644 --- a/src/world/chunk.hpp +++ b/src/world/chunk.hpp @@ -11,13 +11,12 @@ namespace World { #include "tile/tile_base.hpp" #include "../graphics/gl/model.hpp" #include -#include namespace World { struct Chunk { static constexpr int N = 16; - std::unique_ptr m_tiles[N*N]; + std::unique_ptr m_tiles[N*N] = {{}}; Graphics::GL::Model m_model; glm::vec<2, int> m_pos; int m_used_tiles = 0; @@ -27,9 +26,9 @@ namespace World { void update(Map& map); void render(const Graphics::Context& ctx) const; - Tile::TileBase* get(glm::vec<2, int> p); const Tile::TileBase* get(glm::vec<2, int> p) const; - Tile::TileBase* set(glm::vec<2, int> p, std::unique_ptr v); + Tile::TileBase* get(glm::vec<2, int> p); + std::unique_ptr set(glm::vec<2, int> p, std::unique_ptr v); }; }; diff --git a/src/world/map.cpp b/src/world/map.cpp index c671b36..d63adc8 100644 --- a/src/world/map.cpp +++ b/src/world/map.cpp @@ -56,39 +56,37 @@ void Map::mark_chunk_dirty(glm::vec<2, int> pos) { } } -TileBase* Map::get_tile(glm::vec<2, int> pos) { - Chunk* c = get_chunk(pos); - return c ? c->get(pos) : nullptr; -} - const TileBase* Map::get_tile(glm::vec<2, int> pos) const { const Chunk* c = get_chunk(pos); return c ? c->get(pos) : nullptr; } -TileBase* Map::set_tile(glm::vec<2, int> pos, std::unique_ptr tile) { +TileBase* Map::get_tile(glm::vec<2, int> pos) { + Chunk* c = get_chunk(pos); + return c ? c->get(pos) : nullptr; +} + +std::unique_ptr Map::set_tile(glm::vec<2, int> pos, std::unique_ptr tile) { uint64_t cid = get_chunk_id(pos); auto it = m_chunks.find(cid); - if(tile) { - tile->m_pos = pos; - if(it == m_chunks.end()) { - it = m_chunks.try_emplace(cid, pos - get_pos_mod(pos)).first; - } - } else if(it == m_chunks.end()) { - return nullptr; + + if(it == m_chunks.end()) { + it = m_chunks.try_emplace(cid, pos - get_pos_mod(pos)).first; } - Chunk* c = &it->second; - TileBase* tile_p = c->set(pos, std::move(tile)); + + Chunk& c = it->second; + tile = c.set(pos, std::move(tile)); + mark_chunk_dirty(pos + glm::vec<2, int>(1, 0)); mark_chunk_dirty(pos + glm::vec<2, int>(0, 1)); mark_chunk_dirty(pos + glm::vec<2, int>(-1, 0)); mark_chunk_dirty(pos + glm::vec<2, int>(0, -1)); - if(!tile_p && c->m_used_tiles == 0) { + if(c.m_used_tiles <= 0) { m_chunks.erase(it); } - return tile_p; + return tile; } void Map::update() { diff --git a/src/world/map.hpp b/src/world/map.hpp index 4cc08de..864d141 100644 --- a/src/world/map.hpp +++ b/src/world/map.hpp @@ -11,21 +11,21 @@ namespace World { #include #include #include -#include namespace World { struct State; struct Map { static constexpr int N = 16; std::map m_chunks; - - const Chunk* get_chunk(glm::vec<2, int> pos) const; + + Tile::TileBase* get_tile(glm::vec<2, int> pos); const Tile::TileBase* get_tile(glm::vec<2, int> pos) const; Chunk* get_chunk(glm::vec<2, int> pos); + const Chunk* get_chunk(glm::vec<2, int> pos) const; + Chunk* get_or_generate_chunk(glm::vec<2, int> pos); - Tile::TileBase* get_tile(glm::vec<2, int> pos); - Tile::TileBase* set_tile(glm::vec<2, int> pos, std::unique_ptr tile); + std::unique_ptr set_tile(glm::vec<2, int> pos, std::unique_ptr tile); void update(); void render(const Graphics::Context& ctx) const; diff --git a/src/world/player.cpp b/src/world/player.cpp index 36b0a89..eebb39e 100644 --- a/src/world/player.cpp +++ b/src/world/player.cpp @@ -56,8 +56,9 @@ void Player::update() { m_cursor_last = cursor; if(Graphics::Window::mouse_locked) { - m_pitch = std::fmod(m_pitch + cursor_diff.x * 0.0025, glm::pi() * 2); - m_yaw = std::clamp(m_yaw - cursor_diff.y * 0.0025, 0.0, glm::pi() * 0.5); + double pi = glm::pi(); + m_pitch = std::fmod(m_pitch + cursor_diff.x * 0.0025, pi*2); + m_yaw = std::clamp(m_yaw - cursor_diff.y * 0.0025, 0.0, pi*0.5); } m_vel += m_accel; @@ -68,8 +69,9 @@ void Player::update() { mat = glm::translate(mat, {0, 0, -m_distance}); mat = glm::rotate(mat, (float)m_yaw, {-1, 0, 0}); mat = glm::rotate(mat, (float)m_pitch, {0, 0, 1}); + mat = glm::translate(mat, {0, 0, -0.25}); m_view = mat; - m_projection = glm::perspective(glm::radians(90.0f), Graphics::Window::get_aspect(), 0.01f, 10.f); + m_projection = glm::perspective(glm::radians(90.0f), Graphics::Window::get_aspect(), 0.01f, 100.f); } diff --git a/src/world/state.cpp b/src/world/state.cpp index 78b415f..82cac6a 100644 --- a/src/world/state.cpp +++ b/src/world/state.cpp @@ -1,7 +1,6 @@ #include "state.hpp" #include "tile/yellow_brick.hpp" -#include using World::State; diff --git a/src/world/tile/blue_brick.cpp b/src/world/tile/blue_brick.cpp index 7b9fb5b..192b128 100644 --- a/src/world/tile/blue_brick.cpp +++ b/src/world/tile/blue_brick.cpp @@ -2,37 +2,23 @@ #include "blue_brick.hpp" #include "tile_base.hpp" #include "../../graphics/texture.hpp" -#include using World::Tile::BlueBrick; +using World::Tile::TileBase; -void BlueBrick::update() { -} - -unsigned int BlueBrick::get_texid() const { +unsigned int BlueBrick::get_break_texture() const { return Graphics::Texture::BLUE_BRICK_FLOOR; } -std::unique_ptr BlueBrick::clone() const { +std::unique_ptr BlueBrick::clone() const { return std::make_unique(*this); } void BlueBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const { - auto p = TileBase::PRIMITIVE_B; - p.m_texid = Graphics::Texture::BLUE_BRICK_FLOOR; - p.m_offset = {offset, 0}; - mesh.add_primitive(p); - - for(int i = 0; i < std::size(TileBase::PRIMITIVE_S); i++) { - if(!neighbours[i]) { - p = TileBase::PRIMITIVE_S[i]; - p.m_texid = Graphics::Texture::BLUE_BRICK_WALL; - p.m_offset = {offset, 0}; - mesh.add_primitive(p); - } - } + remesh_room(mesh, neighbours, offset, Graphics::Texture::BLUE_BRICK_FLOOR, Graphics::Texture::BLUE_BRICK_WALL, Graphics::Texture::BLUE_BRICK_FLOOR, 0.75); } -void BlueBrick::render() const { +bool BlueBrick::can_place(const TileBase* o) const { + return o == nullptr; } diff --git a/src/world/tile/blue_brick.hpp b/src/world/tile/blue_brick.hpp index 69c5a16..b6c5426 100644 --- a/src/world/tile/blue_brick.hpp +++ b/src/world/tile/blue_brick.hpp @@ -1,15 +1,14 @@ #pragma once -#include "tile_base.hpp" +#include "tile_room.hpp" namespace World::Tile { - struct BlueBrick : TileBase { - void update() override; - unsigned int get_texid() const override; - std::unique_ptr clone() const override; + struct BlueBrick : TileRoom { + unsigned int get_break_texture() const override; void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override; - void render() const override; + std::unique_ptr clone() const override; + bool can_place(const TileBase* o) const override; }; }; diff --git a/src/world/tile/tile_base.cpp b/src/world/tile/tile_base.cpp new file mode 100644 index 0000000..5191f74 --- /dev/null +++ b/src/world/tile/tile_base.cpp @@ -0,0 +1,12 @@ + +#include "tile_base.hpp" + +using World::Tile::TileBase; + +unsigned int TileBase::get_break_texture() const { + return 0; +} + +void TileBase::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const { +} + diff --git a/src/world/tile/tile_base.hpp b/src/world/tile/tile_base.hpp index 174f57f..1a654e7 100644 --- a/src/world/tile/tile_base.hpp +++ b/src/world/tile/tile_base.hpp @@ -9,50 +9,13 @@ namespace World::Tile { struct TileBase { - - static const inline Graphics::Primitive<4, 6> PRIMITIVE_B = { - .m_vertices={ - {.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 0}}, - {.m_pos={-0.5, +0.5, 0, 1}, .m_uv={0, 2}}, - {.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 0}}, - {.m_pos={+0.5, +0.5, 0, 1}, .m_uv={2, 2}}, - }, - .m_indices={ - 0, 2, 3, - 0, 3, 1, - }, - }; - private: - static const inline Graphics::Primitive<4, 6> PRIMITIVE_0 = { - .m_vertices={ - {.m_pos={-0.5, -0.5, 0.75, 1}, .m_uv={0, 0}}, - {.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 1.5}}, - {.m_pos={+0.5, -0.5, 0.75, 1}, .m_uv={2, 0}}, - {.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 1.5}}, - }, - .m_indices={ - 0, 2, 3, - 0, 3, 1, - }, - }; - public: - static const inline Graphics::Primitive<4, 6> PRIMITIVE_S[4] = { - PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 0.5f, {0, 0, 1})), - PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 1.0f, {0, 0, 1})), - PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 1.5f, {0, 0, 1})), - PRIMITIVE_0, - }; - - int m_facing = 0; - glm::vec<2, int> m_pos; virtual ~TileBase() = default; - virtual void update() = 0; - virtual unsigned int get_texid() const = 0; + virtual unsigned int get_break_texture() const = 0; + virtual void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const = 0; virtual std::unique_ptr clone() const = 0; - virtual void remesh(Graphics::Mesh& mesh, TileBase const* const* neighbours, glm::vec<2, int> offset) const = 0; - virtual void render() const = 0; + virtual bool can_place(const TileBase* o) const = 0; }; }; diff --git a/src/world/tile/tile_room.cpp b/src/world/tile/tile_room.cpp new file mode 100644 index 0000000..a1be27a --- /dev/null +++ b/src/world/tile/tile_room.cpp @@ -0,0 +1,84 @@ + +#include "tile_room.hpp" +#include "tile_base.hpp" + +using World::Tile::TileBase; +using World::Tile::TileRoom; + +static const Graphics::Primitive<4, 6> PRIMITIVE_0 = { + .m_vertices={ + {.m_pos={-0.5, -0.5, 1, 1}, .m_uv={0, 0}}, + {.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 2}}, + {.m_pos={+0.5, -0.5, 1, 1}, .m_uv={2, 0}}, + {.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 2}}, + }, + .m_indices={ + 0, 2, 3, + 0, 3, 1, + }, +}; +static const Graphics::Primitive<4, 6> PRIMITIVE_B = { + .m_vertices={ + {.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 0}}, + {.m_pos={-0.5, +0.5, 0, 1}, .m_uv={0, 2}}, + {.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 0}}, + {.m_pos={+0.5, +0.5, 0, 1}, .m_uv={2, 2}}, + }, + .m_indices={ + 0, 2, 3, + 0, 3, 1, + }, +}; +static const Graphics::Primitive<4, 6> PRIMITIVE_T = { + .m_vertices={ + {.m_pos={-0.5, -0.5, 0, 1}, .m_uv={0, 0}}, + {.m_pos={+0.5, -0.5, 0, 1}, .m_uv={2, 0}}, + {.m_pos={-0.5, +0.5, 0, 1}, .m_uv={0, 2}}, + {.m_pos={+0.5, +0.5, 0, 1}, .m_uv={2, 2}}, + }, + .m_indices={ + 0, 2, 3, + 0, 3, 1, + }, +}; +static const Graphics::Primitive<4, 6> PRIMITIVE_S[4] = { + PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 0.5f, {0, 0, 1})), + PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 1.0f, {0, 0, 1})), + PRIMITIVE_0.with_matrix(glm::rotate(glm::mat4(1), glm::pi() * 1.5f, {0, 0, 1})), + PRIMITIVE_0, +}; + +void TileRoom::remesh_room( + Graphics::Mesh& mesh, + const TileBase* const* neighbours, + glm::vec<2, int> offset, + unsigned int texid_floor, + unsigned int texid_walls, + unsigned int texid_ceiling, + double height) const +{ + auto p = PRIMITIVE_B; + p.m_texid = texid_floor; + p.m_offset = {offset, 0}; + mesh.add_primitive(p); + p = PRIMITIVE_T; + p.m_texid = texid_ceiling; + p.m_offset = {offset, height}; + mesh.add_primitive(p); + + for(int i = 0; i < std::size(PRIMITIVE_S); i++) { + if(!neighbours[i]) { + p = PRIMITIVE_S[i]; + p.m_texid = texid_walls; + p.m_offset = {offset, 0}; + + for(Graphics::Vertex& v : p.m_vertices) { + v.m_pos.z *= height; + v.m_uv.y *= height; + } + + mesh.add_primitive(p); + } + } +} + diff --git a/src/world/tile/tile_room.hpp b/src/world/tile/tile_room.hpp new file mode 100644 index 0000000..7526dba --- /dev/null +++ b/src/world/tile/tile_room.hpp @@ -0,0 +1,19 @@ + +#pragma once + +#include "tile_base.hpp" + +namespace World::Tile { + struct TileRoom : TileBase { + + void remesh_room( + Graphics::Mesh& mesh, + const TileBase* const* neighbours, + glm::vec<2, int> offset, + unsigned int texid_floor, + unsigned int texid_walls, + unsigned int texid_ceiling, + double height) const; + }; +}; + diff --git a/src/world/tile/white_brick.cpp b/src/world/tile/white_brick.cpp index 3a56284..ba94bec 100644 --- a/src/world/tile/white_brick.cpp +++ b/src/world/tile/white_brick.cpp @@ -2,37 +2,22 @@ #include "white_brick.hpp" #include "tile_base.hpp" #include "../../graphics/texture.hpp" -#include using World::Tile::WhiteBrick; +using World::Tile::TileBase; -void WhiteBrick::update() { -} - -unsigned int WhiteBrick::get_texid() const { +unsigned int WhiteBrick::get_break_texture() const { return Graphics::Texture::WHITE_BRICK_FLOOR; } -std::unique_ptr WhiteBrick::clone() const { +std::unique_ptr WhiteBrick::clone() const { return std::make_unique(*this); } void WhiteBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const { - auto p = TileBase::PRIMITIVE_B; - p.m_texid = Graphics::Texture::WHITE_BRICK_FLOOR; - p.m_offset = {offset, 0}; - mesh.add_primitive(p); - - for(int i = 0; i < std::size(TileBase::PRIMITIVE_S); i++) { - if(!neighbours[i]) { - p = TileBase::PRIMITIVE_S[i]; - p.m_texid = Graphics::Texture::WHITE_BRICK_WALL; - p.m_offset = {offset, 0}; - mesh.add_primitive(p); - } - } + remesh_room(mesh, neighbours, offset, Graphics::Texture::WHITE_BRICK_FLOOR, Graphics::Texture::WHITE_BRICK_WALL, Graphics::Texture::WHITE_BRICK_FLOOR, 0.75); } -void WhiteBrick::render() const { +bool WhiteBrick::can_place(const TileBase* o) const { + return o == nullptr; } - diff --git a/src/world/tile/white_brick.hpp b/src/world/tile/white_brick.hpp index e7dc63c..526bd0d 100644 --- a/src/world/tile/white_brick.hpp +++ b/src/world/tile/white_brick.hpp @@ -1,16 +1,14 @@ #pragma once -#include "tile_base.hpp" +#include "tile_room.hpp" namespace World::Tile { - struct WhiteBrick : TileBase { - void update() override; - unsigned int get_texid() const override; - std::unique_ptr clone() const override; + struct WhiteBrick : TileRoom { + unsigned int get_break_texture() const override; void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override; - void render() const override; - + std::unique_ptr clone() const override; + bool can_place(const TileBase* o) const override; }; }; diff --git a/src/world/tile/yellow_brick.cpp b/src/world/tile/yellow_brick.cpp index 33407a5..d36a52b 100644 --- a/src/world/tile/yellow_brick.cpp +++ b/src/world/tile/yellow_brick.cpp @@ -2,37 +2,23 @@ #include "yellow_brick.hpp" #include "tile_base.hpp" #include "../../graphics/texture.hpp" -#include using World::Tile::YellowBrick; +using World::Tile::TileBase; -void YellowBrick::update() { -} - -unsigned int YellowBrick::get_texid() const { +unsigned int YellowBrick::get_break_texture() const { return Graphics::Texture::YELLOW_BRICK_FLOOR; } -std::unique_ptr YellowBrick::clone() const { +std::unique_ptr YellowBrick::clone() const { return std::make_unique(*this); } void YellowBrick::remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const { - auto p = TileBase::PRIMITIVE_B; - p.m_texid = Graphics::Texture::YELLOW_BRICK_FLOOR; - p.m_offset = {offset, 0}; - mesh.add_primitive(p); - - for(int i = 0; i < std::size(TileBase::PRIMITIVE_S); i++) { - if(!neighbours[i]) { - p = TileBase::PRIMITIVE_S[i]; - p.m_texid = Graphics::Texture::YELLOW_BRICK_WALL; - p.m_offset = {offset, 0}; - mesh.add_primitive(p); - } - } + remesh_room(mesh, neighbours, offset, Graphics::Texture::YELLOW_BRICK_FLOOR, Graphics::Texture::YELLOW_BRICK_WALL, Graphics::Texture::YELLOW_BRICK_FLOOR, 0.75); } -void YellowBrick::render() const { +bool YellowBrick::can_place(const TileBase* o) const { + return o == nullptr; } diff --git a/src/world/tile/yellow_brick.hpp b/src/world/tile/yellow_brick.hpp index 41d201a..40c33d1 100644 --- a/src/world/tile/yellow_brick.hpp +++ b/src/world/tile/yellow_brick.hpp @@ -1,16 +1,14 @@ #pragma once -#include "tile_base.hpp" +#include "tile_room.hpp" namespace World::Tile { - struct YellowBrick : TileBase { - void update() override; - unsigned int get_texid() const override; - std::unique_ptr clone() const override; + struct YellowBrick : TileRoom { + unsigned int get_break_texture() const override; void remesh(Graphics::Mesh& mesh, const TileBase* const* neighbours, glm::vec<2, int> offset) const override; - void render() const override; - + std::unique_ptr clone() const override; + bool can_place(const TileBase* o) const override; }; };