diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/critter.cpp | 82 | ||||
-rw-r--r-- | src/object.cpp | 62 | ||||
-rw-r--r-- | src/object.hpp | 3 | ||||
-rw-r--r-- | src/scenery.cpp | 5 | ||||
-rw-r--r-- | src/timer-fwd.hpp | 1 | ||||
-rw-r--r-- | src/timer.hpp | 5 |
6 files changed, 70 insertions, 88 deletions
diff --git a/src/critter.cpp b/src/critter.cpp index fb3d7e52..a96e5418 100644 --- a/src/critter.cpp +++ b/src/critter.cpp @@ -16,8 +16,7 @@ namespace floormat { namespace { -constexpr double framerate = 60, move_speed = 60; -constexpr double frame_time = 1/framerate; +using F = float; constexpr auto arrows_to_dir(bool left, bool right, bool up, bool down) { @@ -33,6 +32,7 @@ constexpr auto arrows_to_dir(bool left, bool right, bool up, bool down) switch (bits) { using enum rotation; + default: std::unreachable(); case 0: return rotation{rotation_COUNT}; case L | U: return W; case L | D: return S; @@ -43,28 +43,30 @@ constexpr auto arrows_to_dir(bool left, bool right, bool up, bool down) case R: return NE; case U: return NW; } - std::unreachable(); - fm_assert(false); } constexpr Vector2 rotation_to_vec(rotation r) { - constexpr double c = move_speed * frame_time; - constexpr double d = c / Vector2d{1, 1}.length(); + constexpr double framerate = 60, move_speed = 60; + constexpr double frame_time = F(1)/framerate; + constexpr double b = move_speed * frame_time; + constexpr double inv_sqrt_2 = F{1}/Math::sqrt(F{2}); + constexpr auto d = F(b * inv_sqrt_2); + constexpr auto c = F(b); constexpr Vector2 array[8] = { - Vector2(Vector2d{ 0, -1} * c), - Vector2(Vector2d{ 1, -1} * d), - Vector2(Vector2d{ 1, 0} * c), - Vector2(Vector2d{ 1, 1} * d), - Vector2(Vector2d{ 0, 1} * c), - Vector2(Vector2d{-1, 1} * d), - Vector2(Vector2d{-1, 0} * c), - Vector2(Vector2d{-1, -1} * d), + Vector2{ 0, -1} * c, // N + Vector2{ 1, -1} * d, // NE + Vector2{ 1, 0} * c, // E + Vector2{ 1, 1} * d, // SE + Vector2{ 0, 1} * c, // S + Vector2{-1, 1} * d, // SW + Vector2{-1, 0} * c, // W + Vector2{-1, -1} * d, // NW }; - CORRADE_ASSUME(r < rotation_COUNT); - return array[(size_t)r]; + auto value = array[(size_t)r]; + return value; } constexpr std::array<rotation, 3> rotation_to_similar(rotation r) @@ -133,26 +135,6 @@ void critter::update(size_t i, Ns dt) { if (playable) { -#if 0 - static auto TL = Time::now(); - static Ns TIME{0}; - static unsigned FRAMES; - - if (++FRAMES == 0) - TL = Time::now(); - else - TIME += dt; - - if (++FRAMES > 240) - { - auto t = TL.update(); - Debug{} << "player time" << Time::to_milliseconds(TIME) << Time::to_milliseconds(t); - Debug{} << Time::to_milliseconds(TIME) / Time::to_milliseconds(t); - TIME = Ns{0}; - FRAMES = 0; - } -#endif - const auto new_r = arrows_to_dir(b_L, b_R, b_U, b_D); if (new_r == rotation_COUNT) { @@ -173,16 +155,9 @@ void critter::update_nonplayable(size_t i, Ns dt) void critter::update_movement(size_t i, Ns dt, rotation new_r) { - fm_assert(new_r < rotation_COUNT); - fm_assert(is_dynamic()); - - auto nframes = allocate_frame_time(dt * speed); - if (nframes == 0) - { - static unsigned foo; - //Debug{} << ++foo << "stopped"; - return; - } + const auto fps = atlas->info().fps; + fm_assert(fps > 0); + const auto nframes = allocate_frame_time(delta, dt, speed, fps); const auto rotations = rotation_to_similar(new_r); const unsigned nvecs = (int)new_r & 1 ? 3 : 1; @@ -193,19 +168,19 @@ void critter::update_movement(size_t i, Ns dt, rotation new_r) c->ensure_passability(); - for (auto k = 0u; k < nframes; k++) + for (uint32_t k = 0; k < nframes; k++) { - for (unsigned j = 0; j < nvecs; j++) + for (uint8_t j = 0; j < nvecs; j++) { - const auto vec = rotation_to_vec(rotations[j]); - constexpr auto frac = 65535u; - constexpr auto inv_frac = 1.f / (float)frac; + const auto vec = rotation_to_vec(rotations[j]); + constexpr auto frac = F{65535}; + constexpr auto inv_frac = 1 / frac; const auto sign_vec = Math::sign(vec); auto offset_ = vec + Vector2(offset_frac) * sign_vec * inv_frac; auto off_i = Vector2i(offset_); if (!off_i.isZero()) { - offset_frac = Vector2us(Math::abs(Math::fmod(offset_, 1.f)) * frac); + offset_frac = Vector2us(Math::abs(Math::fmod(offset_, F(1))) * frac); if (can_move_to(off_i)) { move_to(i, off_i, new_r); @@ -215,7 +190,7 @@ void critter::update_movement(size_t i, Ns dt, rotation new_r) } else { - offset_frac = Vector2us(Math::abs(Math::min({1.f,1.f}, offset_)) * frac); + offset_frac = Vector2us(Math::abs(Math::min({F(1),F(1)}, offset_)) * frac); break; } } @@ -243,6 +218,7 @@ critter::critter(object_id id, class chunk& c, const critter_proto& proto) : name = "(Unnamed)"_s; fm_soft_assert(atlas->check_rotation(r)); object::set_bbox_(offset, bbox_offset, Vector2ub(iTILE_SIZE2/2), pass); + fm_soft_assert(speed >= 0); } } // namespace floormat diff --git a/src/object.cpp b/src/object.cpp index 9aca4705..1c242887 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -269,39 +269,47 @@ void object::move_to(Magnum::Vector2i delta) move_to(i, delta, r); } -uint32_t object::allocate_frame_time(Ns dt, uint16_t& accum, uint32_t hz) +uint32_t object::allocate_frame_time(uint16_t& accum, Ns dt_, float speed, uint32_t hz) { + constexpr auto second = uint64_t(1e9), u16_max = uint64_t{65535}; + //dt_ = Ns(16e6); + fm_assert(dt_ >= Ns{}); fm_assert(hz > 0); - fm_assert(dt >= Ns{0}); - constexpr auto ns_in_sec = Ns::Type{Ns(1e9)}; - //const auto count = Ns::Type{ns_in_sec / hz} + accum}; - const auto nsecs = Ns::Type{dt} + accum * ns_in_sec / Ns::Type{65535}; - const auto frame_duration = ns_in_sec / hz; - const auto frames = (uint32_t)(nsecs / frame_duration); - const auto rem = nsecs % frame_duration; - const auto new_accum_ = rem * Ns::Type{65535} / ns_in_sec; - const auto new_accum = (uint16_t)Math::clamp(new_accum_, Ns::Type{0}, Ns::Type{65535}); - [[maybe_unused]] const auto old_accum = accum; - accum = new_accum; -#if 0 - DBG_nospace << "alloc-frame-time: " - << "dt:" << fraction(Time::to_milliseconds(dt)) << "ms" - << ", secs:" << fraction(Time::to_milliseconds(Ns{nsecs}), 1) << " ms" - << ", frames:" << frames - << ", acc:" << new_accum_ - << ", rem:" << rem; + fm_assert(speed >= 0); + + const auto frame_duration_ns = second / hz; + const auto dt_nsec = (uint64_t)int64_t{dt_}; + + const auto nsecs_from_accum = accum * second / u16_max; + const auto nsecs = dt_nsec + nsecs_from_accum; + + const auto ticks = (uint64_t)(nsecs * speed); + const auto rem_ns = ticks % frame_duration_ns; + const auto rem_ = rem_ns * u16_max / second; + + const auto frames = (uint32_t)(ticks / frame_duration_ns); + + const auto rem = (uint16_t)Math::clamp(rem_, uint64_t(0), uint64_t(65535)); + const auto old_accum = accum; (void)old_accum; + accum = rem; +#if 1 + if (frames) + { + DBG_nospace << "alloc-frame: " + << "dt:" << fraction(Time::to_milliseconds(Ns(dt_nsec))) << " ms" + << ", dt-nsec:" << Time::to_milliseconds(Ns(dt_nsec)) + << ", dt-acc:" << Time::to_milliseconds(Ns(nsecs_from_accum)) + << ", Hz:" << hz + << ", old-acc:" << old_accum + << ", frames:" << frames + //<< ", duration:" << Time::to_milliseconds(Ns(frame_duration_ns)) + << ", ticks:" << fraction(Time::to_milliseconds(Ns(ticks)), 1) + << ", rem:" << Time::to_milliseconds(Ns(rem_ns)); + } #endif return frames; } -uint32_t object::allocate_frame_time(Ns dt) -{ - fm_assert(atlas); - auto hz = atlas->info().fps; - fm_assert(hz > 0); - return allocate_frame_time(dt, delta, hz); -} - void object::set_bbox_(Vector2b offset_, Vector2b bb_offset_, Vector2ub bb_size_, pass_mode pass_) { const_cast<Vector2b&>(offset) = offset_; diff --git a/src/object.hpp b/src/object.hpp index e462c8db..b2cf2884 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -85,8 +85,7 @@ struct object void move_to(size_t& i, Vector2i delta, rotation new_r); void move_to(Vector2i delta); - static uint32_t allocate_frame_time(Ns dt, uint16_t& accum, uint32_t hz); - uint32_t allocate_frame_time(Ns dt); + static uint32_t allocate_frame_time(uint16_t& accum, Ns dt, float speed, uint32_t hz); protected: object(object_id id, class chunk& c, const object_proto& proto); diff --git a/src/scenery.cpp b/src/scenery.cpp index b5fd3b59..20fdcad7 100644 --- a/src/scenery.cpp +++ b/src/scenery.cpp @@ -89,8 +89,9 @@ void door_scenery::update(scenery& s, size_t, Ns dt) fm_assert(s.atlas); auto& anim = *s.atlas; const auto nframes = (int)anim.info().nframes; - fm_debug_assert(anim.info().fps > 0 && anim.info().fps <= 0xff); - const auto n = (int)s.allocate_frame_time(dt); + const auto fps = anim.info().fps; + fm_debug_assert(fps > 0 && fps <= 0xff); + const auto n = (int)s.allocate_frame_time(s.delta, dt, 1, fps); if (n == 0) return; const int8_t dir = closing ? 1 : -1; diff --git a/src/timer-fwd.hpp b/src/timer-fwd.hpp index 5e11ce7b..9831319a 100644 --- a/src/timer-fwd.hpp +++ b/src/timer-fwd.hpp @@ -6,6 +6,7 @@ namespace Magnum::Math { template<class T> class Nanoseconds; } namespace floormat { using Ns = Math::Nanoseconds<int64_t>; +//long double operator/(Ns a, Ns b) noexcept; struct Time final { diff --git a/src/timer.hpp b/src/timer.hpp index 24554363..d9b0f602 100644 --- a/src/timer.hpp +++ b/src/timer.hpp @@ -1,12 +1,9 @@ #pragma once #include "timer-fwd.hpp" -#include <mg/Time.h> +#include <mg/Time.h> // todo! replace with my own namespace floormat { -long double operator/(Ns a, Ns b) noexcept; -using namespace Magnum::Math::Literals::TimeLiterals; - constexpr inline size_t fm_DATETIME_BUF_SIZE = 32; const char* format_datetime_to_string(char(&buf)[fm_DATETIME_BUF_SIZE]); |