summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-11-21 12:01:48 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-11-21 12:28:53 +0100
commit9b063b749faedd17fd8f6d76a25d84f066a92814 (patch)
tree4bf4b7106ade3cd762281204bc1e72344bc12739 /src
parent3ed15b56aded3a6f58ef98d0cbe17012e28e9430 (diff)
scenery work
Diffstat (limited to 'src')
-rw-r--r--src/anim-atlas.cpp2
-rw-r--r--src/anim-atlas.hpp2
-rw-r--r--src/scenery.cpp80
-rw-r--r--src/scenery.hpp36
4 files changed, 115 insertions, 5 deletions
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;
};