summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-03-02 10:20:40 +0100
committerStanislaw Halik <sthalik@misaki.pl>2024-03-02 10:20:40 +0100
commit9ff017f1d4c1502fca9797aa4b38351c97e57982 (patch)
tree5b122d52ddec31c988e23a70531a968466e73bf6
parent58d95d559276b556f584411d5c3ea0a986f3fbc4 (diff)
a
-rw-r--r--editor/app.cpp46
-rw-r--r--editor/inspect-types.cpp14
-rw-r--r--editor/update.cpp10
-rw-r--r--entity/metadata.hpp2
-rw-r--r--src/critter.cpp2
-rw-r--r--src/critter.hpp2
-rw-r--r--src/object.hpp2
-rw-r--r--src/world.cpp68
-rw-r--r--src/world.hpp12
-rw-r--r--test/app.cpp3
-rw-r--r--test/app.hpp1
-rw-r--r--test/critter.cpp55
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