summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-05-14 18:40:39 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-05-14 18:54:05 +0200
commit263ab79f393c5b500497448ecaa949a8b8daeb53 (patch)
tree0274797da7e07024d2c369bacfc97aa96f83a3f5
parentd42f407998437db26a8598563af51d99efa3797c (diff)
a
-rw-r--r--editor/tests/walk-test.cpp18
-rw-r--r--src/critter-script-walk.cpp36
-rw-r--r--src/critter.cpp37
-rw-r--r--src/critter.hpp2
4 files changed, 58 insertions, 35 deletions
diff --git a/editor/tests/walk-test.cpp b/editor/tests/walk-test.cpp
index 0032dda2..a317928f 100644
--- a/editor/tests/walk-test.cpp
+++ b/editor/tests/walk-test.cpp
@@ -4,8 +4,11 @@
#include "src/critter.hpp"
#include "src/critter-script.hpp"
#include "src/search-result.hpp"
+#include "src/point.inl"
#include "floormat/main.hpp"
#include "../imgui-raii.hpp"
+#include "src/search-astar.hpp"
+#include <mg/Functions.h>
namespace floormat::tests {
@@ -42,8 +45,19 @@ bool pf_test::handle_mouse_click(app& a, const mouse_button_event& e, bool is_do
{
auto C = a.ensure_player_character(m.world()).ptr;
fm_assert(C->is_dynamic());
- auto S = critter_script::make_walk_script(*ptʹ);
- C->script.do_reassign(move(S), move(C));
+
+ constexpr auto chunk_size = iTILE_SIZE2 * TILE_MAX_DIM;
+ auto pt0 = C->position();
+ auto vec = Math::abs(*ptʹ - pt0) * 2 + chunk_size * 1;
+ auto dist = (uint32_t)vec.length();
+ constexpr auto bb_const = Vector2ui{tile_size_xy / 8};
+ auto bb = Vector2ui{C->bbox_size} + bb_const;
+ auto res = m.astar().Dijkstra(m.world(), C->position(), *ptʹ, C->id, dist, bb, 0);
+ if (!res.empty())
+ {
+ auto S = critter_script::make_walk_script(move(res));
+ C->script.do_reassign(move(S), move(C));
+ }
return true;
}
}
diff --git a/src/critter-script-walk.cpp b/src/critter-script-walk.cpp
index 0af45984..a10cf15d 100644
--- a/src/critter-script-walk.cpp
+++ b/src/critter-script-walk.cpp
@@ -1,7 +1,7 @@
#include "critter-script.hpp"
//#include "raycast.hpp"
#include "compat/failwith.hpp"
-#include "point.hpp"
+#include "point.inl"
#include "nanosecond.hpp"
#include "critter.hpp"
#include "search-result.hpp"
@@ -28,8 +28,8 @@ struct walk_script final : critter_script
void on_destroy(const std::shared_ptr<critter>& c, script_destroy_reason reason) override;
void delete_self() noexcept override;
- walk_script(point dest);
- walk_script(psr path);
+ explicit walk_script(point dest);
+ explicit walk_script(psr path);
bool walk_line(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt);
bool walk_path(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt);
@@ -94,7 +94,15 @@ done:
}
walk_script::walk_script(point dest) : dest{dest}, mode{walk_mode::line} {}
-walk_script::walk_script(psr path) : dest{path.path().back()}, path{move(path)}, mode{walk_mode::path} { fm_assert(!path.empty()); }
+
+walk_script::walk_script(psr pathʹ) :
+ dest{pathʹ.path().back()},
+ path{move(pathʹ)},
+ path_index{0},
+ mode{walk_mode::path}
+{
+ fm_assert(!path.empty());
+}
bool walk_script::walk_line(const std::shared_ptr<critter>& c, size_t& i, const Ns& dtʹ)
{
@@ -105,15 +113,19 @@ bool walk_script::walk_line(const std::shared_ptr<critter>& c, size_t& i, const
bool walk_script::walk_path(const std::shared_ptr<critter>& c, size_t& i, const Ns& dtʹ)
{
- point cur;
- for (cur = path.path()[path_index]; c->position() == cur; path_index++) [[unlikely]]
- if (path_index == path.size()) [[unlikely]]
- return true;
auto dt = dtʹ;
- auto ret = c->move_toward(i, dt, cur);
- Debug{} << "move toward" << cur << dt;
- return ret.blocked;
- // todo allow move_toward() to return portion of dt
+ while (dt != Ns{})
+ {
+ while (path_index < path.size() && c->position() == path.path()[path_index])
+ path_index++;
+ if (path_index == path.size())
+ return true;
+ point cur = path.path()[path_index];
+ auto ret = c->move_toward(i, dt, cur);
+ if (ret.blocked || !ret.moved)
+ return ret.blocked;
+ }
+ return false;
}
} // namespace
diff --git a/src/critter.cpp b/src/critter.cpp
index 07f8466f..505bbe16 100644
--- a/src/critter.cpp
+++ b/src/critter.cpp
@@ -7,6 +7,7 @@
#include "loader/loader.hpp"
#include "src/world.hpp"
#include "src/object.hpp"
+#include "src/nanosecond.inl"
#include "shaders/shader.hpp"
#include "compat/exception.hpp"
#include <cmath>
@@ -317,6 +318,11 @@ constexpr float step_magnitude(Vector2b vec)
return c;
}
+Ns return_unspent_dt(uint32_t nframes, uint32_t i, float speed, Ns frame_duration)
+{
+ return Ns{(uint64_t)((float)(uint64_t)((nframes - i) * frame_duration) / speed)};
+}
+
} // namespace
extern template class Script<critter, critter_script>;
@@ -426,12 +432,17 @@ void critter::update_movement(size_t& i, const Ns& dt, rotation new_r)
}
}
-auto critter::move_toward(size_t& index, const Ns& dt, const point& dest) -> move_result
+auto critter::move_toward(size_t& index, Ns& dt, const point& dest) -> move_result
{
fm_assert(is_dynamic());
const auto& info = atlas->info();
- const auto nframes = alloc_frame_time(dt, delta, info.fps, speed);
+ const auto anim_frames = info.nframes;
+ const auto hz = info.fps;
+ constexpr auto ns_in_sec = Ns((int)1e9);
+ const auto frame_duration = ns_in_sec / hz;
+ const auto nframes = alloc_frame_time(dt, delta, hz, speed);
+ dt = Ns{};
bool moved = false;
if (nframes == 0)
@@ -448,27 +459,12 @@ auto critter::move_toward(size_t& index, const Ns& dt, const point& dest) -> mov
{
//Debug{} << "done!" << from;
//C.set_keys(false, false, false, false);
+ dt = return_unspent_dt(nframes, i, speed, frame_duration);
return { .blocked = false, .moved = moved, };
}
const auto step = next_step(from, dest);
//Debug{} << "step" << step.direction << step.count << "|" << C.position();
- if (step.direction == Vector2b{}) [[unlikely]]
- {
- {
- static bool once = false;
- if (!once) [[unlikely]]
- {
- once = true;
- DBG_nospace << "critter::move_toward: no dir for"
- << " vec:" << (dest - from)
- << " dest:" << dest
- << " from:" << from;
- }
- }
- ok = false;
- break;
- }
- fm_assert(step.count > 0);
+ fm_assert(step.direction != Vector2b{} && step.count > 0);
const auto new_r = dir_from_step(step);
using Frac = decltype(critter::offset_frac_);
constexpr auto frac = (float{limits<Frac>::max}+1)/2;
@@ -489,10 +485,11 @@ auto critter::move_toward(size_t& index, const Ns& dt, const point& dest) -> mov
{
move_to(index, off_i, new_r);
moved = true;
- ++frame %= info.nframes;
+ ++frame %= anim_frames;
}
else
{
+ dt = return_unspent_dt(nframes, i, speed, frame_duration);
ok = false;
break;
}
diff --git a/src/critter.hpp b/src/critter.hpp
index 066a65cd..c569bd33 100644
--- a/src/critter.hpp
+++ b/src/critter.hpp
@@ -36,7 +36,7 @@ struct critter final : object
void update_movement(size_t& i, const Ns& dt, rotation r);
struct move_result { bool blocked, moved; };
- [[nodiscard]] move_result move_toward(size_t& i, const Ns& dt, const point& dest);
+ [[nodiscard]] move_result move_toward(size_t& i, Ns& dt, const point& dest);
Vector2 ordinal_offset(Vector2b offset) const override;
float depth_offset() const override;