diff options
| author | Mel <einebeere@gmail.com> | 2023-08-06 04:27:07 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2023-08-06 04:27:07 +0200 |
| commit | 5a1b126f1f6d55226c2b5068d0c17c428fd29ba8 (patch) | |
| tree | 3acc0240cd8dedd0764eeae6df04e134b04584c8 /src/Entities | |
| parent | e6f5f9e03f673db796f1babb308609ca2576db2f (diff) | |
| download | meowcraft-5a1b126f1f6d55226c2b5068d0c17c428fd29ba8.tar.zst meowcraft-5a1b126f1f6d55226c2b5068d0c17c428fd29ba8.zip | |
Create separate Player entity and add bad collision system
Diffstat (limited to 'src/Entities')
| -rw-r--r-- | src/Entities/Player.cpp | 80 | ||||
| -rw-r--r-- | src/Entities/Player.hpp | 40 |
2 files changed, 120 insertions, 0 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp new file mode 100644 index 0000000..175b59e --- /dev/null +++ b/src/Entities/Player.cpp @@ -0,0 +1,80 @@ +#include "Player.hpp" + +namespace MC::Entities { + +void Player::update(const Time& time, GFX::Window& window, GFX::Camera& camera, World::World& world) { + auto r = window.mouse_delta(); + + auto key = [&](Int k) -> Real { return window.key(k, GLFW_PRESS); }; + + Real x = key(GLFW_KEY_D) - key(GLFW_KEY_A); + Real y = key(GLFW_KEY_SPACE) - key(GLFW_KEY_LEFT_SHIFT); + 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 rotation_speed = 0.1f; + + auto direction = m_transform.right() * x + Vec3(0, y, 0) + m_transform.forward() * z; + auto position = m_transform.position() + direction * move_speed; + + if (!collides_with_terrain(position, world)) move_to(position); + rotate({r.y() * rotation_speed, r.x() * rotation_speed, 0.0f}); + + update_camera_position(camera); +} + +void Player::move(Position::WorldOffset by) { + m_transform.position() += by; +} + +void Player::rotate(Rotation by) { + m_transform.rotation() += by; + m_transform.rotation().pitch() = std::clamp(m_transform.rotation().pitch(), -89.0, 89.0); +} + +void Player::move_to(Position::World to) { + m_transform.position() = to; +} + +void Player::rotate_to(Rotation to) { + m_transform.rotation() = to; +} + +AABB Player::bounds() const { + return bounding_box_for_position(m_transform.position()); +} + +void Player::update_camera_position(GFX::Camera& camera) { + auto camera_position = m_transform.position(); + camera_position.y() += 1.5; + + camera.set_position(camera_position); + camera.set_angles(m_transform.rotation()); +} + +Bool Player::collides_with_terrain(Position::World new_position, World::World& world) { + 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 block = world.block_at(block_position); + if (!block.empty()) return true; + } + + return false; +} + +AABB Player::bounding_box_for_position(Position::World position) { + Vec3 box_start = { + position.x() - s_bounds.max.x() / 2, + position.y(), + position.z() - s_bounds.max.z() / 2, + }; + + return s_bounds.offset(box_start); +} + +} diff --git a/src/Entities/Player.hpp b/src/Entities/Player.hpp new file mode 100644 index 0000000..86d8c90 --- /dev/null +++ b/src/Entities/Player.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "../Time.hpp" +#include "../Transform.hpp" +#include "../GFX/Camera.hpp" +#include "../World/World.hpp" +#include "../GFX/Window.hpp" +#include "../Math/AABB.hpp" +#include "../Math/Rotation.hpp" +#include "../World/Position.hpp" + +namespace MC::Entities { + +class Player { +public: + explicit Player(Position::World position) : m_transform(position) {} + + void update(const Time& time, GFX::Window& window, GFX::Camera& camera, World::World& world); + + void move(Position::WorldOffset by); + void move_to(Position::World to); + + void rotate(Rotation by); + void rotate_to(Rotation to); + + AABB bounds() const; +private: + void update_camera_position(GFX::Camera& camera); + + static Bool collides_with_terrain(Position::World new_position, 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); + + Transform m_transform; + + static inline AABB s_bounds{{0.35, 1.8, 0.35}}; +}; + +} |
