feat: deltatime based physic
This commit is contained in:
64
main.cpp
64
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<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) ---
|
||||
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<Plot>& 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<Plot>& 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<std::pair<float, float>> corners = {
|
||||
{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 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<float> 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 ---
|
||||
|
||||
Reference in New Issue
Block a user