summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-03-17 23:20:46 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-03-17 23:23:12 +0100
commit90c43f035f41cf901832794f0b4e00c2b5569723 (patch)
tree4cb7bc4f09509c03bbeb3cb3fcf6b115fca910f0 /src
parentc17cef93bd6bbc1b071dcd82df0dbc9420e52ef4 (diff)
dddd
Diffstat (limited to 'src')
-rw-r--r--src/character.cpp14
-rw-r--r--src/character.hpp1
-rw-r--r--src/chunk-collision.cpp13
-rw-r--r--src/chunk.hpp14
-rw-r--r--src/chunk.inl37
-rw-r--r--src/entity.cpp44
-rw-r--r--src/entity.hpp15
-rw-r--r--src/scenery.cpp20
-rw-r--r--src/scenery.hpp1
9 files changed, 59 insertions, 100 deletions
diff --git a/src/character.cpp b/src/character.cpp
index ed9ce4fa..67b6ca72 100644
--- a/src/character.cpp
+++ b/src/character.cpp
@@ -52,12 +52,13 @@ constexpr auto arrows_to_dir(bool L, bool R, bool U, bool D)
} // namespace
character::character(std::uint64_t id, struct chunk& c, entity_type type, const character_proto& proto) :
- entity{id, c, type},
+ entity{id, c, type, proto},
name{proto.name},
playable{proto.playable}
{
- atlas = loader.anim_atlas("npc-walk", loader.ANIM_PATH);
- bbox_size = Vector2ub(iTILE_SIZE2/2);
+ if (!atlas)
+ atlas = loader.anim_atlas("npc-walk", loader.ANIM_PATH);
+ entity::set_bbox_(offset, bbox_offset, Vector2ub(iTILE_SIZE2/2), pass);
}
character::~character() = default;
@@ -88,7 +89,7 @@ void character::set_keys(bool L, bool R, bool U, bool D)
bool character::update(std::size_t i, float dt)
{
- auto [lr, ud, rot] = arrows_to_dir(b_L, b_R, b_U, b_D);
+ auto [lr, ud, new_r] = arrows_to_dir(b_L, b_R, b_U, b_D);
if (!lr & !ud)
{
@@ -102,18 +103,17 @@ bool character::update(std::size_t i, float dt)
return false;
const auto vec = move_vec(lr, ud);
- r = rot;
c->ensure_passability();
for (int k = 0; k < nframes; k++)
{
constexpr auto frac = Vector2(32767);
- constexpr auto inv_frac = Vector2(1.f/32767);
+ constexpr auto inv_frac = 1.f / frac;
auto offset_ = vec + Vector2(offset_frac) * inv_frac;
offset_frac = Vector2s(Vector2(std::fmod(offset_[0], 1.f), std::fmod(offset_[1], 1.f)) * frac);
auto off_i = Vector2i(offset_);
if (can_move_to(off_i))
- i = move(i, off_i);
+ i = move(i, off_i, new_r);
++frame %= atlas->info().nframes;
}
//Debug{} << "pos" << Vector2i(pos.local());
diff --git a/src/character.hpp b/src/character.hpp
index 9481c4ac..af48b19a 100644
--- a/src/character.hpp
+++ b/src/character.hpp
@@ -29,7 +29,6 @@ struct character final : entity
void set_keys(bool L, bool R, bool U, bool D);
bool update(std::size_t i, float dt) override;
- void update_bbox(Vector2b bbox_offset, Vector2ub bbox_size) override;
String name;
Vector2s offset_frac;
diff --git a/src/chunk-collision.cpp b/src/chunk-collision.cpp
index c64d9a5b..c228c514 100644
--- a/src/chunk-collision.cpp
+++ b/src/chunk-collision.cpp
@@ -96,9 +96,9 @@ void chunk::ensure_passability() noexcept
}
}
-bool chunk::_bbox_for_scenery(const entity& s, local_coords local, Vector2b offset, bbox& value) noexcept
+bool chunk::_bbox_for_scenery(const entity& s, local_coords local, Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size, bbox& value) noexcept
{
- auto [start, end] = scenery_tile(local, offset, s.bbox_offset, s.bbox_size);
+ auto [start, end] = scenery_tile(local, offset, bbox_offset, bbox_size);
auto id = make_id(collision_type::scenery, s.pass, s.id);
value = { .id = id, .start = start, .end = end };
return s.atlas && s.pass != pass_mode::pass;
@@ -106,27 +106,26 @@ bool chunk::_bbox_for_scenery(const entity& s, local_coords local, Vector2b offs
bool chunk::_bbox_for_scenery(const entity& s, bbox& value) noexcept
{
- return _bbox_for_scenery(s, s.coord.local(), s.offset, value);
+ return _bbox_for_scenery(s, s.coord.local(), s.offset, s.bbox_offset, s.bbox_size, value);
}
void chunk::_remove_bbox(const bbox& x)
{
- if (_scenery_modified)
- return;
auto start = Vector2(x.start), end = Vector2(x.end);
_rtree.Remove(start.data(), end.data(), x.id);
}
void chunk::_add_bbox(const bbox& x)
{
- if (_scenery_modified)
- return;
auto start = Vector2(x.start), end = Vector2(x.end);
_rtree.Insert(start.data(), end.data(), x.id);
}
void chunk::_replace_bbox(const bbox& x0, const bbox& x1, bool b0, bool b1)
{
+ if (_pass_modified)
+ return;
+
unsigned i = (unsigned)b1 << 1 | (unsigned)(b0 ? 1 : 0) << 0;
CORRADE_ASSUME(i < 4u);
diff --git a/src/chunk.hpp b/src/chunk.hpp
index 0cd7bcfc..e825ce33 100644
--- a/src/chunk.hpp
+++ b/src/chunk.hpp
@@ -87,26 +87,18 @@ struct chunk final
float depth = -1;
};
+ using RTree = ::RTree<std::uint64_t, float, 2, float>;
+
ground_mesh_tuple ensure_ground_mesh() noexcept;
tile_atlas* ground_atlas_at(std::size_t i) const noexcept;
-
wall_mesh_tuple ensure_wall_mesh() noexcept;
tile_atlas* wall_atlas_at(std::size_t i) const noexcept;
-
scenery_mesh_tuple ensure_scenery_mesh() noexcept;
void ensure_passability() noexcept;
-
- using RTree = ::RTree<std::uint64_t, float, 2, float>;
-
RTree* rtree() noexcept;
-
struct world& world() noexcept { return *_world; }
- template<typename F>
- requires requires(F fun) { fun(); }
- void with_scenery_update(entity& e, F&& fun);
-
[[nodiscard]] bool can_place_entity(const entity_proto& proto, local_coords pos);
void add_entity(const std::shared_ptr<entity>& e);
@@ -147,7 +139,7 @@ private:
bool operator==(const bbox& other) const noexcept;
};
static bool _bbox_for_scenery(const entity& s, bbox& value) noexcept;
- static bool _bbox_for_scenery(const entity& s, local_coords local, Vector2b offset, bbox& value) noexcept;
+ static bool _bbox_for_scenery(const entity& s, local_coords local, Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size, bbox& value) noexcept;
void _remove_bbox(const bbox& x);
void _add_bbox(const bbox& x);
void _replace_bbox(const bbox& x0, const bbox& x, bool b0, bool b);
diff --git a/src/chunk.inl b/src/chunk.inl
deleted file mode 100644
index 132657ab..00000000
--- a/src/chunk.inl
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-#include "chunk.hpp"
-#include "scenery.hpp"
-
-namespace floormat {
-
-template<typename F>
-requires requires(F fun) { fun(); }
-void chunk::with_scenery_update(entity& s, F&& fun)
-{
- static_assert(std::is_convertible_v<decltype(fun()), bool> || std::is_same_v<void, decltype(fun())>);
-
- // todo handle coord & offset fields
-
- auto ch = s.coord.chunk();
- entity_proto s0(s);
- bbox bb0; bool b0 = _bbox_for_scenery(s, bb0);
-
- bool modified = true;
- if constexpr(!std::is_same_v<void, std::decay_t<decltype(fun())>>)
- modified = fun();
- else
- fun();
- if (!modified)
- return;
-
- if (s.coord.chunk() != ch) // todo
- return;
-
- if (bbox bb; !is_passability_modified())
- if (bool b = _bbox_for_scenery(s, bb); b != b0 || bb != bb0)
- _replace_bbox(bb0, bb, b0, b);
- if (!is_scenery_modified() && !s.is_dynamic() && entity_proto(s) != s0)
- mark_scenery_modified(false);
-}
-
-} // namespace floormat
diff --git a/src/entity.cpp b/src/entity.cpp
index c9c1a4ab..390cf18c 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -1,7 +1,6 @@
#include "entity.hpp"
#include "world.hpp"
#include "rotation.inl"
-#include "chunk.inl"
#include "anim-atlas.hpp"
#include "RTree.hpp"
#include <algorithm>
@@ -14,11 +13,6 @@ entity_proto::~entity_proto() noexcept = default;
entity_proto::entity_proto() = default;
entity_proto::entity_proto(const entity_proto&) = default;
-entity::entity(std::uint64_t id, struct chunk& c, entity_type type) noexcept :
- id{id}, c{&c}, type{type}
-{
-}
-
entity::entity(std::uint64_t id, struct chunk& c, entity_type type, const entity_proto& proto) noexcept :
id{id}, c{&c}, atlas{proto.atlas},
offset{proto.offset}, bbox_offset{proto.bbox_offset},
@@ -26,6 +20,8 @@ entity::entity(std::uint64_t id, struct chunk& c, entity_type type, const entity
frame{proto.frame}, type{type}, r{proto.r}, pass{proto.pass}
{
fm_assert(type == proto.type);
+ fm_assert(atlas->check_rotation(r));
+ fm_assert(frame < atlas->info().nframes);
}
entity::~entity() noexcept
@@ -90,12 +86,9 @@ std::size_t entity::index() const
void entity::rotate(std::size_t, rotation new_r)
{
- auto& w = *c->_world;
- w[coord.chunk()].with_scenery_update(*this, [&]() {
- bbox_offset = rotate_point(bbox_offset, r, new_r);
- bbox_size = rotate_size(bbox_size, r, new_r);
- r = new_r;
- });
+ fm_assert(atlas->check_rotation(new_r));
+ set_bbox(offset, rotate_point(bbox_offset, r, new_r), rotate_size(bbox_size, r, new_r), pass);
+ const_cast<rotation&>(r) = new_r;
}
template <typename T> constexpr T sgn(T val) { return T(T(0) < val) - T(val < T(0)); }
@@ -141,7 +134,7 @@ bool entity::can_move_to(Vector2i delta)
return ret;
}
-std::size_t entity::move(std::size_t i, Vector2i delta)
+std::size_t entity::move(std::size_t i, Vector2i delta, rotation new_r)
{
auto& es = c->_entities;
fm_debug_assert(i < es.size());
@@ -159,8 +152,10 @@ std::size_t entity::move(std::size_t i, Vector2i delta)
c->mark_scenery_modified(false);
chunk::bbox bb0, bb1;
+ const auto bb_offset = rotate_point(bbox_offset, r, new_r);
+ const auto bb_size = rotate_size(bbox_size, r, new_r);
bool b0 = c->_bbox_for_scenery(e, bb0),
- b1 = c->_bbox_for_scenery(e, coord_.local(), offset_, bb1);
+ b1 = c->_bbox_for_scenery(e, coord_.local(), offset_, bb_offset, bb_size, bb1);
const auto ord = e.ordinal(coord_.local(), offset_, e.type);
if (coord_.chunk() == coord.chunk())
@@ -168,7 +163,7 @@ std::size_t entity::move(std::size_t i, Vector2i delta)
c->_replace_bbox(bb0, bb1, b0, b1);
auto it_ = std::lower_bound(es.cbegin(), es.cend(), e_, [=](const auto& a, const auto&) { return a->ordinal() < ord; });
e_->coord = coord_;
- e_->offset = offset_;
+ set_bbox_(offset_, bb_offset, bb_size, pass);
auto pos1 = std::distance(es.cbegin(), it_);
if ((std::size_t)pos1 > i)
pos1--;
@@ -193,13 +188,30 @@ std::size_t entity::move(std::size_t i, Vector2i delta)
auto it = std::lower_bound(es.cbegin(), es.cend(), e_, [=](const auto& a, const auto&) { return a->ordinal() < ord; });
auto ret = (std::size_t)std::distance(es.cbegin(), it);
e_->coord = coord_;
- e_->offset = offset_;
+ set_bbox_(offset_, bb_offset, bb_size, pass);
const_cast<struct chunk*&>(e_->c) = &c2;
es.insert(it, std::move(e_));
return ret;
}
}
+void entity::set_bbox_(Vector2b offset_, Vector2b bbox_offset_, Vector2ub bbox_size_, pass_mode pass_)
+{
+ const_cast<Vector2b&>(offset) = offset_;
+ const_cast<Vector2b&>(bbox_offset) = bbox_offset_;
+ const_cast<Vector2ub&>(bbox_size) = bbox_size_;
+ const_cast<pass_mode&>(pass) = pass_;
+}
+
+void entity::set_bbox(Vector2b offset_, Vector2b bbox_offset_, Vector2ub bbox_size_, pass_mode pass)
+{
+ chunk::bbox bb0, bb;
+ const bool b0 = c->_bbox_for_scenery(*this, bb0);
+ set_bbox_(offset_, bbox_offset_, bbox_size_, pass);
+ const bool b = c->_bbox_for_scenery(*this, bb);
+ c->_replace_bbox(bb0, bb, b0, b);
+}
+
entity::operator entity_proto() const
{
entity_proto x;
diff --git a/src/entity.hpp b/src/entity.hpp
index 893c30e9..c6edcf90 100644
--- a/src/entity.hpp
+++ b/src/entity.hpp
@@ -41,12 +41,12 @@ struct entity
struct chunk* const c;
std::shared_ptr<anim_atlas> atlas;
global_coords coord;
- Vector2b offset, bbox_offset;
- Vector2ub bbox_size;
+ const Vector2b offset, bbox_offset;
+ const Vector2ub bbox_size;
std::uint16_t delta = 0, frame = 0;
const entity_type type;
- rotation r : rotation_BITS = rotation::N;
- pass_mode pass : pass_mode_BITS = pass_mode::see_through;
+ const rotation r = rotation::N;
+ const pass_mode pass = pass_mode::see_through;
virtual ~entity() noexcept;
@@ -65,15 +65,16 @@ struct entity
static Pair<global_coords, Vector2b> normalize_coords(global_coords coord, Vector2b cur_offset, Vector2i delta);
[[nodiscard]] virtual bool can_move_to(Vector2i delta);
- std::size_t move(std::size_t i, Vector2i delta);
- virtual void update_bbox(Vector2b bbox_offset, Vector2ub bbox_size) = 0;
+ std::size_t move(std::size_t i, Vector2i delta, rotation new_r);
+ virtual void set_bbox(Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size, pass_mode pass);
bool is_dynamic() const;
friend struct world;
protected:
- entity(std::uint64_t id, struct chunk& c, entity_type type) noexcept;
entity(std::uint64_t id, struct chunk& c, entity_type type, const entity_proto& proto) noexcept;
+
+ void set_bbox_(Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size, pass_mode pass);
};
} // namespace floormat
diff --git a/src/scenery.cpp b/src/scenery.cpp
index be0249d2..694090a2 100644
--- a/src/scenery.cpp
+++ b/src/scenery.cpp
@@ -50,12 +50,14 @@ bool scenery::update(std::size_t, float dt)
const std::int8_t dir = s.closing ? 1 : -1;
const int fr = s.frame + dir*n;
s.active = fr > 0 && fr < nframes-1;
+ pass_mode p;
if (fr <= 0)
- s.pass = pass_mode::pass;
+ p = pass_mode::pass;
else if (fr >= nframes-1)
- s.pass = pass_mode::blocked;
+ p = pass_mode::blocked;
else
- s.pass = pass_mode::see_through;
+ p = pass_mode::see_through;
+ set_bbox(offset, bbox_offset, bbox_size, p);
s.frame = (std::uint16_t)std::clamp(fr, 0, nframes-1);
if (!s.active)
s.delta = s.closing = 0;
@@ -117,19 +119,11 @@ scenery::operator scenery_proto() const
return ret;
}
-scenery::scenery(std::uint64_t id, struct chunk& c, entity_type type, const scenery_proto& proto) :
- entity{id, c, type}, sc_type{proto.sc_type}, active{proto.active},
+scenery::scenery(std::uint64_t id, struct chunk& c, entity_type type_, const scenery_proto& proto) :
+ entity{id, c, type_, proto}, sc_type{proto.sc_type}, active{proto.active},
closing{proto.closing}, interactive{proto.interactive}
{
fm_assert(type == proto.type);
- atlas = proto.atlas;
- offset = proto.offset;
- bbox_offset = proto.bbox_offset;
- bbox_size = proto.bbox_size;
- delta = proto.delta;
- frame = proto.frame;
- r = proto.r;
- pass = proto.pass;
}
} // namespace floormat
diff --git a/src/scenery.hpp b/src/scenery.hpp
index 55a13bd0..3fe5fa35 100644
--- a/src/scenery.hpp
+++ b/src/scenery.hpp
@@ -45,7 +45,6 @@ struct scenery final : entity
bool can_activate(std::size_t i) const override;
bool activate(std::size_t i) override;
bool update(std::size_t i, float dt) override;
- void update_bbox(Vector2b bbox_offset, Vector2ub bbox_size) override;
explicit operator scenery_proto() const;
private: