diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-03-23 18:02:03 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-03-23 18:02:03 +0100 |
commit | c772e3273a9ce6dde9026f24ed8903e335e58375 (patch) | |
tree | f9a8885d62fb1e73d97173b7db7eb260c3644a38 | |
parent | bc6e414dec9418d8f839baba32e379dd5bf09b17 (diff) |
w
-rw-r--r-- | src/critter.cpp | 94 |
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_ = {}; |