#include "PlayerController.hpp" #include PlayerController::PlayerController(float distance, float height, float speed) : cameraDistance(distance), cameraHeight(height), moveSpeed(speed) { camera.position = {0, cameraHeight, cameraDistance}; camera.target = {0, 0, 0}; camera.up = {0, 1, 0}; camera.fovy = 45.0f; camera.projection = CAMERA_PERSPECTIVE; updateCameraPosition(); } void PlayerController::update(float deltaTime) { handleCameraRotation(); handleCameraZoom(); updateCameraPosition(); } void PlayerController::setPlayerPosition(const Vector3& position) { playerPosition = position; } Vector3 PlayerController::getMoveInput() const { Vector3 moveDir = {0, 0, 0}; // Forward/Backward movement (W/S) - relative to camera direction if (IsKeyDown(KEY_W)) { moveDir.x += sinf(cameraYaw); moveDir.z += cosf(cameraYaw); } if (IsKeyDown(KEY_S)) { moveDir.x -= sinf(cameraYaw); moveDir.z -= cosf(cameraYaw); } // Strafe left/right (Q/E) - perpendicular to camera direction (inverted) if (IsKeyDown(KEY_Q)) { moveDir.x += cosf(cameraYaw); moveDir.z -= sinf(cameraYaw); } if (IsKeyDown(KEY_E)) { moveDir.x -= cosf(cameraYaw); moveDir.z += sinf(cameraYaw); } // Also support A/D for strafing as alternative (inverted) if (IsKeyDown(KEY_A)) { moveDir.x += cosf(cameraYaw); moveDir.z -= sinf(cameraYaw); } if (IsKeyDown(KEY_D)) { moveDir.x -= cosf(cameraYaw); moveDir.z += sinf(cameraYaw); } // Normalize movement vector if it has length float length = sqrtf(moveDir.x * moveDir.x + moveDir.z * moveDir.z); if (length > 0.0f) { moveDir.x /= length; moveDir.z /= length; } return moveDir; } void PlayerController::updateCameraPosition() { // Update camera target to player position camera.target = playerPosition; // Calculate camera position based on spherical coordinates float cosYaw = cosf(cameraYaw); float sinYaw = sinf(cameraYaw); float cosPitch = cosf(cameraPitch); float sinPitch = sinf(cameraPitch); camera.position.x = playerPosition.x - sinYaw * cosPitch * cameraDistance; camera.position.y = playerPosition.y + sinPitch * cameraDistance; camera.position.z = playerPosition.z - cosYaw * cosPitch * cameraDistance; } void PlayerController::handleCameraRotation() { // Check for right mouse button if (IsMouseButtonDown(MOUSE_RIGHT_BUTTON)) { if (!isRightMouseDown) { // Just pressed - store initial mouse position isRightMouseDown = true; lastMousePos = GetMousePosition(); DisableCursor(); } // Get mouse delta Vector2 currentMousePos = GetMousePosition(); Vector2 mouseDelta = { currentMousePos.x - lastMousePos.x, currentMousePos.y - lastMousePos.y }; // Update camera angles (inverted Y-axis) const float sensitivity = 0.003f; cameraYaw -= mouseDelta.x * sensitivity; cameraPitch += mouseDelta.y * sensitivity; // Clamp pitch to prevent camera flipping cameraPitch = std::clamp(cameraPitch, -1.4f, 1.4f); // Wrap yaw if (cameraYaw > PI * 2.0f) cameraYaw -= PI * 2.0f; if (cameraYaw < 0.0f) cameraYaw += PI * 2.0f; lastMousePos = currentMousePos; } else { if (isRightMouseDown) { // Just released isRightMouseDown = false; EnableCursor(); } } } void PlayerController::handleCameraZoom() { // Handle mouse wheel zoom float wheel = GetMouseWheelMove(); if (wheel != 0) { cameraDistance -= wheel * 2.0f; // Clamp zoom distance cameraDistance = std::clamp(cameraDistance, 5.0f, 50.0f); } }