summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2024-02-04 21:20:52 +0100
committerMel <einebeere@gmail.com>2024-02-04 21:20:52 +0100
commite2e52b7069d2eeed18e935616d72af5774b14a97 (patch)
tree77fe19692cbc7d00dcebc51752c032867a33a2cd /src
parent44b87e9751f054ed5406042d69bbc130331d660e (diff)
downloadmeowcraft-e2e52b7069d2eeed18e935616d72af5774b14a97.tar.zst
meowcraft-e2e52b7069d2eeed18e935616d72af5774b14a97.zip
Toggle between movement modes (Walking, Flying, NoClip)
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;