summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-05-06 16:04:17 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-05-06 16:04:17 +0200
commit2085e643eb422eedba887c40ff4c6331f6f247c2 (patch)
treeffc3f75a0dfbe55f361d81166ed0ede6d43f7e36
parentcb484be64de45ad6529952366273978502a17b6d (diff)
walk script wip
-rw-r--r--compat/failwith.hpp21
-rw-r--r--editor/tests/walk-test.cpp3
-rw-r--r--src/critter-script-walk.cpp107
-rw-r--r--src/critter-script.hpp4
-rw-r--r--src/critter.cpp31
-rw-r--r--src/critter.hpp38
-rw-r--r--src/search-result.hpp2
7 files changed, 111 insertions, 95 deletions
diff --git a/compat/failwith.hpp b/compat/failwith.hpp
new file mode 100644
index 00000000..580ed923
--- /dev/null
+++ b/compat/failwith.hpp
@@ -0,0 +1,21 @@
+#pragma once
+#include "compat/assert.hpp"
+#if !defined __GNUG__ && !defined _MSC_VER
+#include <utility>
+#endif
+
+namespace floormat {
+
+template<typename T> T failwith(const char* str)
+{
+ fm_abort("%s", str);
+#ifdef __GNUG__
+ __builtin_unreachable();
+#elif defined _MSC_VER
+ __assume(false);
+#else
+ std::unreachable();
+#endif
+}
+
+} // namespace floormat
diff --git a/editor/tests/walk-test.cpp b/editor/tests/walk-test.cpp
index e3b6f8d5..0032dda2 100644
--- a/editor/tests/walk-test.cpp
+++ b/editor/tests/walk-test.cpp
@@ -40,10 +40,9 @@ bool pf_test::handle_mouse_click(app& a, const mouse_button_event& e, bool is_do
{
if (auto ptʹ = a.cursor_state().point())
{
-
auto C = a.ensure_player_character(m.world()).ptr;
fm_assert(C->is_dynamic());
- auto S = critter_script::make_walk_script(*ptʹ, {}, critter_script::walk_mode::line);
+ auto S = critter_script::make_walk_script(*ptʹ);
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 8799aed5..bd2b00ca 100644
--- a/src/critter-script-walk.cpp
+++ b/src/critter-script-walk.cpp
@@ -1,16 +1,15 @@
#include "critter-script.hpp"
//#include "raycast.hpp"
+#include "critter.hpp"
+#include "compat/failwith.hpp"
#include "point.hpp"
#include "critter.hpp"
#include "search-result.hpp"
#include "search-astar.hpp"
#include "entity/name-of.hpp"
-#include <cr/Optional.h>
namespace floormat {
-using walk_mode = critter_script::walk_mode;
-
namespace {
bool walk_line(point dest, const std::shared_ptr<critter>& c, size_t& i, const Ns& dt)
@@ -19,10 +18,19 @@ bool walk_line(point dest, const std::shared_ptr<critter>& c, size_t& i, const N
return res.blocked || c->position() == dest;
}
+bool walk_path(point dest, const path_search_result& path, const std::shared_ptr<critter>& c, size_t& i, const Ns& dt)
+{
+ return {};
+}
+
+struct walk_script;
+constexpr StringView script_name = name_of<walk_script>;
+using ScriptPtr = Pointer<critter_script>;
+using psr = path_search_result;
+
struct walk_script final : critter_script
{
- struct line_tag_t {};
- struct path_tag_t {};
+ enum class walk_mode : uint8_t { none, line, path, };
StringView name() const override;
const void* id() const override;
@@ -31,91 +39,74 @@ 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, line_tag_t);
- //walk_script(point dest, path_search_result path, path_tag_t);
+ walk_script(point dest);
+ walk_script(psr path);
private:
point dest;
- Optional<path_search_result> path;
- walk_mode mode = walk_mode::none;
+ psr path;
+ uint32_t path_index = -1u;
+ walk_mode mode = failwith<walk_mode>("walk_mode not set");
};
-walk_script::walk_script(point dest, line_tag_t) :
- dest{dest}, mode{walk_mode::line}
-{
-}
+StringView walk_script::name() const { return "walk"_s; }
+const void* walk_script::id() const { return &script_name; }
+void walk_script::on_destroy(const std::shared_ptr<critter>& c, script_destroy_reason) { c->clear_auto_movement(); }
+void walk_script::delete_self() noexcept { delete this; }
void walk_script::on_init(const std::shared_ptr<critter>& c)
{
- c->movement.AUTO = true;
+ Debug{} << "| start walking from" << c->position() << "to" << dest;
+ c->moves.AUTO = true;
+
+ switch (mode)
+ {
+ case walk_mode::line:
+ break;
+ case walk_mode::path:
+ fm_assert(!path.empty());
+ break;
+ default:
+ std::unreachable();
+ fm_assert(false);
+ }
}
void walk_script::on_update(const std::shared_ptr<critter>& c, size_t& i, const Ns& dt)
{
- auto& m = c->movement;
-
- if (m.L | m.R | m.U | m.D)
- m.AUTO = false;
-
- if (!m.AUTO)
+ auto& m = c->moves;
+ if (c->maybe_stop_auto_movement())
goto done;
switch (mode)
{
- case walk_mode::none:
- fm_abort("bad walk_mode 'none'");
case walk_mode::line:
fm_assert(!path);
if (walk_line(dest, c, i, dt))
goto done;
return;
case walk_mode::path:
- fm_abort("todo!");
- //break;
+ if (walk_path(dest, path, c, i, dt))
+ goto done;
+ return;
+ case walk_mode::none:
+ break;
}
- std::unreachable();
fm_assert(false);
done:
+ //path = {};
Debug{} << " finished walking";
- m.AUTO = false;
+ c->clear_auto_movement();
c->script.do_clear(c);
}
-constexpr StringView script_name = name_of<walk_script>;
-
-StringView walk_script::name() const { return "walk"_s; }
-
-const void* walk_script::id() const
-{
- return &script_name;
-}
-
-void walk_script::on_destroy(const std::shared_ptr<critter>& c, script_destroy_reason reason)
-{
-}
-
-void walk_script::delete_self() noexcept
-{
- delete this;
-}
+walk_script::walk_script(point dest) : dest{dest}, mode{walk_mode::line} {}
+walk_script::walk_script(psr path) : path{move(path)}, mode{walk_mode::path} { fm_assert(!path.empty()); }
} // namespace
-Pointer<critter_script> critter_script::make_walk_script(point dest, const path_search_result& path, walk_mode mode)
-{
- switch (mode)
- {
- case walk_mode::line:
- fm_assert(path.empty());
- return Pointer<critter_script>(new walk_script{dest, walk_script::line_tag_t{}});
- case walk_mode::path:
- fm_abort("todo!");
- fm_assert(!path.empty());
- case walk_mode::none:
- break;
- }
- fm_abort("bad walk_mode %d", (int)mode);
-}
+ScriptPtr critter_script::make_walk_script(point dest) { return ScriptPtr(new walk_script{dest}); }
+ScriptPtr critter_script::make_walk_script(psr path) { return ScriptPtr(new walk_script{move(path)}); }
} // namespace floormat
diff --git a/src/critter-script.hpp b/src/critter-script.hpp
index a8258ea0..c26d57e0 100644
--- a/src/critter-script.hpp
+++ b/src/critter-script.hpp
@@ -26,8 +26,8 @@ struct critter_script : base_script
object_type type() const override;
- enum class walk_mode : uint8_t { none, line, path, };
- static Pointer<critter_script> make_walk_script(point to, const path_search_result& path, walk_mode mode);
+ static Pointer<critter_script> make_walk_script(point to);
+ static Pointer<critter_script> make_walk_script(path_search_result path);
};
} // namespace floormat
diff --git a/src/critter.cpp b/src/critter.cpp
index 4a4fa617..07f8466f 100644
--- a/src/critter.cpp
+++ b/src/critter.cpp
@@ -18,6 +18,8 @@ namespace floormat {
namespace {
+constexpr auto m_auto_mask = critter::move_u { .bits {.AUTO = true} };
+
constexpr auto arrows_to_dir(bool left, bool right, bool up, bool down)
{
constexpr unsigned L = 1 << 3, R = 1 << 2, U = 1 << 1, D = 1 << 0;
@@ -341,14 +343,14 @@ bool critter_proto::operator==(const object_proto& e0) const
return name == s0.name && playable == s0.playable;
}
-void critter::set_keys(bool L, bool R, bool U, bool D)
-{
- movement = { L, R, U, D, movement.AUTO, false, false, false };
-}
-
-void critter::set_keys_auto()
+void critter::set_keys(bool L, bool R, bool U, bool D) { moves = { L, R, U, D, moves.AUTO, }; }
+void critter::set_keys_auto() { moves_ = m_auto_mask.val; }
+void critter::clear_auto_movement() { moves_ &= ~m_auto_mask.val; }
+bool critter::maybe_stop_auto_movement()
{
- movement = { false, false, false, false, true, false, false, false };
+ bool b1 = moves_ == m_auto_mask.val;
+ bool b2 = moves.AUTO &= b1;
+ return !b2;
}
float critter::depth_offset() const
@@ -372,13 +374,11 @@ void critter::update(const std::shared_ptr<object>& ptrʹ, size_t& i, const Ns&
if (check_script_update_2(script.state())) [[unlikely]]
return;
#endif
- if (playable && !movement.AUTO) [[unlikely]]
+ if (playable) [[unlikely]]
{
- movement.AUTO &= (movement.L | movement.R | movement.U | movement.D) == 0;
-
- if (!movement.AUTO)
+ if (!moves.AUTO)
{
- const auto new_r = arrows_to_dir(movement.L, movement.R, movement.U, movement.D);
+ const auto new_r = arrows_to_dir(moves.L, moves.R, moves.U, moves.D);
if (new_r == rotation_COUNT)
{
offset_frac_ = {};
@@ -430,15 +430,10 @@ auto critter::move_toward(size_t& index, const Ns& dt, const point& dest) -> mov
{
fm_assert(is_dynamic());
- if (movement.L | movement.R | movement.U | movement.D) [[unlikely]]
- return { .blocked = true, .moved = false, };
-
const auto& info = atlas->info();
const auto nframes = alloc_frame_time(dt, delta, info.fps, speed);
bool moved = false;
- set_keys_auto();
-
if (nframes == 0)
return { .blocked = false, .moved = moved };
@@ -509,6 +504,8 @@ auto critter::move_toward(size_t& index, const Ns& dt, const point& dest) -> mov
}
}
+ // todo return unused movement frames into the offset_frac pool
+
if (!ok) [[unlikely]]
{
//Debug{} << "bad";
diff --git a/src/critter.hpp b/src/critter.hpp
index c1e8ded0..066a65cd 100644
--- a/src/critter.hpp
+++ b/src/critter.hpp
@@ -38,8 +38,6 @@ struct critter final : object
struct move_result { bool blocked, moved; };
[[nodiscard]] move_result move_toward(size_t& i, const Ns& dt, const point& dest);
- void set_keys(bool L, bool R, bool U, bool D);
- void set_keys_auto();
Vector2 ordinal_offset(Vector2b offset) const override;
float depth_offset() const override;
@@ -47,32 +45,42 @@ struct critter final : object
void destroy_script_pre(const std::shared_ptr<object>& ptr, script_destroy_reason r) override;
void destroy_script_post() override;
+ void clear_auto_movement();
+ bool maybe_stop_auto_movement();
+ void set_keys(bool L, bool R, bool U, bool D);
+ void set_keys_auto();
+
Script<critter_script, critter> script;
String name;
float speed = 1;
uint16_t offset_frac_ = 0; // todo! remove underscore
- struct movement_s
+ bool playable : 1 = false;
+
+ struct move_s
{
- bool L : 1 = false;
- bool R : 1 = false;
- bool U : 1 = false;
- bool D : 1 = false;
+ bool L : 1 = false;
+ bool R : 1 = false;
+ bool U : 1 = false;
+ bool D : 1 = false;
bool AUTO : 1 = false;
-
- bool _pad1 : 1;
- bool _pad2 : 1;
- bool _pad3 : 1;
+ bool pad1 : 1 = false;
+ bool pad2 : 1 = false;
+ bool pad3 : 1 = false;
//bool _pad4 : 1;
};
- union
+ union move_u
{
- uint8_t movement_value = 0;
- movement_s movement;
+ move_s bits;
+ uint8_t val = 0;
};
- bool playable : 1 = false;
+ union
+ {
+ move_s moves;
+ uint8_t moves_ = 0;
+ };
private:
friend class world;
diff --git a/src/search-result.hpp b/src/search-result.hpp
index afbca8af..3d91643d 100644
--- a/src/search-result.hpp
+++ b/src/search-result.hpp
@@ -30,7 +30,7 @@ struct path_search_result final
explicit operator bool() const;
path_search_result();
- path_search_result(const path_search_result& x) noexcept;
+ explicit path_search_result(const path_search_result& x) noexcept;
path_search_result& operator=(const path_search_result& x) noexcept;
path_search_result(path_search_result&&) noexcept;
path_search_result& operator=(path_search_result&&) noexcept;