diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-03-02 10:20:40 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-03-02 10:20:40 +0100 |
commit | 9ff017f1d4c1502fca9797aa4b38351c97e57982 (patch) | |
tree | 5b122d52ddec31c988e23a70531a968466e73bf6 | |
parent | 58d95d559276b556f584411d5c3ea0a986f3fbc4 (diff) |
a
-rw-r--r-- | editor/app.cpp | 46 | ||||
-rw-r--r-- | editor/inspect-types.cpp | 14 | ||||
-rw-r--r-- | editor/update.cpp | 10 | ||||
-rw-r--r-- | entity/metadata.hpp | 2 | ||||
-rw-r--r-- | src/critter.cpp | 2 | ||||
-rw-r--r-- | src/critter.hpp | 2 | ||||
-rw-r--r-- | src/object.hpp | 2 | ||||
-rw-r--r-- | src/world.cpp | 68 | ||||
-rw-r--r-- | src/world.hpp | 12 | ||||
-rw-r--r-- | test/app.cpp | 3 | ||||
-rw-r--r-- | test/app.hpp | 1 | ||||
-rw-r--r-- | test/critter.cpp | 55 |
12 files changed, 157 insertions, 60 deletions
diff --git a/editor/app.cpp b/editor/app.cpp index 5e06d93a..dafea3d9 100644 --- a/editor/app.cpp +++ b/editor/app.cpp @@ -30,51 +30,7 @@ const cursor_state& app::cursor_state() { return cursor; } shared_ptr_wrapper<critter> app::ensure_player_character(world& w) { - if (_character_id) - { - std::shared_ptr<critter> tmp; - if (auto C = w.find_object(_character_id); C && C->type() == object_type::critter) - { - auto ptr = std::static_pointer_cast<critter>(C); - return {ptr}; - } - } - _character_id = 0; - - auto id = (object_id)-1; - - shared_ptr_wrapper<critter> ret; - - for (const auto& [coord, c] : w.chunks()) - { - for (const auto& e_ : c.objects()) - { - const auto& e = *e_; - if (e.type() == object_type::critter) - { - const auto& C = static_cast<const critter&>(e); - if (C.playable) - { - id = std::min(id, C.id); - ret.ptr = std::static_pointer_cast<critter>(e_); - } - } - } - } - - if (id != (object_id)-1) - _character_id = id; - else - { - critter_proto cproto; - cproto.name = "Player"_s; - cproto.speed = 10; - cproto.playable = true; - ret.ptr = w.make_object<critter>(w.make_id(), global_coords{}, cproto); - _character_id = ret.ptr->id; - } - fm_debug_assert(ret.ptr); - return ret; + return w.ensure_player_character(_character_id); } void app::reset_world(class world&& w_) diff --git a/editor/inspect-types.cpp b/editor/inspect-types.cpp index fe33a760..44e85678 100644 --- a/editor/inspect-types.cpp +++ b/editor/inspect-types.cpp @@ -28,7 +28,7 @@ struct entity_accessors<object, inspect_intent_t> { }, E::type<StringView>::field{"atlas"_s, [](const object& x) { return loader.strip_prefix(x.atlas->name()); }, - [](object&, StringView) {}, + ignored_write, constantly(st::readonly), }, E::type<rotation>::field{"rotation"_s, @@ -36,14 +36,22 @@ struct entity_accessors<object, inspect_intent_t> { [](object& x, rotation r) { x.rotate(x.index(), r); }, }, E::type<uint16_t>::field{"frame"_s, - [](const object& x) { return x.frame; }, + &object::frame, [](object& x, uint16_t value) { x.frame = value; }, [](const object& x) { return constraints::range<uint16_t>{0, !x.atlas ? uint16_t(0) : uint16_t(x.atlas->info().nframes-1)}; }, }, + E::type<Vector3i>::field{"chunk"_s, + [](const object& x) { return Vector3i(x.chunk().coord()); }, + ignored_write, + }, + E::type<Vector2i>::field{"tile"_s, + [](const object& x) { return Vector2i(x.coord.local()); }, + ignored_write, + }, E::type<Vector2i>::field{"offset"_s, - [](const object& x) { return Vector2i(x.offset); }, + [](const object& x) { return Vector2i(x.offset); }, // todo return Vector2b //[](object& x, Vector2i value) { x.set_bbox(value, x.bbox_offset, x.bbox_size, x.pass); }, [](object& x, Vector2i value) { x.move_to(value - Vector2i(x.offset)); }, //constantly(constraints::range{Vector2b(iTILE_SIZE2/-2), Vector2b(iTILE_SIZE2/2)}), diff --git a/editor/update.cpp b/editor/update.cpp index 8c3349e5..beb7c048 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -132,16 +132,16 @@ void app::do_emit_timestamp() char buf[fm_DATETIME_BUF_SIZE]; format_datetime_to_string(buf); - if (time >= 1e5f) + if (time >= 1e5) + fm_debug("%s%s0x%08x %.1f" " s", buf, prefix, counter++, time*1e-3); + else if (time >= 1e4) fm_debug("%s%s0x%08x %.2f" " s", buf, prefix, counter++, time*1e-3); - else if (time >= 1e4f) - fm_debug("%s%s0x%08x %.2f" " s", buf, prefix, counter++, time*1e-3); - else if (time >= 1e3f) + else if (time >= 1e3) fm_debug("%s%s0x%08x %.2f" " ms", buf, prefix, counter++, time); else if (time > 0) fm_debug("%s%s0x%08x %.4f" " ms", buf, prefix, counter++, time); else - fm_debug("%s%s0x%08x 0" " ms", buf, prefix, counter++); + fm_debug("%s%s0x%08x 0 ms", buf, prefix, counter++); _timestamp = now.stamp; } diff --git a/entity/metadata.hpp b/entity/metadata.hpp index 41c57186..3da3dcb0 100644 --- a/entity/metadata.hpp +++ b/entity/metadata.hpp @@ -246,6 +246,8 @@ constexpr bool find_in_tuple(F&& fun, Tuple&& tuple) return false; } +constexpr inline auto ignored_write = []<typename O, typename T>(O&, T) {}; + } // namespace floormat::entities namespace floormat { diff --git a/src/critter.cpp b/src/critter.cpp index f018f274..b187c33a 100644 --- a/src/critter.cpp +++ b/src/critter.cpp @@ -212,7 +212,7 @@ critter::operator critter_proto() const return ret; } -critter::critter(object_id id, class chunk& c, const critter_proto& proto) : +critter::critter(object_id id, class chunk& c, critter_proto proto) : // todo! check if it gets move-constructed object{id, c, proto}, name{proto.name}, speed{proto.speed}, diff --git a/src/critter.hpp b/src/critter.hpp index 01159710..fc3e8f17 100644 --- a/src/critter.hpp +++ b/src/critter.hpp @@ -41,7 +41,7 @@ struct critter final : object private: friend class world; - critter(object_id id, class chunk& c, const critter_proto& proto); + critter(object_id id, class chunk& c, critter_proto proto); }; template<> struct object_type_<struct critter> : std::integral_constant<object_type, object_type::critter> {}; diff --git a/src/object.hpp b/src/object.hpp index f15699bb..49d861aa 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -48,7 +48,7 @@ struct object const Vector2b offset, bbox_offset; const Vector2ub bbox_size; uint16_t delta = 0, frame = 0; - const rotation r = rotation::N; + const rotation r = rotation::N; // todo remove bitfield? const pass_mode pass = pass_mode::see_through; bool ephemeral : 1 = false; //char _pad[4]; // got 4 bytes left diff --git a/src/world.cpp b/src/world.cpp index ef0de7ae..650f1494 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,6 +1,8 @@ #include "world.hpp" #include "chunk.hpp" #include "object.hpp" +#include "critter.hpp" +#include "compat/shared-ptr-wrapper.hpp" #include "compat/int-hash.hpp" #include "compat/exception.hpp" #include <cr/GrowableArray.h> @@ -95,7 +97,7 @@ chunk& world::operator[](chunk_coords_ coord) noexcept return *c; } -auto world::operator[](global_coords pt) noexcept -> pair +auto world::operator[](global_coords pt) noexcept -> pair_chunk_tile { auto& c = operator[](pt.chunk3()); return { c, c[pt.local()] }; @@ -196,4 +198,68 @@ auto world::neighbors(chunk_coords_ coord) -> std::array<chunk*, 8> return ret; } +const critter_proto& world::make_player_proto() +{ + static const critter_proto p = [] + { + critter_proto cproto; + cproto.name = "Player"_s; + cproto.speed = 10; + cproto.playable = true; + return cproto; + }(); + return p; +} + +shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id) +{ + return ensure_player_character(id, make_player_proto()); +} + +shared_ptr_wrapper<critter> world::ensure_player_character(object_id& id_, critter_proto p) +{ + if (id_) + { + std::shared_ptr<critter> tmp; + if (auto C = find_object(id_); C && C->type() == object_type::critter) + { + auto ptr = std::static_pointer_cast<critter>(C); + return {ptr}; + } + } + id_ = 0; + + auto id = (object_id)-1; + + shared_ptr_wrapper<critter> ret; + + for (const auto& [coord, c] : chunks()) // todo use world::_objects + { + for (const auto& e_ : c.objects()) + { + const auto& e = *e_; + if (e.type() == object_type::critter) + { + const auto& C = static_cast<const critter&>(e); + if (C.playable) + { + id = std::min(id, C.id); + ret.ptr = std::static_pointer_cast<critter>(e_); + } + } + } + } + + if (id != (object_id)-1) + id_ = id; + else + { + p.playable = true; + ret.ptr = make_object<critter>(make_id(), global_coords{}, p); + id_ = ret.ptr->id; + } + fm_debug_assert(ret.ptr); + return ret; +} + } // namespace floormat diff --git a/src/world.hpp b/src/world.hpp index 19a31a46..c6846750 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -10,7 +10,10 @@ namespace floormat { struct object; +struct critter; +struct critter_proto; template<typename T> struct object_type_; +template<typename T> struct shared_ptr_wrapper; class world final { @@ -43,6 +46,7 @@ private: void do_kill_object(object_id id); std::shared_ptr<object> find_object_(object_id id); + [[noreturn]] static void throw_on_wrong_object_type(object_id id, object_type actual, object_type expected); friend struct object; @@ -52,10 +56,10 @@ public: ~world() noexcept; explicit world(std::unordered_map<chunk_coords_, chunk>&& chunks); - struct pair final { chunk& c; tile_ref t; }; // NOLINT + struct pair_chunk_tile final { chunk& c; tile_ref t; }; // NOLINT chunk& operator[](chunk_coords_ c) noexcept; - pair operator[](global_coords pt) noexcept; // todo maybe remove this overload? + pair_chunk_tile operator[](global_coords pt) noexcept; // todo maybe remove this overload? chunk* at(chunk_coords_ c) noexcept; bool contains(chunk_coords_ c) const noexcept; void clear(); @@ -90,6 +94,10 @@ public: template<typename T = object> std::shared_ptr<T> find_object(object_id id); + shared_ptr_wrapper<critter> ensure_player_character(object_id& id, critter_proto p); + shared_ptr_wrapper<critter> ensure_player_character(object_id& id); + static const critter_proto& make_player_proto(); + bool is_teardown() const { return _teardown; } object_id object_counter() const { return _object_counter; } [[nodiscard]] object_id make_id() { return ++_object_counter; } diff --git a/test/app.cpp b/test/app.cpp index 4677de39..8bccfbbd 100644 --- a/test/app.cpp +++ b/test/app.cpp @@ -51,6 +51,7 @@ int test_app::exec() FM_TEST(test_entity), FM_TEST(test_iptr), FM_TEST(test_hash), + FM_TEST(test_critter), FM_TEST(test_raycast), FM_TEST(test_json), FM_TEST(test_time), @@ -111,7 +112,7 @@ int test_app::exec() fm_assert(num_tabs <= tab_limit); for (auto i = 0uz; i < num_tabs; i++) std::fputc('\t', s); - std::fprintf(s, "% 12.3f ms\n", (double)ms); + std::fprintf(s, "%12.3f ms\n", (double)ms); std::fflush(s); } } diff --git a/test/app.hpp b/test/app.hpp index d100ab13..e7db04cb 100644 --- a/test/app.hpp +++ b/test/app.hpp @@ -25,6 +25,7 @@ struct test_app final : private FM_APPLICATION static void test_astar_pool(); static void test_bitmask(); static void test_coords(); + static void test_critter(); static void test_dijkstra(); static void test_entity(); static void test_hash(); diff --git a/test/critter.cpp b/test/critter.cpp new file mode 100644 index 00000000..6eb42315 --- /dev/null +++ b/test/critter.cpp @@ -0,0 +1,55 @@ +#include "app.hpp" +#include "compat/shared-ptr-wrapper.hpp" +#include "src/critter.hpp" +#include "src/world.hpp" +#include "src/wall-atlas.hpp" +#include "loader/loader.hpp" + +namespace floormat { + +namespace { + +/* ***** TEST 1 ***** + * + * wall n 0x0 - 8:9 + * wall n 0x1 - 8:0 + * + * npc speed=5 bbox-offset=0 bbox-size=32x32 + * + * before chunk=0x0 tile=8:15 offset=-8:8 + * after chunk=0x0 tile=8:9 offset=-8:-16 +*/ + +template<typename F> void test1(F&& make_dt) +{ + const auto W = wall_image_proto{ loader.wall_atlas("empty"), 0 }; + + auto w = world(); + w[{{0,0,0}, {8,9}}].t.wall_north() = W; + w[{{0,1,0}, {8,0}}].t.wall_north() = W; + + critter_proto cproto; + cproto.name = "Player"_s; + cproto.speed = 10; + cproto.playable = true; + + object_id id = 0; + w.ensure_player_character(id, move(cproto)); + + w[chunk_coords_{0,0,0}].mark_modified(); + w[chunk_coords_{0,1,0}].mark_modified(); +} + +template<typename F> void test2(F&& make_dt) +{ + // TODO diagonal! +} + +} // namespace + +void test_app::test_critter() +{ + +} + +} // namespace floormat |