diff options
-rw-r--r-- | editor/update.cpp | 40 | ||||
-rw-r--r-- | src/critter.cpp | 2 | ||||
-rw-r--r-- | src/critter.hpp | 2 | ||||
-rw-r--r-- | src/light.cpp | 2 | ||||
-rw-r--r-- | src/light.hpp | 2 | ||||
-rw-r--r-- | src/object.hpp | 3 | ||||
-rw-r--r-- | src/scenery.cpp | 6 | ||||
-rw-r--r-- | src/scenery.hpp | 6 | ||||
-rw-r--r-- | test/serializer.cpp | 5 |
9 files changed, 50 insertions, 18 deletions
diff --git a/editor/update.cpp b/editor/update.cpp index 55d0ec4a..a4b9bbcd 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -225,7 +225,7 @@ void app::apply_commands(const key_set& keys) void app::update_world(Ns dt) { auto& world = M->world(); - world.increment_frame_no(); + const auto frame_no = world.increment_frame_no(); auto [minx, maxx, miny, maxy] = M->get_draw_bounds(); minx--; miny--; maxx++; maxy++; for (int8_t z = chunk_z_min; z <= chunk_z_max; z++) @@ -237,10 +237,42 @@ void app::update_world(Ns dt) continue; auto& c = *cʹ; const auto& es = c.objects(); - const auto size = es.size(); - for (auto i = (int)(size-1); i >= 0; i--) - es[i]->update((unsigned)i, dt); + auto size = es.size(); + for (auto i = 0uz; i < size; i++) + { + auto& e = *es[i]; + if (e.last_frame_no == frame_no) [[unlikely]] + continue; + e.last_frame_no = frame_no; + const auto* const ch = &e.chunk(); + size_t index = i; + e.update(index, dt); + if (&e.chunk() != ch || (uint32_t)index > i) [[unlikely]] + { + i--; + size = es.size(); + } + } + } + +#ifndef FM_NO_DEBUG + for (int8_t z = chunk_z_min; z <= chunk_z_max; z++) + for (int16_t y = miny; y <= maxy; y++) + for (int16_t x = minx; x <= maxx; x++) + { + auto* cʹ = world.at({x, y, z}); + if (!cʹ) + continue; + auto& c = *cʹ; + const auto& es = c.objects(); + auto size = es.size(); + for (auto i = 0uz; i < size; i++) + { + auto& e = *es[i]; + fm_assert(e.last_frame_no == frame_no); + } } +#endif } void app::update_character([[maybe_unused]] Ns dt) diff --git a/src/critter.cpp b/src/critter.cpp index 21dc74bd..5b80ab81 100644 --- a/src/critter.cpp +++ b/src/critter.cpp @@ -362,7 +362,7 @@ Vector2 critter::ordinal_offset(Vector2b offset) const return Vector2(offset); } -void critter::update(size_t i, const Ns& dt) +void critter::update(size_t& i, const Ns& dt) { if (playable) [[unlikely]] { diff --git a/src/critter.hpp b/src/critter.hpp index 18f714e5..40423b3f 100644 --- a/src/critter.hpp +++ b/src/critter.hpp @@ -29,7 +29,7 @@ struct critter final : object object_type type() const noexcept override; explicit operator critter_proto() const; - void update(size_t i, const Ns& dt) override; // todo! return true when the position changed + void update(size_t& i, const Ns& dt) override; // todo! // add a field: last_update_frame. if doesn't equal to the current world's update // frame, update() gets called and last_update_frame is set to current frame. diff --git a/src/light.cpp b/src/light.cpp index 0e36fd6d..3e25dfc5 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -53,7 +53,7 @@ light::operator light_proto() const } object_type light::type() const noexcept { return object_type::light; } -void light::update(size_t, const Ns&) {} +void light::update(size_t&, const Ns&) {} bool light::is_dynamic() const { return true; } bool light::is_virtual() const { return true; } diff --git a/src/light.hpp b/src/light.hpp index 3d0d3546..ecc45d31 100644 --- a/src/light.hpp +++ b/src/light.hpp @@ -33,7 +33,7 @@ struct light final : object Vector2 ordinal_offset(Vector2b offset) const override; float depth_offset() const override; object_type type() const noexcept override; - void update(size_t i, const Ns& dt) override; + void update(size_t& i, const Ns& dt) override; bool is_dynamic() const override; bool is_virtual() const override; diff --git a/src/object.hpp b/src/object.hpp index ae930259..66cf4d6b 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -43,6 +43,7 @@ struct object fm_DECLARE_DELETED_COPY_ASSIGNMENT(object); const object_id id = 0; + uint64_t last_frame_no = 0; class chunk* const c; const std::shared_ptr<anim_atlas> atlas; const global_coords coord; @@ -71,7 +72,7 @@ struct object virtual object_type type() const noexcept = 0; virtual bool can_activate(size_t i) const; virtual bool activate(size_t i); - virtual void update(size_t i, const Ns& dt) = 0; + virtual void update(size_t& i, const Ns& dt) = 0; void rotate(size_t i, rotation r); bool can_rotate(global_coords coord, rotation new_r, rotation old_r, Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size); bool can_move_to(Vector2i delta, global_coords coord, Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_aize); diff --git a/src/scenery.cpp b/src/scenery.cpp index 701dde1f..fb3010f1 100644 --- a/src/scenery.cpp +++ b/src/scenery.cpp @@ -50,7 +50,7 @@ scenery_proto::operator bool() const { return atlas != nullptr; } bool generic_scenery_proto::operator==(const generic_scenery_proto& p) const = default; enum scenery_type generic_scenery_proto::scenery_type() const { return scenery_type::generic; } -void generic_scenery::update(scenery&, size_t, Ns) {} +void generic_scenery::update(scenery&, size_t&, Ns) {} Vector2 generic_scenery::ordinal_offset(const scenery&, Vector2b offset) const { return Vector2(offset); } bool generic_scenery::can_activate(const scenery&, size_t) const { return interactive; } bool generic_scenery::activate(floormat::scenery&, size_t) { return false; } @@ -80,7 +80,7 @@ door_scenery::door_scenery(object_id, class chunk&, const door_scenery_proto& p) closing{p.closing}, active{p.active}, interactive{p.interactive} {} -void door_scenery::update(scenery& s, size_t, Ns dt) +void door_scenery::update(scenery& s, size_t&, Ns dt) { if (!s.atlas || !active) return; @@ -146,7 +146,7 @@ bool scenery::can_activate(size_t i) const ); } -void scenery::update(size_t i, const Ns& dt) +void scenery::update(size_t& i, const Ns& dt) { return std::visit( [&]<typename T>(T& sc) { sc.update(*this, i, dt); }, diff --git a/src/scenery.hpp b/src/scenery.hpp index cb952320..cc728a4b 100644 --- a/src/scenery.hpp +++ b/src/scenery.hpp @@ -63,7 +63,7 @@ struct generic_scenery unsigned char active : 1 = false; unsigned char interactive : 1 = false; - void update(scenery& sc, size_t i, Ns dt); + void update(scenery& sc, size_t& i, Ns dt); Vector2 ordinal_offset(const scenery& sc, Vector2b offset) const; bool can_activate(const scenery& sc, size_t i) const; bool activate(scenery& sc, size_t i); @@ -80,7 +80,7 @@ struct door_scenery unsigned char active : 1 = false; unsigned char interactive : 1 = false; - void update(scenery& sc, size_t i, Ns dt); + void update(scenery& sc, size_t& i, Ns dt); Vector2 ordinal_offset(const scenery& sc, Vector2b offset) const; bool can_activate(const scenery& sc, size_t i) const; bool activate(scenery& sc, size_t i); @@ -97,7 +97,7 @@ struct scenery final : object { scenery_variants subtype; - void update(size_t i, const Ns& dt) override; + void update(size_t& i, const Ns& dt) override; Vector2 ordinal_offset(Vector2b offset) const override; float depth_offset() const override; bool can_activate(size_t i) const override; diff --git a/test/serializer.cpp b/test/serializer.cpp index 5179342c..86105d3b 100644 --- a/test/serializer.cpp +++ b/test/serializer.cpp @@ -51,7 +51,6 @@ chunk& test_app::make_test_chunk(world& w, chunk_coords_ ch) { auto& e = *w.make_object<scenery>(w.make_id(), {ch, {K+3, K+1}}, door); - const auto index = e.index(); const auto end = e.atlas->info().nframes-1; constexpr auto dt = Second / 60; fm_assert(e.frame == end); @@ -59,10 +58,10 @@ chunk& test_app::make_test_chunk(world& w, chunk_coords_ ch) fm_assert(!x.active); e.activate(e.index()); fm_assert(x.active); - e.update(index, dt); + { auto index = e.index(); e.update(index, dt); } fm_assert(e.frame != end); for (int i = 0; i < 60*3; i++) - e.update(index, dt); + { auto index = e.index(); e.update(index, dt); } fm_assert(e.frame == 0); fm_assert(!x.active); } |