diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-06 16:04:17 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-06 16:04:17 +0200 |
commit | 2085e643eb422eedba887c40ff4c6331f6f247c2 (patch) | |
tree | ffc3f75a0dfbe55f361d81166ed0ede6d43f7e36 | |
parent | cb484be64de45ad6529952366273978502a17b6d (diff) |
walk script wip
-rw-r--r-- | compat/failwith.hpp | 21 | ||||
-rw-r--r-- | editor/tests/walk-test.cpp | 3 | ||||
-rw-r--r-- | src/critter-script-walk.cpp | 107 | ||||
-rw-r--r-- | src/critter-script.hpp | 4 | ||||
-rw-r--r-- | src/critter.cpp | 31 | ||||
-rw-r--r-- | src/critter.hpp | 38 | ||||
-rw-r--r-- | src/search-result.hpp | 2 |
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; |