diff options
-rw-r--r-- | draw/anim.cpp | 11 | ||||
-rw-r--r-- | editor/scenery-editor.cpp | 6 | ||||
-rw-r--r-- | editor/scenery-editor.hpp | 2 | ||||
-rw-r--r-- | editor/update.cpp | 2 | ||||
-rw-r--r-- | src/anim-atlas.cpp | 2 | ||||
-rw-r--r-- | src/anim-atlas.hpp | 2 | ||||
-rw-r--r-- | src/scenery.cpp | 80 | ||||
-rw-r--r-- | src/scenery.hpp | 36 |
8 files changed, 120 insertions, 21 deletions
diff --git a/draw/anim.cpp b/draw/anim.cpp index aa5ee1f6..d2f644a9 100644 --- a/draw/anim.cpp +++ b/draw/anim.cpp @@ -28,18 +28,7 @@ void anim_mesh::draw(tile_shader& shader, chunk& c) { const local_coords pos{i}; if (auto [atlas, s] = c[pos].scenery(); atlas) - { draw(shader, *atlas, s.r, s.frame, pos); -#if 1 - // todo debugging - static std::size_t N = 0; - N++; - auto nframes = atlas->info().nframes; - if (N > nframes*3) - N = 0; - s.frame = (scenery::frame_t)std::min(N, nframes-1); -#endif - } } } diff --git a/editor/scenery-editor.cpp b/editor/scenery-editor.cpp index 1f2fabf3..482b2131 100644 --- a/editor/scenery-editor.cpp +++ b/editor/scenery-editor.cpp @@ -29,7 +29,7 @@ void scenery_editor::next_rotation() { auto r_1 = (rotation_t)_selected.r + 1; auto rot = (rotation_)r_1; - if (rot >= rotation_::COUNT) + if (rot >= rotation_COUNT) rot = (rotation_)0; _selected.r = rot; } @@ -37,7 +37,7 @@ void scenery_editor::next_rotation() void scenery_editor::prev_rotation() { if (_selected.r == (rotation_)0) - _selected.r = (rotation_)((rotation_t)rotation_::COUNT - 1); + _selected.r = (rotation_)((rotation_t)rotation_COUNT - 1); else _selected.r = (rotation_)((rotation_t)_selected.r - 1); } @@ -52,7 +52,7 @@ void scenery_editor::select_tile(const std::shared_ptr<anim_atlas>& atlas, rotat void scenery_editor::clear_selection() { - _selected = { nullptr, rotation_::COUNT, scenery::NO_FRAME }; + _selected = { nullptr, rotation_COUNT, scenery::NO_FRAME }; } auto scenery_editor::get_selected() -> pair diff --git a/editor/scenery-editor.hpp b/editor/scenery-editor.hpp index 9b89d2da..85ccd3be 100644 --- a/editor/scenery-editor.hpp +++ b/editor/scenery-editor.hpp @@ -14,7 +14,7 @@ struct scenery_editor final struct pair final { std::shared_ptr<anim_atlas> atlas; - enum rotation r = rotation::COUNT; + enum rotation r = rotation_COUNT; frame_t frame = scenery::NO_FRAME; operator bool() const; }; diff --git a/editor/update.cpp b/editor/update.cpp index cc765268..60d012d2 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -29,7 +29,7 @@ void app::maybe_initialize_chunk_(const chunk_coords& pos, chunk& c) c[{K, K }].wall_west() = { _wall2, 0 }; c[{K, K+1}].wall_north() = { _wall1, 0 }; c[{K+1, K }].wall_west() = { _wall2, 0 }; - c[{K+1, K+1}].scenery() = { _door, scenery{0, rotation::N} }; + c[{K+1, K+1}].scenery() = { scenery::door, rotation::N, _door, false }; c.mark_modified(); } diff --git a/src/anim-atlas.cpp b/src/anim-atlas.cpp index cbcaac78..b566d19f 100644 --- a/src/anim-atlas.cpp +++ b/src/anim-atlas.cpp @@ -23,7 +23,7 @@ std::uint8_t anim_atlas::rotation_to_index(const anim_def& info, rotation r) noe decltype(anim_atlas::_group_indices) anim_atlas::make_group_indices(const anim_def& a) noexcept { - std::array<std::uint8_t, (std::size_t)rotation::COUNT> array; + std::array<std::uint8_t, (std::size_t)rotation_COUNT> array; for (std::size_t i = 0; i < array.size(); i++) array[i] = rotation_to_index(a, rotation(i)); return array; diff --git a/src/anim-atlas.hpp b/src/anim-atlas.hpp index 36939f68..e3e7243d 100644 --- a/src/anim-atlas.hpp +++ b/src/anim-atlas.hpp @@ -37,7 +37,7 @@ private: GL::Texture2D _tex; String _name; anim_def _info; - std::array<std::uint8_t, (std::size_t)rotation::COUNT> _group_indices = { + std::array<std::uint8_t, (std::size_t)rotation_COUNT> _group_indices = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; diff --git a/src/scenery.cpp b/src/scenery.cpp index 620fb51e..e103d679 100644 --- a/src/scenery.cpp +++ b/src/scenery.cpp @@ -1,7 +1,26 @@ #include "scenery.hpp" +#include "anim-atlas.hpp" +#include "compat/assert.hpp" +#include <algorithm> namespace floormat { +scenery_proto::scenery_proto() noexcept : scenery_proto{scenery::none} {} +scenery_proto::scenery_proto(scenery::none_tag_t) noexcept : frame{scenery::none} {} +scenery_proto::scenery_proto(const std::shared_ptr<anim_atlas>& atlas, const scenery& frame) : + atlas{atlas}, frame{frame} +{} + +scenery_proto::scenery_proto(scenery::generic_tag_t, rotation r, const std::shared_ptr<anim_atlas>& atlas, scenery::frame_t frame) : + atlas{atlas}, frame{scenery::generic, r, *atlas, frame} +{} + +scenery_proto::scenery_proto(scenery::door_tag_t, rotation r, const std::shared_ptr<anim_atlas>& atlas, bool is_open) : + atlas{atlas}, frame{scenery::door, r, *atlas, is_open} +{} + +scenery_proto& scenery_proto::operator=(const scenery_proto&) noexcept = default; + scenery_proto::operator bool() const noexcept { return atlas != nullptr; } scenery_ref::scenery_ref(std::shared_ptr<anim_atlas>& atlas, scenery& frame) noexcept : atlas{atlas}, frame{frame} {} @@ -16,6 +35,65 @@ scenery_ref& scenery_ref::operator=(const scenery_proto& proto) noexcept } scenery_ref::operator scenery_proto() const noexcept { return { atlas, frame }; } -scenery_ref::operator bool() const noexcept { return atlas != nullptr; }; +scenery_ref::operator bool() const noexcept { return atlas != nullptr; } + +scenery::scenery() noexcept : scenery{none_tag_t{}} {} +scenery::scenery(none_tag_t) noexcept : passable{true} {} +scenery::scenery(generic_tag_t, rotation r, const anim_atlas& atlas, frame_t frame) : + frame{frame}, r{r}, type{scenery_type::generic} +{ + fm_assert(frame < atlas.group(r).frames.size()); +} + +scenery::scenery(door_tag_t, rotation r, const anim_atlas& atlas, bool is_open) : + frame{frame_t(is_open ? 0 : atlas.group(r).frames.size()-1)}, + r{r}, passable{is_open}, type{scenery_type::door} +{} + +scenery::scenery(float dt, frame_t frame, rotation r, bool passable, scenery_type type) : + delta{dt}, frame{frame}, r{r}, passable{passable}, type{type} +{} + +void scenery::update(float dt, const anim_atlas& anim) +{ + switch (type) + { + default: + case scenery_type::none: + case scenery_type::generic: + break; + case scenery_type::door: + if (active) + { + const auto hz = std::uint8_t(anim.info().fps); + const auto nframes = (int)anim.info().nframes; + fm_debug_assert(anim.info().fps > 0 && anim.info().fps <= 0xff); + + delta += dt; + const float frame_time = 1000.f/hz; + const auto n = int(delta / frame_time); + delta -= frame_time * n; + fm_debug_assert(delta >= 0); + const std::int8_t dir = passable ? 1 : -1; + const int fr = frame + dir*n; + active = fr > 0 && fr < nframes-1; + passable = fr <= 0; + frame = (frame_t)std::clamp(fr, 0, nframes-1); + if (!active) + delta = 0; + } + break; + } +} + +bool scenery::activate(const anim_atlas& atlas) +{ + if (!active) { + fm_assert(frame == 0 || frame == atlas.info().nframes-1); + active = true; + return true; + } else + return false; +} } // namespace floormat diff --git a/src/scenery.hpp b/src/scenery.hpp index cc8cc159..fadf4da8 100644 --- a/src/scenery.hpp +++ b/src/scenery.hpp @@ -8,23 +8,55 @@ struct anim_atlas; enum class rotation : std::uint8_t { N, NE, E, SE, S, SW, W, NW, - COUNT, +}; + +constexpr inline rotation rotation_COUNT = rotation{8}; + +enum class scenery_type : std::uint8_t { + none, generic, door, }; struct scenery final { + struct none_tag_t final {}; + struct generic_tag_t final {}; + struct door_tag_t final {}; + static constexpr auto NO_FRAME = (std::uint16_t)-1; + static constexpr inline auto none = none_tag_t{}; + static constexpr inline auto generic = generic_tag_t{}; + static constexpr inline auto door = door_tag_t{}; using frame_t = std::uint16_t; + float delta = 0; frame_t frame = NO_FRAME; - rotation r = rotation::N; + rotation r : 3 = rotation::N; + std::uint8_t passable : 1 = false; + std::uint8_t active : 1 = false; + scenery_type type : 3 = scenery_type::none; + + scenery() noexcept; + scenery(none_tag_t) noexcept; + scenery(generic_tag_t, rotation r, const anim_atlas& atlas, frame_t frame = 0); + scenery(door_tag_t, rotation r, const anim_atlas& atlas, bool is_open = false); + scenery(float dt, frame_t frame, rotation r, bool passable, scenery_type type); + + bool activate(const anim_atlas& atlas); + void update(float dt, const anim_atlas& anim); }; struct scenery_proto final { std::shared_ptr<anim_atlas> atlas; scenery frame; + scenery_proto() noexcept; + explicit scenery_proto(scenery::none_tag_t) noexcept; + scenery_proto(const std::shared_ptr<anim_atlas>& atlas, const scenery& frame); + scenery_proto(scenery::generic_tag_t, rotation r, const std::shared_ptr<anim_atlas>& atlas, scenery::frame_t frame = 0); + scenery_proto(scenery::door_tag_t, rotation r, const std::shared_ptr<anim_atlas>& atlas, bool is_open = false); + scenery_proto& operator=(const scenery_proto&) noexcept; + operator bool() const noexcept; }; |