From b4d0ad9e95226d225d5361b1182866884aaa6366 Mon Sep 17 00:00:00 2001 From: Mitja Felicijan Date: Thu, 30 Apr 2026 19:19:27 +0200 Subject: Structural refactor --- player.c | 184 ++++++++++++++++++++++----------------------------------------- 1 file changed, 63 insertions(+), 121 deletions(-) (limited to 'player.c') diff --git a/player.c b/player.c index 01c56ca..52788f1 100644 --- a/player.c +++ b/player.c @@ -1,55 +1,24 @@ #include "all.h" #include "raymath.h" + #include static void PlayerRotate(void) { if (!game.cursor_captured) return; Vector2 mouseDelta = GetMouseDelta(); - game.yaw += -mouseDelta.x * PLAYER_MOUSE_SENSITIVITY; - game.pitch += mouseDelta.y * PLAYER_MOUSE_SENSITIVITY; + game.player.yaw += -mouseDelta.x * PLAYER_MOUSE_SENSITIVITY; + game.player.pitch += mouseDelta.y * PLAYER_MOUSE_SENSITIVITY; - // Clamp pitch to avoid gimbal lock/flipping (approx 89 degrees) - if (game.pitch > 89.0f * DEG2RAD) game.pitch = 89.0f * DEG2RAD; - if (game.pitch < -89.0f * DEG2RAD) game.pitch = -89.0f * DEG2RAD; -} - -static bool CheckWorldCollision(Vector3 start, Vector3 end, RayCollision *outCollision) { - Vector3 diff = Vector3Subtract(end, start); - float maxDist = Vector3Length(diff); - if (maxDist < 0.001f) return false; - - Ray ray = { 0 }; - ray.position = start; - ray.direction = Vector3Scale(diff, 1.0f / maxDist); - - RayCollision closest = { 0 }; - closest.distance = FLT_MAX; - closest.hit = false; - - for (int i = 0; i < game.world_model_count; i++) { - Model model = game.world_models[i]; - for (int m = 0; m < model.meshCount; m++) { - RayCollision col = GetRayCollisionMesh(ray, model.meshes[m], model.transform); - if (col.hit && col.distance < closest.distance && col.distance <= maxDist) { - closest = col; - } - } - } - - if (closest.hit) { - if (outCollision) *outCollision = closest; - return true; - } - return false; + if (game.player.pitch > 89.0f * DEG2RAD) game.player.pitch = 89.0f * DEG2RAD; + if (game.player.pitch < -89.0f * DEG2RAD) game.player.pitch = -89.0f * DEG2RAD; } static void MoveNormal(float dt) { - float eyeHeight = PLAYER_EYE_HEIGHT - (game.crouch_amount * PLAYER_CROUCH_OFFSET); + float eyeHeight = PLAYER_EYE_HEIGHT - (game.player.crouch_amount * PLAYER_CROUCH_OFFSET); - // Movement vectors based on yaw - Vector3 forward = { sinf(game.yaw), 0, cosf(game.yaw) }; - Vector3 right = { sinf(game.yaw - PI/2.0f), 0, cosf(game.yaw - PI/2.0f) }; + Vector3 forward = { sinf(game.player.yaw), 0, cosf(game.player.yaw) }; + Vector3 right = { sinf(game.player.yaw - PI/2.0f), 0, cosf(game.player.yaw - PI/2.0f) }; Vector3 moveDir = { 0 }; if (IsKeyDown(KEY_W)) moveDir = Vector3Add(moveDir, forward); @@ -59,24 +28,19 @@ static void MoveNormal(float dt) { float speed = PLAYER_MOVE_SPEED; if (IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT)) speed *= PLAYER_SPRINT_MULTIPLIER; - - // Apply crouch speed penalty - speed *= Lerp(1.0f, PLAYER_CROUCH_MOVE_MULTIPLIER, game.crouch_amount); + speed *= Lerp(1.0f, PLAYER_CROUCH_MOVE_MULTIPLIER, game.player.crouch_amount); if (Vector3Length(moveDir) > 0) { moveDir = Vector3Scale(Vector3Normalize(moveDir), speed * dt); } - // Apply gravity - game.velocity.y -= PLAYER_GRAVITY * dt; + game.player.velocity.y -= PLAYER_GRAVITY * dt; - // Jump - if (game.is_grounded && IsKeyPressed(KEY_SPACE)) { - game.velocity.y = PLAYER_JUMP_FORCE; - game.is_grounded = false; + if (game.player.is_grounded && IsKeyPressed(KEY_SPACE)) { + game.player.velocity.y = PLAYER_JUMP_FORCE; + game.player.is_grounded = false; } - // Horizontal movement with sliding collision Vector3 remainingMove = moveDir; for (int iter = 0; iter < 4 && Vector3Length(remainingMove) > 0.001f; iter++) { RayCollision closestHit = { 0 }; @@ -84,7 +48,7 @@ static void MoveNormal(float dt) { bool hitFound = false; float heights[] = { -eyeHeight + 10.0f, -eyeHeight / 2.0f, 0.0f }; - Vector3 currentPos = game.pos; + Vector3 currentPos = game.player.pos; for (int i = 0; i < 3; i++) { Vector3 start = Vector3Add(currentPos, (Vector3){0, heights[i], 0}); @@ -93,8 +57,7 @@ static void MoveNormal(float dt) { Vector3 end = Vector3Add(start, Vector3Scale(dir, dist)); RayCollision col; - if (CheckWorldCollision(start, end, &col)) { - // Adjust distance to be relative to the player boundary + if (CheckMapCollision(start, end, &col)) { float adjustedDist = col.distance - PLAYER_RADIUS; if (adjustedDist < closestHit.distance) { closestHit = col; @@ -105,13 +68,11 @@ static void MoveNormal(float dt) { } if (hitFound) { - // Move as far as possible float moveDist = fmaxf(0, closestHit.distance - 0.1f); Vector3 moveStep = Vector3Scale(Vector3Normalize(remainingMove), moveDist); - game.pos.x += moveStep.x; - game.pos.z += moveStep.z; + game.player.pos.x += moveStep.x; + game.player.pos.z += moveStep.z; - // Project remaining movement onto the plane of the wall Vector3 slideNormal = { closestHit.normal.x, 0, closestHit.normal.z }; if (Vector3Length(slideNormal) > 0.001f) { slideNormal = Vector3Normalize(slideNormal); @@ -122,68 +83,61 @@ static void MoveNormal(float dt) { remainingMove = (Vector3){0, 0, 0}; } } else { - // No collision found, move the rest of the way - game.pos.x += remainingMove.x; - game.pos.z += remainingMove.z; + game.player.pos.x += remainingMove.x; + game.player.pos.z += remainingMove.z; break; } } - // Vertical movement with collision - float verticalMove = game.velocity.y * dt; - Vector3 vStart = game.pos; + float verticalMove = game.player.velocity.y * dt; + Vector3 vStart = game.player.pos; - if (verticalMove < 0) { // Falling/Down + if (verticalMove < 0) { Vector3 start = vStart; - // Check slightly below feet Vector3 end = Vector3Add(vStart, (Vector3){0, verticalMove - eyeHeight, 0}); RayCollision vCol; - if (CheckWorldCollision(start, end, &vCol) && vCol.normal.y > 0.5f) { - game.pos.y = vCol.point.y + eyeHeight; - game.velocity.y = 0; - game.is_grounded = true; + if (CheckMapCollision(start, end, &vCol) && vCol.normal.y > 0.5f) { + game.player.pos.y = vCol.point.y + eyeHeight; + game.player.velocity.y = 0; + game.player.is_grounded = true; } else { - game.pos.y += verticalMove; - game.is_grounded = false; + game.player.pos.y += verticalMove; + game.player.is_grounded = false; } - } else if (verticalMove > 0) { // Jumping/Up + } else if (verticalMove > 0) { Vector3 start = vStart; - // Check above head float headHeight = PLAYER_HEIGHT - PLAYER_EYE_HEIGHT; Vector3 end = Vector3Add(vStart, (Vector3){0, verticalMove + headHeight, 0}); RayCollision vCol; - if (CheckWorldCollision(start, end, &vCol)) { - game.pos.y = vCol.point.y - headHeight - 1.0f; - game.velocity.y = 0; + if (CheckMapCollision(start, end, &vCol)) { + game.player.pos.y = vCol.point.y - headHeight - 1.0f; + game.player.velocity.y = 0; } else { - game.pos.y += verticalMove; + game.player.pos.y += verticalMove; } - game.is_grounded = false; + game.player.is_grounded = false; } else { - // Not moving vertically, but check if we are still on ground Vector3 start = vStart; Vector3 end = Vector3Add(vStart, (Vector3){0, -eyeHeight - 2.0f, 0}); RayCollision vCol; - if (CheckWorldCollision(start, end, &vCol) && vCol.normal.y > 0.5f) { - game.is_grounded = true; - // Snap to floor if very close + if (CheckMapCollision(start, end, &vCol) && vCol.normal.y > 0.5f) { + game.player.is_grounded = true; if (vCol.distance < eyeHeight + 1.0f) { - game.pos.y = vCol.point.y + eyeHeight; + game.player.pos.y = vCol.point.y + eyeHeight; } } else { - game.is_grounded = false; + game.player.is_grounded = false; } } } static void MoveFly(float dt) { - // Full 3D movement based on yaw/pitch Vector3 forward = { - cosf(game.pitch) * sinf(game.yaw), - -sinf(game.pitch), - cosf(game.pitch) * cosf(game.yaw) + cosf(game.player.pitch) * sinf(game.player.yaw), + -sinf(game.player.pitch), + cosf(game.player.pitch) * cosf(game.player.yaw) }; - Vector3 right = { sinf(game.yaw - PI/2.0f), 0, cosf(game.yaw - PI/2.0f) }; + Vector3 right = { sinf(game.player.yaw - PI/2.0f), 0, cosf(game.player.yaw - PI/2.0f) }; Vector3 move = { 0 }; if (IsKeyDown(KEY_W)) move = Vector3Add(move, forward); @@ -191,7 +145,6 @@ static void MoveFly(float dt) { if (IsKeyDown(KEY_D)) move = Vector3Add(move, right); if (IsKeyDown(KEY_A)) move = Vector3Subtract(move, right); - // Fly up/down if (IsKeyDown(KEY_SPACE)) move.y += 1.0f; if (IsKeyDown(KEY_LEFT_CONTROL)) move.y -= 1.0f; @@ -200,86 +153,75 @@ static void MoveFly(float dt) { if (Vector3Length(move) > 0) { move = Vector3Scale(Vector3Normalize(move), speed * dt); - game.pos = Vector3Add(game.pos, move); + game.player.pos = Vector3Add(game.player.pos, move); } - game.velocity = (Vector3){0, 0, 0}; - game.is_grounded = false; + game.player.velocity = (Vector3){0, 0, 0}; + game.player.is_grounded = false; } void UpdatePlayer(void) { float dt = GetFrameTime(); - Vector3 oldPos = game.pos; + Vector3 oldPos = game.player.pos; if (IsKeyPressed(KEY_F)) { - game.move_mode = (game.move_mode == MOVE_NORMAL) ? MOVE_FLY : MOVE_NORMAL; - TraceLog(LOG_INFO, "Movement mode: %s", (game.move_mode == MOVE_NORMAL) ? "NORMAL" : "FLY"); + game.player.move_mode = (game.player.move_mode == MOVE_NORMAL) ? MOVE_FLY : MOVE_NORMAL; } PlayerRotate(); - // Crouching logic bool canStand = true; - if (game.crouch_amount > 0.1f) { - Vector3 headPos = game.pos; + if (game.player.crouch_amount > 0.1f) { + Vector3 headPos = game.player.pos; Vector3 headEnd = Vector3Add(headPos, (Vector3){0, PLAYER_HEIGHT - PLAYER_EYE_HEIGHT + PLAYER_CROUCH_OFFSET, 0}); RayCollision col; - if (CheckWorldCollision(headPos, headEnd, &col)) { + if (CheckMapCollision(headPos, headEnd, &col)) { canStand = false; } } float targetCrouch = 0.0f; if (IsKeyDown(KEY_LEFT_CONTROL) || !canStand) targetCrouch = 1.0f; - game.crouch_amount = Lerp(game.crouch_amount, targetCrouch, PLAYER_CROUCH_SPEED * dt); + game.player.crouch_amount = Lerp(game.player.crouch_amount, targetCrouch, PLAYER_CROUCH_SPEED * dt); - // Leaning logic float targetLean = 0.0f; if (IsKeyDown(KEY_Q)) targetLean -= 1.0f; if (IsKeyDown(KEY_E)) targetLean += 1.0f; + game.player.lean_amount = Lerp(game.player.lean_amount, targetLean, PLAYER_LEAN_SPEED * dt); - game.lean_amount = Lerp(game.lean_amount, targetLean, PLAYER_LEAN_SPEED * dt); - - if (game.move_mode == MOVE_FLY) { + if (game.player.move_mode == MOVE_FLY) { MoveFly(dt); } else { MoveNormal(dt); } - // Apply lean as a pivot from the neck/waist - float leanAngle = game.lean_amount * PLAYER_LEAN_ANGLE * DEG2RAD; - Vector3 bodyForward = { sinf(game.yaw), 0, cosf(game.yaw) }; + float leanAngle = game.player.lean_amount * PLAYER_LEAN_ANGLE * DEG2RAD; + Vector3 bodyForward = { sinf(game.player.yaw), 0, cosf(game.player.yaw) }; - float currentEyeHeight = PLAYER_EYE_HEIGHT - (game.crouch_amount * PLAYER_CROUCH_OFFSET); + float currentEyeHeight = PLAYER_EYE_HEIGHT - (game.player.crouch_amount * PLAYER_CROUCH_OFFSET); float pivotDist = fminf(PLAYER_LEAN_PIVOT_DISTANCE, currentEyeHeight * 0.8f); Vector3 neckToEye = { 0, pivotDist, 0 }; Vector3 rotatedOffset = Vector3RotateByAxisAngle(neckToEye, bodyForward, leanAngle); - Vector3 pivot = Vector3Subtract(game.pos, (Vector3){ 0, pivotDist, 0 }); + Vector3 pivot = Vector3Subtract(game.player.pos, (Vector3){ 0, pivotDist, 0 }); - // Update camera based on physical pos + visual lean pivot game.camera.position = Vector3Add(pivot, rotatedOffset); - // Apply roll to up vector Vector3 forward = { - cosf(game.pitch) * sinf(game.yaw), - -sinf(game.pitch), - cosf(game.pitch) * cosf(game.yaw) + cosf(game.player.pitch) * sinf(game.player.yaw), + -sinf(game.player.pitch), + cosf(game.player.pitch) * cosf(game.player.yaw) }; - // Use a stable world-up vector and apply lean roll Vector3 up = { 0, 1, 0 }; up = Vector3RotateByAxisAngle(up, forward, leanAngle); game.camera.up = up; - - // Use a longer target distance for better precision in the projection matrix game.camera.target = Vector3Add(game.camera.position, Vector3Scale(forward, 20.0f)); - // Calculate horizontal speed for UI if (dt > 0) { - Vector2 velH = { game.pos.x - oldPos.x, game.pos.z - oldPos.z }; - game.horizontal_speed = Vector2Length(velH) / dt; + Vector2 velH = { game.player.pos.x - oldPos.x, game.player.pos.z - oldPos.z }; + game.player.horizontal_speed = Vector2Length(velH) / dt; } else { - game.horizontal_speed = 0; + game.player.horizontal_speed = 0; } } -- cgit v1.2.3