From e2e52b7069d2eeed18e935616d72af5774b14a97 Mon Sep 17 00:00:00 2001 From: Mel Date: Sun, 4 Feb 2024 21:20:52 +0100 Subject: Toggle between movement modes (Walking, Flying, NoClip) --- src/Entities/Player.cpp | 56 ++++++++++++++++++++++++++++++++++++++++--------- src/Entities/Player.hpp | 14 ++++++++++++- 2 files changed, 59 insertions(+), 11 deletions(-) (limited to 'src') 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; -- cgit 1.4.1