diff --git a/src/Player.h b/src/Player.h new file mode 100644 index 0000000..69e8d95 --- /dev/null +++ b/src/Player.h @@ -0,0 +1,88 @@ +#ifndef PLAYER_H +#define PLAYER_H + +#include +#include "World.h" + +const float PLAYER_HEIGHT = 1.8f; +const float GRAVITY = 18.6f; // Should be in m/s^2 but it doesn't really work out with 9.8 so we double it + +class Player +{ + public: + glm::vec3 position; + + // Movement velocities + glm::vec3 horizontal_velocity; + glm::vec3 forward_velocity; + glm::vec3 vertical_velocity; + + bool grounded; + float speed; + + Player(float speed, glm::vec3 pos) + { + this->speed = speed; + this->position = pos; + + this->horizontal_velocity = glm::vec3(0.0f); + this->forward_velocity = glm::vec3(0.0f); + this->vertical_velocity = glm::vec3(0.0f); + + this->grounded = false; + } + + void move(World* world, float time) // time passed in seconds since last move + { + glm::vec3 velocity = this->forward_velocity + this->horizontal_velocity + this->vertical_velocity; + glm::vec3 position_delta = (velocity * time); + + // AABB Algorithm + glm::vec3 aabb_dims = glm::vec3(0.8f, 1.8f, 0.8f); + glm::vec3 aabb_half_dims = aabb_dims / 2.0f; + glm::vec3 aabb_center_offset = glm::vec3(0.0f, aabb_dims.y / 2.0f, 0.0f); + + bool y_axis_collided = false; + + for (int axis = 0; axis < 3; axis++) { + glm::vec3 target_position = this->position; + target_position[axis] += position_delta[axis]; + + glm::vec3 aabb_center = target_position + aabb_center_offset; + glm::vec3 adjusted_center = aabb_center + glm::vec3(0.5f, 0.5f, 0.5f); + glm::vec3 min = glm::floor(adjusted_center - aabb_half_dims); + glm::vec3 max = glm::ceil(adjusted_center + aabb_half_dims); + + bool collided = false; + for (int x = min.x; x < max.x && !collided; x++) { + for (int y = min.y; y < max.y && !collided; y++) { + for (int z = min.z; z < max.z && !collided; z++) { + glm::ivec3 calculated_position = glm::ivec3(x, y, z); + if (world->get_voxel(calculated_position) != VoxelKind::Air) { + collided = true; + } + } + } + } + + if (!collided) { + this->position[axis] = target_position[axis]; + } else if (axis == 1) { + y_axis_collided = true; + grounded = true; + this->vertical_velocity.y = 0.0f; + } + } + + if (!y_axis_collided) { + this->vertical_velocity.y -= GRAVITY * time; + grounded = false; + } + } + + glm::vec3 getEyePosition() const { + return position + glm::vec3(0.0f, PLAYER_HEIGHT, 0.0f); + } +}; + +#endif