summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/critter.cpp94
1 files changed, 57 insertions, 37 deletions
diff --git a/src/critter.cpp b/src/critter.cpp
index 90941860..8acfac65 100644
--- a/src/critter.cpp
+++ b/src/critter.cpp
@@ -99,6 +99,49 @@ constexpr std::array<rotation, 3> rotation_to_similar(rotation r)
}
+template<rotation new_r>
+bool update_movement_1(critter& C, size_t& i, const anim_def& info, uint32_t nframes)
+{
+ const auto rotations = rotation_to_similar(new_r);
+ const unsigned nvecs = (int)new_r & 1 ? 3 : 1;
+ bool can_move = false;
+
+ for (auto k = 0u; k < nframes; k++)
+ {
+ for (unsigned j = 0; j < nvecs; j++)
+ {
+ const auto vec = rotation_to_vec(rotations[j]);
+ using Frac = decltype(critter::offset_frac_);
+ constexpr auto frac = (float{limits<Frac>::max}+1)/2;
+ constexpr auto inv_frac = 1 / frac;
+ const auto from_accum = C.offset_frac_ * inv_frac * vec;
+ auto offset_ = vec + from_accum;
+ auto off_i = Vector2i(offset_);
+ if (!off_i.isZero())
+ {
+ auto rem = Math::fmod(offset_, 1.f).length();
+ C.offset_frac_ = Frac(rem * frac);
+ if (C.can_move_to(off_i))
+ {
+ can_move = true;
+ C.move_to(i, off_i, new_r);
+ ++C.frame %= info.nframes;
+ break;
+ }
+ }
+ else
+ {
+ can_move = true;
+ auto rem = offset_.length();
+ C.offset_frac_ = Frac(rem * frac);
+ break;
+ }
+ }
+ }
+
+ return can_move;
+}
+
} // namespace
critter_proto::critter_proto(const critter_proto&) = default;
@@ -181,49 +224,26 @@ void critter::update_movement(size_t i, const Ns& dt, rotation new_r)
if (nframes == 0)
return;
- const auto rotations = rotation_to_similar(new_r);
- const unsigned nvecs = (int)new_r & 1 ? 3 : 1;
if (r != new_r)
- //if (is_dynamic())
- rotate(i, new_r);
-
+ rotate(i, new_r);
c->ensure_passability();
- bool can_move = false;
- for (auto k = 0u; k < nframes; k++)
+ bool ret;
+
+ switch (new_r)
{
- for (unsigned j = 0; j < nvecs; j++)
- {
- const auto vec = rotation_to_vec(rotations[j]);
- using Frac = decltype(critter::offset_frac_);
- constexpr auto frac = (float{limits<Frac>::max}+1)/2;
- constexpr auto inv_frac = 1 / frac;
- const auto from_accum = offset_frac_ * inv_frac * vec;
- auto offset_ = vec + from_accum;
- auto off_i = Vector2i(offset_);
- if (!off_i.isZero())
- {
- auto rem = Math::fmod(offset_, 1.f).length();
- offset_frac_ = Frac(rem * frac);
- if (can_move_to(off_i))
- {
- can_move = true;
- move_to(i, off_i, new_r);
- ++frame %= info.nframes;
- break;
- }
- }
- else
- {
- can_move = true;
- auto rem = offset_.length();
- offset_frac_ = Frac(rem * frac);
- break;
- }
- }
+ default: std::unreachable();
+ case (rotation)0: ret = update_movement_1<(rotation)0>(*this, i, info, nframes); break;
+ case (rotation)1: ret = update_movement_1<(rotation)1>(*this, i, info, nframes); break;
+ case (rotation)2: ret = update_movement_1<(rotation)2>(*this, i, info, nframes); break;
+ case (rotation)3: ret = update_movement_1<(rotation)3>(*this, i, info, nframes); break;
+ case (rotation)4: ret = update_movement_1<(rotation)4>(*this, i, info, nframes); break;
+ case (rotation)5: ret = update_movement_1<(rotation)5>(*this, i, info, nframes); break;
+ case (rotation)6: ret = update_movement_1<(rotation)6>(*this, i, info, nframes); break;
+ case (rotation)7: ret = update_movement_1<(rotation)7>(*this, i, info, nframes); break;
}
- if (!can_move) [[unlikely]]
+ if (!ret) [[unlikely]]
{
delta = {};
offset_frac_ = {};