diff --git a/main.cpp b/main.cpp index 63add05..1173b8c 100644 --- a/main.cpp +++ b/main.cpp @@ -91,6 +91,8 @@ bool panoramic_view = 0; //Zmienne do ruchu ##############################################^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FPSCounter fpsCounter; +float deltaTime = 0.0f; + static const int targetFPS = 444; // Celowany FPS //Fps counter @@ -190,61 +192,79 @@ static bool CheckAllFencesCollision(float rXMin, float rXMax, float rZMin, float } static void UpdateRover(const std::vector& fences) { + // --- SKALOWANIE CZASU --- + // Twoje stałe (acceleration, maxSpeed) były ustawione pod 144 FPS. + // Mnożnik timeScale sprawia, że fizyka działa tak samo, ale jest niezależna od klatek. + // Jeśli deltaTime = 1/144, to timeScale = 1.0 (czyli bez zmian). + // Jeśli FPS spadnie, timeScale wzrośnie, kompensując spowolnienie. + float timeScale = deltaTime * 144.0f; + + // Zabezpieczenie na wypadek ekstremalnie niskiego FPS (np. przy ładowaniu), + // żeby łazik nie przeleciał przez ścianę w jednej klatce. + if (timeScale > 5.0f) timeScale = 5.0f; + // --- 1. OBSŁUGA PRZYSPIESZENIA (W / S) --- if (keyWPressed) { - velocity += acceleration; + velocity += acceleration * timeScale; if (velocity > maxSpeed) velocity = maxSpeed; } else if (keySPressed) { - velocity -= acceleration; + velocity -= acceleration * timeScale; if (velocity < -maxSpeed) velocity = -maxSpeed; } else { // Hamowanie (tarcie) + float frictionStep = friction * timeScale; + if (velocity > 0) { - velocity -= friction; + velocity -= frictionStep; if (velocity < 0) velocity = 0; } else if (velocity < 0) { - velocity += friction; + velocity += frictionStep; if (velocity > 0) velocity = 0; } } // --- 2. OBSŁUGA OBROTU (A / D) --- if (keyAPressed) { - rotationVelocity += rotationAcceleration; + rotationVelocity += rotationAcceleration * timeScale; if (rotationVelocity > maxRotationSpeed) rotationVelocity = maxRotationSpeed; } else if (keyDPressed) { - rotationVelocity -= rotationAcceleration; + rotationVelocity -= rotationAcceleration * timeScale; if (rotationVelocity < -maxRotationSpeed) rotationVelocity = -maxRotationSpeed; } else { // Driftowanie (wytracanie rotacji) float driftFactor = 0.1f; + float rotationFrictionStep = rotationFriction * driftFactor * timeScale; + if (rotationVelocity > 0) { - rotationVelocity -= rotationFriction * driftFactor; + rotationVelocity -= rotationFrictionStep; if (rotationVelocity < 0) rotationVelocity = 0; } else if (rotationVelocity < 0) { - rotationVelocity += rotationFriction * driftFactor; + rotationVelocity += rotationFrictionStep; if (rotationVelocity > 0) rotationVelocity = 0; } } // --- 3. LOGIKA ODWRÓCENIA SKRĘTU PRZY COFANIU --- - // Jeśli prędkość jest ujemna, odwracamy wpływ rotationVelocity na kąt, - // aby klawisz D zawsze kierował pojazd w prawo względem kamery. - float actualRotationStep = rotationVelocity; + // Tutaj też stosujemy timeScale do obliczenia faktycznego kroku obrotu w tej klatce + float actualRotationStep = rotationVelocity * timeScale; + if (velocity < 0.0f) { - actualRotationStep = -rotationVelocity; + actualRotationStep = -actualRotationStep; } // --- 4. WYLICZENIE NOWEJ POZYCJI --- + // Obliczamy przesunięcie w tej klatce (velocity to jednostki na klatkę przy 144fps, więc mnożymy przez timeScale) + float currentMoveStep = velocity * timeScale; + float radRotation = Rotation * GL_PI / 180.0f; - float newSides = Sides - velocity * cos(radRotation); - float newFoward = Foward - velocity * sin(radRotation); + float newSides = Sides - currentMoveStep * cos(radRotation); + float newFoward = Foward - currentMoveStep * sin(radRotation); // Wymiary łazika const float roverHalfWidthX = 19.0f; @@ -261,6 +281,8 @@ static void UpdateRover(const std::vector& fences) { // Kolizja przy ruchu przód/tył if (CheckAllFencesCollision(roverZMin, roverZMax, roverXMin, roverXMax, fences)) { velocity = 0.0f; + // Opcjonalnie: minimalne odbicie, żeby nie "kleił" się do ściany + // velocity = -velocity * 0.1f; } else { Sides = newSides; @@ -272,7 +294,8 @@ static void UpdateRover(const std::vector& fences) { float newRotation = Rotation + actualRotationStep; float radNewRotation = newRotation * GL_PI / 180.0f; - // Punkty narożne do sprawdzenia po obrocie (OBB) + // Punkty narożne do sprawdzenia po obrocie (OBB - uproszczone sprawdzenie narożników) + // Używamy zaktualizowanych Sides/Foward (jeśli ruch do przodu się udał) std::vector> corners = { {Sides - roverHalfWidthX, Foward - roverHalfLengthZ}, {Sides + roverHalfWidthX, Foward - roverHalfLengthZ}, @@ -289,7 +312,9 @@ static void UpdateRover(const std::vector& fences) { float rotatedX = Sides + (x - Sides) * cos(radNewRotation) - (z - Foward) * sin(radNewRotation); float rotatedZ = Foward + (x - Sides) * sin(radNewRotation) + (z - Foward) * cos(radNewRotation); - if (CheckAllFencesCollision(rotatedX, rotatedX, rotatedZ, rotatedZ, fences)) { + // Sprawdzamy czy punkt (o bardzo małym promieniu) wchodzi w płot + // Dla uproszczenia traktujemy punkt jako malutki kwadrat +/- 1.0f + if (CheckAllFencesCollision(rotatedZ - 1.0f, rotatedZ + 1.0f, rotatedX - 1.0f, rotatedX + 1.0f, fences)) { collisionDetected = true; break; } @@ -802,13 +827,20 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); + + ZeroMemory(&msg, sizeof(msg)); + auto lastFrameTime = std::chrono::high_resolution_clock::now(); while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { + auto currentFrameTime = std::chrono::high_resolution_clock::now(); + std::chrono::duration timeSpan = currentFrameTime - lastFrameTime; + deltaTime = timeSpan.count(); // Czas w sekundach (np. 0.0069 przy 144 FPS) + lastFrameTime = currentFrameTime; RenderScene(); // --- POPRAWKA 2: Używaj zapisanego hDC, a nie pobieraj nowego ---