// playerController.c #include "raylib.h" #include "raymath.h" #include "playerController.h" #include "blockTypes.h" #include "world.h" #include inline int FloorDiv(int a, int b) { return (a >= 0) ? (a / b) : ((a - b + 1) / b); } void UpdatePlayer(Player *player) { Vector2 mouseDelta = GetMouseDelta(); player->playerOrientation.x += mouseDelta.x * -0.002f; player->playerOrientation.y += mouseDelta.y * -0.002f; float limit = PI / 1.8f; if (player->playerOrientation.y > limit) player->playerOrientation.y = limit; if (player->playerOrientation.y < -limit) player->playerOrientation.y = -limit; float yaw = player->playerOrientation.x; float pitch = player->playerOrientation.y; player->forward = (Vector3){ cosf(pitch) * sinf(yaw), sinf(pitch), cosf(pitch) * cosf(yaw) }; player->right = (Vector3){ sinf(yaw - PI/2.0f), 0.0f, cosf(yaw - PI/2.0f) }; Vector3 movement = {0}; if (IsKeyDown(KEY_W)) movement = Vector3Add(movement, player->forward); if (IsKeyDown(KEY_S)) movement = Vector3Subtract(movement, player->forward); if (IsKeyDown(KEY_A)) movement = Vector3Subtract(movement, player->right); if (IsKeyDown(KEY_D)) movement = Vector3Add(movement, player->right); if (IsKeyDown(KEY_SPACE)) movement.y += 1.0f; if (IsKeyDown(KEY_LEFT_SHIFT)) movement.y -= 1.0f; if (Vector3Length(movement) > 0.0f) movement = Vector3Scale(Vector3Normalize(movement), player->moveSpeed * GetFrameTime()); player->mapPosition = Vector3Add(player->mapPosition, movement); player->camera.position = player->mapPosition; player->camera.target = Vector3Add(player->mapPosition, player->forward); } RaycastHit GetPlayerRaycastHit(Player *player, World *world, float maxDistance) { RaycastHit result = {0}; Vector3 origin = Vector3Add(player->camera.position, Vector3Scale(player->forward, 0.001f)); Vector3 dir = Vector3Normalize(player->forward); int x = (int)floorf(origin.x); int y = (int)floorf(origin.y); int z = (int)floorf(origin.z); int stepX = (dir.x > 0) ? 1 : -1; int stepY = (dir.y > 0) ? 1 : -1; int stepZ = (dir.z > 0) ? 1 : -1; float tMaxX = ((stepX > 0 ? (x + 1) : x) - origin.x) / dir.x; float tMaxY = ((stepY > 0 ? (y + 1) : y) - origin.y) / dir.y; float tMaxZ = ((stepZ > 0 ? (z + 1) : z) - origin.z) / dir.z; float tDeltaX = fabsf(1.0f / dir.x); float tDeltaY = fabsf(1.0f / dir.y); float tDeltaZ = fabsf(1.0f / dir.z); float t = 0.0f; Vector3 lastNormal = {0}; for (int i = 0; i < (int)(maxDistance * 3); i++) { int chunkX = FloorDiv(x, CHUNK_SIZE_X); int chunkZ = FloorDiv(z, CHUNK_SIZE_Z); Chunk *chunk = GetChunk(world, chunkX, chunkZ); if (chunk) { int localX = x - chunkX * CHUNK_SIZE_X; int localY = y; int localZ = z - chunkZ * CHUNK_SIZE_Z; if (localX >= 0 && localX < CHUNK_SIZE_X && localY >= 0 && localY < CHUNK_SIZE_Y && localZ >= 0 && localZ < CHUNK_SIZE_Z) { Block block = chunk->blocks[localX][localY][localZ]; if (block.type != BLOCK_AIR) { result.hit = true; result.hitBlockX = x; result.hitBlockY = y; result.hitBlockZ = z; result.normal = lastNormal; result.chunkX = chunkX; result.chunkZ = chunkZ; result.t = t; // For visual debugging result.position = Vector3Add((Vector3){x, y, z}, Vector3Scale(lastNormal, 0.5f)); return result; } } } // DDA step if (tMaxX < tMaxY && tMaxX < tMaxZ) { x += stepX; t = tMaxX; tMaxX += tDeltaX; lastNormal = (Vector3){-stepX, 0, 0}; } else if (tMaxY < tMaxZ) { y += stepY; t = tMaxY; tMaxY += tDeltaY; lastNormal = (Vector3){0, -stepY, 0}; } else { z += stepZ; t = tMaxZ; tMaxZ += tDeltaZ; lastNormal = (Vector3){0, 0, -stepZ}; } if (t > maxDistance) break; } return result; }