feat: deltatime based physic

This commit is contained in:
Pc
2026-01-28 01:36:56 +01:00
parent 233d4189d1
commit 60c71b0993

View File

@@ -91,6 +91,8 @@ bool panoramic_view = 0;
//Zmienne do ruchu ##############################################^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //Zmienne do ruchu ##############################################^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FPSCounter fpsCounter; FPSCounter fpsCounter;
float deltaTime = 0.0f;
static const int targetFPS = 444; // Celowany FPS static const int targetFPS = 444; // Celowany FPS
//Fps counter //Fps counter
@@ -190,61 +192,79 @@ static bool CheckAllFencesCollision(float rXMin, float rXMax, float rZMin, float
} }
static void UpdateRover(const std::vector<Plot>& fences) { static void UpdateRover(const std::vector<Plot>& 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) --- // --- 1. OBSŁUGA PRZYSPIESZENIA (W / S) ---
if (keyWPressed) { if (keyWPressed) {
velocity += acceleration; velocity += acceleration * timeScale;
if (velocity > maxSpeed) velocity = maxSpeed; if (velocity > maxSpeed) velocity = maxSpeed;
} }
else if (keySPressed) { else if (keySPressed) {
velocity -= acceleration; velocity -= acceleration * timeScale;
if (velocity < -maxSpeed) velocity = -maxSpeed; if (velocity < -maxSpeed) velocity = -maxSpeed;
} }
else { else {
// Hamowanie (tarcie) // Hamowanie (tarcie)
float frictionStep = friction * timeScale;
if (velocity > 0) { if (velocity > 0) {
velocity -= friction; velocity -= frictionStep;
if (velocity < 0) velocity = 0; if (velocity < 0) velocity = 0;
} }
else if (velocity < 0) { else if (velocity < 0) {
velocity += friction; velocity += frictionStep;
if (velocity > 0) velocity = 0; if (velocity > 0) velocity = 0;
} }
} }
// --- 2. OBSŁUGA OBROTU (A / D) --- // --- 2. OBSŁUGA OBROTU (A / D) ---
if (keyAPressed) { if (keyAPressed) {
rotationVelocity += rotationAcceleration; rotationVelocity += rotationAcceleration * timeScale;
if (rotationVelocity > maxRotationSpeed) rotationVelocity = maxRotationSpeed; if (rotationVelocity > maxRotationSpeed) rotationVelocity = maxRotationSpeed;
} }
else if (keyDPressed) { else if (keyDPressed) {
rotationVelocity -= rotationAcceleration; rotationVelocity -= rotationAcceleration * timeScale;
if (rotationVelocity < -maxRotationSpeed) rotationVelocity = -maxRotationSpeed; if (rotationVelocity < -maxRotationSpeed) rotationVelocity = -maxRotationSpeed;
} }
else { else {
// Driftowanie (wytracanie rotacji) // Driftowanie (wytracanie rotacji)
float driftFactor = 0.1f; float driftFactor = 0.1f;
float rotationFrictionStep = rotationFriction * driftFactor * timeScale;
if (rotationVelocity > 0) { if (rotationVelocity > 0) {
rotationVelocity -= rotationFriction * driftFactor; rotationVelocity -= rotationFrictionStep;
if (rotationVelocity < 0) rotationVelocity = 0; if (rotationVelocity < 0) rotationVelocity = 0;
} }
else if (rotationVelocity < 0) { else if (rotationVelocity < 0) {
rotationVelocity += rotationFriction * driftFactor; rotationVelocity += rotationFrictionStep;
if (rotationVelocity > 0) rotationVelocity = 0; if (rotationVelocity > 0) rotationVelocity = 0;
} }
} }
// --- 3. LOGIKA ODWRÓCENIA SKRĘTU PRZY COFANIU --- // --- 3. LOGIKA ODWRÓCENIA SKRĘTU PRZY COFANIU ---
// Jeśli prędkość jest ujemna, odwracamy wpływ rotationVelocity na kąt, // Tutaj też stosujemy timeScale do obliczenia faktycznego kroku obrotu w tej klatce
// aby klawisz D zawsze kierował pojazd w prawo względem kamery. float actualRotationStep = rotationVelocity * timeScale;
float actualRotationStep = rotationVelocity;
if (velocity < 0.0f) { if (velocity < 0.0f) {
actualRotationStep = -rotationVelocity; actualRotationStep = -actualRotationStep;
} }
// --- 4. WYLICZENIE NOWEJ POZYCJI --- // --- 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 radRotation = Rotation * GL_PI / 180.0f;
float newSides = Sides - velocity * cos(radRotation); float newSides = Sides - currentMoveStep * cos(radRotation);
float newFoward = Foward - velocity * sin(radRotation); float newFoward = Foward - currentMoveStep * sin(radRotation);
// Wymiary łazika // Wymiary łazika
const float roverHalfWidthX = 19.0f; const float roverHalfWidthX = 19.0f;
@@ -261,6 +281,8 @@ static void UpdateRover(const std::vector<Plot>& fences) {
// Kolizja przy ruchu przód/tył // Kolizja przy ruchu przód/tył
if (CheckAllFencesCollision(roverZMin, roverZMax, roverXMin, roverXMax, fences)) { if (CheckAllFencesCollision(roverZMin, roverZMax, roverXMin, roverXMax, fences)) {
velocity = 0.0f; velocity = 0.0f;
// Opcjonalnie: minimalne odbicie, żeby nie "kleił" się do ściany
// velocity = -velocity * 0.1f;
} }
else { else {
Sides = newSides; Sides = newSides;
@@ -272,7 +294,8 @@ static void UpdateRover(const std::vector<Plot>& fences) {
float newRotation = Rotation + actualRotationStep; float newRotation = Rotation + actualRotationStep;
float radNewRotation = newRotation * GL_PI / 180.0f; 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<std::pair<float, float>> corners = { std::vector<std::pair<float, float>> corners = {
{Sides - roverHalfWidthX, Foward - roverHalfLengthZ}, {Sides - roverHalfWidthX, Foward - roverHalfLengthZ},
{Sides + roverHalfWidthX, Foward - roverHalfLengthZ}, {Sides + roverHalfWidthX, Foward - roverHalfLengthZ},
@@ -289,7 +312,9 @@ static void UpdateRover(const std::vector<Plot>& fences) {
float rotatedX = Sides + (x - Sides) * cos(radNewRotation) - (z - Foward) * sin(radNewRotation); float rotatedX = Sides + (x - Sides) * cos(radNewRotation) - (z - Foward) * sin(radNewRotation);
float rotatedZ = Foward + (x - Sides) * sin(radNewRotation) + (z - Foward) * cos(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; collisionDetected = true;
break; break;
} }
@@ -802,13 +827,20 @@ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
ShowWindow(hWnd, SW_SHOW); ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd); UpdateWindow(hWnd);
ZeroMemory(&msg, sizeof(msg)); ZeroMemory(&msg, sizeof(msg));
auto lastFrameTime = std::chrono::high_resolution_clock::now();
while (msg.message != WM_QUIT) { while (msg.message != WM_QUIT) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
} }
else { else {
auto currentFrameTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<float> timeSpan = currentFrameTime - lastFrameTime;
deltaTime = timeSpan.count(); // Czas w sekundach (np. 0.0069 przy 144 FPS)
lastFrameTime = currentFrameTime;
RenderScene(); RenderScene();
// --- POPRAWKA 2: Używaj zapisanego hDC, a nie pobieraj nowego --- // --- POPRAWKA 2: Używaj zapisanego hDC, a nie pobieraj nowego ---