summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--draw/anim.cpp11
-rw-r--r--editor/scenery-editor.cpp6
-rw-r--r--editor/scenery-editor.hpp2
-rw-r--r--editor/update.cpp2
-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
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;
};