From efd17623627607a26f33dac8f7ef1a1ddc931907 Mon Sep 17 00:00:00 2001 From: Mel Date: Thu, 7 Dec 2023 02:14:47 +0100 Subject: Gather all possibly colliding blocks in the player move domain for collision detection --- src/Entities/Player.cpp | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'src/Entities/Player.cpp') 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 Player::colliding_terrain( - Position::World new_position, +std::vector Player::terrain_collision_domain( + Position::World from, Position::World to, World::World& world ) { - FlexArray colliding_blocks; + auto domain_box = bounding_box_for_position(from).unite(bounding_box_for_position(to)); + std::vector colliding_blocks; + + // 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 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; + 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; -- cgit 1.4.1