summary refs log tree commit diff
path: root/src/Entities/Player.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities/Player.cpp')
-rw-r--r--src/Entities/Player.cpp43
1 files changed, 27 insertions, 16 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;
+
+    // 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;