summaryrefslogtreecommitdiff
path: root/src/Entities
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2023-12-07 02:14:47 +0100
committerMel <einebeere@gmail.com>2023-12-07 02:14:47 +0100
commitefd17623627607a26f33dac8f7ef1a1ddc931907 (patch)
tree76cf0389ae927bfc697c830155d926843178030e /src/Entities
parent581f50e0bd45a19282d7958975997d376512b195 (diff)
downloadmeowcraft-efd17623627607a26f33dac8f7ef1a1ddc931907.tar.zst
meowcraft-efd17623627607a26f33dac8f7ef1a1ddc931907.zip
Gather all possibly colliding blocks in the player move domain for collision detection
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/Player.cpp43
-rw-r--r--src/Entities/Player.hpp2
2 files changed, 28 insertions, 17 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 5d41ad0..fb88222 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -12,17 +12,15 @@ void Player::update(const Time& time, GFX::Window& window, GFX::Camera& camera,
Real z = key(GLFW_KEY_S) - key(GLFW_KEY_W);
Real boost = key(GLFW_KEY_LEFT_CONTROL) * 75.0f;
- auto move_speed = (20.0f + boost) * time.delta();
+ auto move_speed = (10.0f + boost) * time.delta();
auto rotation_speed = 0.1f;
auto direction = m_transform.right() * x + Vec3(0, y, 0) + m_transform.forward() * z;
auto destination = m_transform.position() + direction * move_speed;
- auto collisions = colliding_terrain(destination, world);
- for (auto collision : collisions) {
- auto original = destination;
+ auto collision_domain = terrain_collision_domain(m_transform.position(), destination, world);
+ for (auto collision : collision_domain) {
destination = collision_reposition(m_transform.position(), destination, collision);
- if (!original.mostly_equal(destination)) break;
}
move_to(destination);
@@ -60,21 +58,34 @@ void Player::update_camera_position(GFX::Camera& camera) {
camera.set_angles(m_transform.rotation());
}
-FlexArray<AABB, Player::MaxCollidingTerrain> Player::colliding_terrain(
- Position::World new_position,
+std::vector<AABB> Player::terrain_collision_domain(
+ Position::World from, Position::World to,
World::World& world
) {
- FlexArray<AABB, MaxCollidingTerrain> colliding_blocks;
+ auto domain_box = bounding_box_for_position(from).unite(bounding_box_for_position(to));
+ std::vector<AABB> colliding_blocks;
- auto corners = bounding_box_for_position(new_position).corners();
- for (auto corner : corners) {
- auto block_position = Position::World(corner).round_to_block();
- if (block_position.y() < 0 || block_position.y() >= World::Chunk::Height) continue;
+ // TODO: Unbind from chunks and loop through all the
+ // blocks individually inside domain.
+ // This will be more efficient and actually accurate,
+ // since right now if you're fast enough you can clip
+ // through whole chunks.
+ auto add_colliding = [&](Position::World chunk_pos, Position::BlockLocal pos, World::Chunk::BlockData& b) {
+ if (b.type == World::BlockType::Air) return;
+ auto block_bounds = World::Chunk::block_bounds(pos).offset(chunk_pos);
+ if (domain_box.collides(block_bounds)) colliding_blocks.push_back(block_bounds);
+ };
+
+ auto chunk_from = world.chunks().find(to);
+ if (chunk_from.chunk.has_value()) {
+ auto position = chunk_from.chunk.value().position();
+ chunk_from.chunk->for_each([&](auto p, auto b) { add_colliding(position, p, b); });
+ }
- auto block = world.block_at(block_position);
- if (!block.empty()) {
- colliding_blocks.push_back(World::Chunk::block_bounds(block_position.to_local()));
- }
+ auto chunk_to = world.chunks().find(to);
+ if (chunk_to.chunk.has_value()) {
+ auto position = chunk_to.chunk.value().position();
+ chunk_to.chunk->for_each([&](auto p, auto b) { add_colliding(position, p, b); });
}
return colliding_blocks;
diff --git a/src/Entities/Player.hpp b/src/Entities/Player.hpp
index 7238e80..3ae10ff 100644
--- a/src/Entities/Player.hpp
+++ b/src/Entities/Player.hpp
@@ -29,7 +29,7 @@ private:
void update_camera_position(GFX::Camera& camera);
static constexpr UInt MaxCollidingTerrain = 34;
- static FlexArray<AABB, MaxCollidingTerrain> colliding_terrain(Position::World new_position, World::World& world);
+ static std::vector<AABB> terrain_collision_domain(Position::World from, Position::World to, World::World& world);
// Creates a bounding box where `position` is at the center of the bottom face.
static AABB bounding_box_for_position(Position::World position);