summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/critter.cpp82
-rw-r--r--src/object.cpp62
-rw-r--r--src/object.hpp3
-rw-r--r--src/scenery.cpp5
-rw-r--r--src/timer-fwd.hpp1
-rw-r--r--src/timer.hpp5
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]);