#pragma once #include "../Time.hpp" #include "../Transform.hpp" #include "../GFX/Camera.hpp" #include "../World/World.hpp" #include "../GFX/Window.hpp" #include "../GFX/Shading/Program.hpp" #include "../Math/AABB.hpp" #include "../Math/Rotation.hpp" #include "../World/Position.hpp" namespace MC::Entities { class Player { public: explicit Player(Position::World position, Real ascept, Real fov, Real near, Real far); void update(const Time& time, GFX::Window& window, GFX::Camera& camera, World::World& world); void render(const GFX::Camera& camera); void move(Position::WorldOffset by); void move_to(Position::World to); void rotate(Rotation by); void rotate_to(Rotation to); AABB bounds() const; private: struct BlockedAxis { Bool positive, negative; }; Bool can_collide() const; struct ProcessCollisionsResult { Position::World position; Vector<3, BlockedAxis> blocked_axes; }; static ProcessCollisionsResult process_collisions(World::World& world, Position::World from, Position::World to); static std::vector terrain_collision_domain(Position::World from, Position::World to, World::World& world); 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 update_targeted_block(World::World& world); void actions(GFX::Window& window, World::World& world); Transform camera_transform() const; void update_camera_position(GFX::Camera& camera) const; static Vec3 directional_input(GFX::Window& window); static Rotation rotational_input(GFX::Window& window); // Creates a bounding box where `position` is at the center of the bottom face. static AABB bounding_box_for_position(Position::World position); // Returns position of the center of the bottom face of `box`. static Position::World position_for_bounding_box(AABB box); static GFX::Mesh create_outline_cube_mesh(); 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; struct TargetedBlock { Position::BlockWorld position; Position::BlockWorldOffset normal; }; std::optional m_targeted_block; Vec3 m_velocity{}; Transform m_transform; static inline AABB s_bounds{{0.35, 1.8, 0.35}}; // TODO: Put this into the rendering system static const Char* outline_vertex; static const Char* outline_fragment; GFX::Shading::Program m_outline_program; GFX::Mesh m_outline_mesh; GFX::Shading::Uniform m_outline_model_uniform; GFX::Shading::Uniform m_outline_view_uniform; GFX::Shading::Uniform m_outline_projection_uniform; }; }