summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Entities/Player.cpp56
-rw-r--r--src/Entities/Player.hpp14
2 files changed, 59 insertions, 11 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index da96d56..01e3588 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -9,14 +9,17 @@ void Player::update(const Time& time, GFX::Window& window, GFX::Camera& camera,
auto const input_direction = directional_input(window);
auto destination = movement(window, time, input_direction);
- auto const [position, blocked_axes] = process_collisions(world, m_transform.position(), destination);
- destination = position;
- m_on_ground = blocked_axes.y().negative;
+ if (can_collide()) {
+ auto const [position, blocked_axes] = process_collisions(world, m_transform.position(), destination);
- for (UInt axis = 0; axis < 3; axis++) {
- if (blocked_axes[axis].positive) m_velocity[axis] = std::max(m_velocity[axis], 0.0);
- if (blocked_axes[axis].negative) m_velocity[axis] = std::min(m_velocity[axis], 0.0);
+ destination = position;
+ m_on_ground = blocked_axes.y().negative;
+
+ for (UInt axis = 0; axis < 3; axis++) {
+ if (blocked_axes[axis].positive) m_velocity[axis] = std::max(m_velocity[axis], 0.0);
+ if (blocked_axes[axis].negative) m_velocity[axis] = std::min(m_velocity[axis], 0.0);
+ }
}
move_to(destination);
@@ -48,16 +51,24 @@ AABB Player::bounds() const {
return bounding_box_for_position(m_transform.position());
}
+Bool Player::can_collide() const {
+ // Collisions are always on, except when in noclip mode.
+ return m_movement != MovementMode::NoClip;
+}
+
Position::World Player::movement(GFX::Window& window, const Time& time, Vec3 input_direction) {
- m_velocity = m_flying
- ? flying_velocity(window, time, input_direction)
- : walking_velocity(window, time, input_direction);
+ switch (m_movement) {
+ case MovementMode::Walking: m_velocity = walking_velocity(window, time, input_direction); break;
+ case MovementMode::Flying: m_velocity = flying_velocity(window, time, input_direction); break;
+ case MovementMode::NoClip: m_velocity = noclip_velocity(window, time, input_direction); break;
+ }
return m_transform.position() + m_velocity;
}
Vec3 Player::walking_velocity(GFX::Window& window, const Time& time, Vec3 input_direction) {
constexpr auto base_move_speed = 8.0;
+ constexpr auto initial_jump_velocity = 0.16;
constexpr auto gravity = 0.6;
auto walking_direction = m_transform.right() * input_direction.x() + m_transform.forward() * input_direction.z();
@@ -69,7 +80,7 @@ Vec3 Player::walking_velocity(GFX::Window& window, const Time& time, Vec3 input_
auto vertical_velocity = 0.0;
if (m_on_ground) {
if (window.key(GLFW_KEY_SPACE, GLFW_PRESS)) {
- vertical_velocity = 0.16;
+ vertical_velocity = initial_jump_velocity;
m_on_ground = false;
}
} else {
@@ -87,6 +98,23 @@ Vec3 Player::walking_velocity(GFX::Window& window, const Time& time, Vec3 input_
Vec3 Player::flying_velocity(GFX::Window& window, const Time& time, Vec3 input_direction) {
constexpr auto base_move_speed = 10.0;
+ auto flying_direction = m_transform.right() * input_direction.x() + m_transform.forward() * input_direction.z();
+ flying_direction.y() = 0;
+ if (!flying_direction.is_zero()) flying_direction = flying_direction.normalize();
+
+ auto const flying_velocity = flying_direction * base_move_speed * time.delta();
+ auto vertical_velocity = input_direction.y() * base_move_speed * time.delta();
+
+ return {
+ flying_velocity.x(),
+ vertical_velocity,
+ flying_velocity.z(),
+ };
+}
+
+Vec3 Player::noclip_velocity(GFX::Window& window, const Time& time, Vec3 input_direction) {
+ constexpr auto base_move_speed = 10.0;
+
Real const boost = TO(Real, window.key(GLFW_KEY_LEFT_CONTROL, GLFW_PRESS)) * 75.0;
auto const [x, y, z] = input_direction.elements;
@@ -98,6 +126,7 @@ Vec3 Player::flying_velocity(GFX::Window& window, const Time& time, Vec3 input_d
void Player::actions(GFX::Window& window, World::World& world) {
auto constexpr max_block_reach = 4.0;
+ // Breaking and placing blocks.
auto left_click = window.mouse(GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS);
auto right_click = window.mouse(GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS);
if (left_click || right_click) {
@@ -122,6 +151,13 @@ void Player::actions(GFX::Window& window, World::World& world) {
}
}
}
+
+ // Toggle movement modes.
+ // TODO: Need an input system for this, can't get an event only at
+ // the moment the key is pressed, so can't toggle between modes on single press.
+ if (window.key(GLFW_KEY_1, GLFW_PRESS)) m_movement = MovementMode::Walking;
+ else if (window.key(GLFW_KEY_2, GLFW_PRESS)) m_movement = MovementMode::Flying;
+ else if (window.key(GLFW_KEY_3, GLFW_PRESS)) m_movement = MovementMode::NoClip;
}
#define STUCK_THRESHOLD 100
diff --git a/src/Entities/Player.hpp b/src/Entities/Player.hpp
index f6c1f9a..c8a1c1f 100644
--- a/src/Entities/Player.hpp
+++ b/src/Entities/Player.hpp
@@ -29,6 +29,8 @@ private:
Bool positive, negative;
};
+ Bool can_collide() const;
+
struct ProcessCollisionsResult {
Position::World position;
Vector<3, BlockedAxis> blocked_axes;
@@ -39,6 +41,7 @@ private:
Position::World movement(GFX::Window& window, const Time& time, Vec3 input_direction);
Vec3 walking_velocity(GFX::Window& window, const Time& time, Vec3 input_direction);
Vec3 flying_velocity(GFX::Window& window, const Time& time, Vec3 input_direction);
+ Vec3 noclip_velocity(GFX::Window& window, const Time& time, Vec3 input_direction);
void actions(GFX::Window& window, World::World& world);
@@ -53,8 +56,17 @@ private:
// Returns position of the center of the bottom face of `box`.
static Position::World position_for_bounding_box(AABB box);
+ enum class MovementMode {
+ // Gravity, collision, and normal movement
+ Walking,
+ // Collisions, but no gravity, and normal movement
+ Flying,
+ // No collisions, no gravity, movement in the facing direction
+ NoClip,
+ };
+
+ MovementMode m_movement = MovementMode::Walking;
Bool m_on_ground = false;
- Bool m_flying = false;
Vec3 m_velocity{};
Transform m_transform;