summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Entities/Player.cpp43
-rw-r--r--src/Entities/Player.hpp2
-rw-r--r--src/Math/AABB.hpp8
-rw-r--r--src/World/Chunk.hpp12
-rw-r--r--src/World/ChunkIndex.hpp4
5 files changed, 52 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);
diff --git a/src/Math/AABB.hpp b/src/Math/AABB.hpp
index 22de760..53ce6d2 100644
--- a/src/Math/AABB.hpp
+++ b/src/Math/AABB.hpp
@@ -2,6 +2,7 @@
#include <array>
#include "Vector.hpp"
+#include "../Common/Lambda.hpp"
struct AABB {
AABB() = default;
@@ -60,6 +61,13 @@ struct AABB {
return {center() - new_size / 2, center() + new_size / 2};
}
+ AABB unite(AABB with) const {
+ return {
+ min.zip(with.min, LAMBDA(std::min, 2)),
+ max.zip(with.max, LAMBDA(std::max, 2))
+ };
+ }
+
AABB collision_response(Vector<3> v, AABB against) const;
Vector<3> min, max;
diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp
index ed3220d..9a29284 100644
--- a/src/World/Chunk.hpp
+++ b/src/World/Chunk.hpp
@@ -48,6 +48,18 @@ public:
void set_details(const Details& details) { m_details = details; }
Details& details(){ return m_details; }
+ template <typename F>
+ void for_each(F f) {
+ for (U32 x = 0; x < Width; ++x) {
+ for (U32 y = 0; y < Height; ++y) {
+ for (U32 z = 0; z < Width; ++z) {
+ Position::BlockLocal pos{x, y, z};
+ f(pos, at(x, y, z));
+ }
+ }
+ }
+ }
+
ChunkIndex index() const;
Vector<3> position() const;
diff --git a/src/World/ChunkIndex.hpp b/src/World/ChunkIndex.hpp
index 2e4fa67..bc61f3d 100644
--- a/src/World/ChunkIndex.hpp
+++ b/src/World/ChunkIndex.hpp
@@ -21,6 +21,10 @@ struct ChunkIndex {
return {x * Width + local.x(), local.y(), y * Width + local.z()};
}
+ Position::BlockWorld world_position() const {
+ return local_to_world_position({0, 0, 0});
+ }
+
static ChunkIndex from_position(Position::BlockWorld pos) {
I32 chunk_x = std::floor((Real)pos.x() / ChunkDimensions::Width);
I32 chunk_y = std::floor((Real)pos.z() / ChunkDimensions::Width);