Ich versuche mit Vektoren eine realistische Fahrzeugbewegung zu erzeugen


12

Ich habe glotzte wie dies zu tun und fanden diese http://www.helixsoft.nl/articles/circle/sincos.htm ich es mal gehabt haben , aber die meisten der Funktionen , die zeigten , wurden nicht ich gerade bekam Fehler funktionierten weil sie nicht existierten. Ich habe mir die Funktionen cos und sin angeschaut, verstehe aber nicht, wie man sie benutzt oder wie man die Bewegung des Autos mithilfe von Vektoren korrekt zum Laufen bringt. Ich habe keinen Code, weil ich nicht sicher bin, was ich tun soll.

Jede Hilfe wird geschätzt.

BEARBEITEN:

Ich habe Einschränkungen, dass ich die TL-Engine für mein Spiel verwenden muss. Es ist mir nicht gestattet, irgendeine Art von Physik-Engine hinzuzufügen. Es muss in c ++ programmiert werden. Hier ist ein Beispiel von dem, was ich bei dem Versuch mitbekommen habe, dem zu folgen, was in dem von mir bereitgestellten Link getan wurde.

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);

Überprüfen Sie diese Seite auf Lenkverhalten: red3d.com/cwr/steer
MichaelHouse

Sie müssen "realistische Auto Bewegung" definieren
Maik Semder

1
Ich nehme an, dein Winkel kommt vielleicht vom Lenkrad. Die Länge sollte die Größe Ihrer Geschwindigkeit sein. So ist der letzte Code - Schnipsel etwas auf den Linien sein könnten: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);abgesehen davon, bitte sagen , was Ihre Eingabe ist und wie sich das Auto verhalten soll. Im Moment sollte es in der Grundebene lenken, aber auch dies ist überhaupt nicht allgemein. Dort haben Sie gerade einen groben Euler-Integrationsschritt gemacht.
teodron

Antworten:


23

Es ist nicht so schwer, eine ziemlich gute Autobewegung zu erschaffen (aber dieser Beitrag wird ziemlich lang sein). Sie müssen ein paar grundlegende Kräfte "simulieren", um das Auto physikalisch plausibel zu bewegen.

(Alle Codebeispiele sind Pseudocodes.)

Beschleunigung

Zunächst müssen Sie natürlich beschleunigen. Etwas so Einfaches wie die folgende Zeile:

acceleration_vector = forward_vector * acceleration_input * acceleration_factor
  • forward_vector - Ein Vektor, der in dieselbe Richtung zeigt wie das Auto.
  • acceleration_input - Die Eingabe sollte im Intervall [-1, 1] liegen.
  • acceleration_factor - Der Wert der Beschleunigung (Pixel / Sekunde ^ 2 oder was auch immer Ihre Einheiten sind).

Lenkung

Die Lenkung ist auch ziemlich einfach. Im Prinzip drehen Sie den Vorwärtsvektor des Autos so, dass er in eine andere Richtung zeigt.

steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)

Hier kann es jedoch zu Komplikationen kommen. Wenn Ihre Eingabe über eine Tastatur erfolgt, ist der Wert entweder -1 oder 1, was bedeutet, dass sich Ihr Auto sofort dreht. Sie können dies mit einer sehr einfachen linearen Interpolation (Lerping) beheben:

 amount = time_since_last_frame * steer_lerp_factor
 forward_vector = lerp(forward_vector, new_forward_vector, amount)

Die Menge sollte von der Zeit abhängen, sodass Ihre Bewegung nicht von Ihrer Framerate abhängt. Der Betrag sollte zwischen [0, 1] und je kleiner er ist, desto weicher wird der Übergang zwischen dem alten und dem neuen Vektor sein.

(An diesem Punkt werden Sie feststellen, dass das Auto auch dann lenkt, wenn es stillsteht. Um dies zu verhindern, multiplizieren Sie steer_anglemit current_speed / max_speed, wo max_speedeine von Ihnen definierte Konstante ist.)

Ziehen um

Jetzt wenden wir die Beschleunigung an und bewegen das Auto um eine bestimmte Anzahl von Pixeln, basierend auf seiner Geschwindigkeit, Beschleunigung und Lenkung. Wir werden auch die Geschwindigkeit des Autos so begrenzen wollen, dass es sich nicht unendlich schnell bewegt.

current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Ihr Auto rutscht jetzt

Wenn ich recht habe, sollte Ihr Auto jetzt beim Abbiegen wie auf Eis rutschen. Dies liegt daran, dass es keine Reibung gibt. Bei einem echten Auto gibt es eine hohe Seitenreibung (da sich die Räder nicht seitlich drehen können: P).

Sie müssen die Quergeschwindigkeit reduzieren. Indem Sie es nicht vollständig reduzieren, können Sie das Auto auch so wirken lassen, als ob es treibt.

 lateral_velocity = right_vector * dot(velocity_vector, right_vector)
 lateral_friction = -lateral_velocity * lateral_friction_factor 

Da es sich um Reibung handelt, möchten Sie möglicherweise auch eine Kraft (Reibung) haben, die Ihre Geschwindigkeit verringert, sodass Ihr Auto irgendwann anhält, wenn Sie aufhören zu beschleunigen.

 backwards_friction = -velocity_vector * backwards_friction_factor

Ihr Code zum Bewegen des Autos sollte jetzt so aussehen:

// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame


current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{ 
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Notizen schließen

Ich erwähnte, wie Sie Lerping zum Lenken anwenden sollten; Ich denke, Sie müssen möglicherweise das Gleiche für die Beschleunigung und möglicherweise auch für den Lenkwinkel tun (Sie müssen die Werte des vorherigen Frames speichern und danach lerpen). Auch sollten alle Vektoren relativ zum Auto (vorwärts, rechts, oben) die Länge 1 haben.

Auch die Reibung ist etwas komplizierter als ich hier gezeigt habe. Sie sollten immer darauf achten, dass seine Länge niemals größer ist als die Beschleunigung, die zum Anhalten des Autos erforderlich ist (andernfalls würde das Auto durch Reibung in die entgegengesetzte Richtung fahren). Sie sollten also etwas haben wie:

dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))

Wow, das ist eine großartige Antwort!
Ezolotko

0

Ihrer Frage nach zu urteilen, gehe ich davon aus, dass Sie relativ neu in der Programmierung sind (was übrigens a-ok ist!). Ich würde vorschlagen, vorhandene Frameworks zu verwenden, da eine realistische Autosimulation einer der schwierigsten Aspekte der Physik ist.

Sie haben die 2D / 3D-Einschränkungen nicht erwähnt. Daher schlage ich vor, dass Sie Havok SDK (kostenlos für nichtkommerzielle Zwecke) herunterladen und eine einfache Demo zum Laufen bringen (es gibt tatsächlich Demos, die sofort verfügbar sind) kompiliert auf Ihrem System, der gesamte Code ist da], Sie müssen nichts tun, um ihn zu kompilieren ... öffnen Sie einfach das Projekt und klicken Sie auf build.

Wenn Sie eine Vorstellung von den Aspekten der Fahrzeugphysik hinter den Kulissen haben (obwohl Sie die tatsächliche Implementierung der Physik nicht sehen, die verborgen ist, werden Sie die Schnittstellen sehen), glaube ich, dass Sie in einer besseren Position sind um es richtig zu machen, wenn Sie alleine anfangen.

Ich habe auch eine ähnliche Frage vor nicht allzu langer Zeit gestellt. Die darin enthaltenen Links können ebenfalls hilfreich sein. Und hier ist ein weiterer Link .


Nachdem Sie sich Ihre Bearbeitung angesehen haben, scheint es, als würden Sie einfach die Geschwindigkeit des Autos in Abhängigkeit von den berechneten Winkeln ändern (das ist übrigens nicht realistisch, also sollten Sie die ursprüngliche Frage ändern, um dies widerzuspiegeln). Wenn die Winkel Teil der Frage sind (die Sie nicht ändern können) und Sie die Winkel verwenden müssen, um die neue Geschwindigkeit zu berechnen, fahren Sie mit dem fort, was @teodron in den Kommentaren angegeben hat.

Eine andere Möglichkeit besteht darin, nur Vektoren zu verwenden. Es gibt mehrere Ansätze mit Vektoren, ich werde einen vorstellen.

Eine Geschwindigkeit ist Richtung * Größe (wobei Größe Geschwindigkeit und Richtung ein normalisierter Vektor ist). Berechnen Sie die aktuelle Geschwindigkeit und Richtung des Autos. Nehmen Sie die Richtung und fügen Sie einen Vektor (nennen wir ihn D') senkrecht dazu hinzu. Dies ändert die Geschwindigkeit des Autos. Kein Winkel Kampf mit (obwohl Sie können Winkel verwenden , um die Länge des Lotes Vektors zu bestimmen , die Sie sein können drehen Faktor [siehe unten])

So berechnen SieD' : Um den senkrechten Vektor zu finden, nehmen Sie die Richtung der ursprünglichen Geschwindigkeit und kreuzen Sie ihn mit dem Richtungsvektor, der auf den Bildschirm zukommt. Die Reihenfolge, in der Sie die Vektoren kreuzen, bestimmt die Richtung des senkrechten Vektors. Dann mehrere dieser perpedicular Faktor mit einigen wiederum Faktor , der bestimmt , wie schnell das Auto es drehen.


Ich würde, aber ich darf keine Physik-Engine verwenden, das Spiel ist 3D und alles, was ich ändern muss, sind die X- und Z-Vektoren. Ich muss nur herausfinden, was sie sind.
Bobthemac

@bobthemac: Ist das eine Hausaufgabe? Wenn ja, bearbeiten Sie Ihre Frage, um auf die Einschränkungen hinzuweisen, die Sie haben, und veröffentlichen Sie möglicherweise einen relevanten Code, damit wir etwas aufbauen können. Übrigens kann der letzte Link genau das sein, wonach Sie suchen, um die Funktionalität zu verstehen.
Samaursa

Ich habe die angeforderten Informationen hinzugefügt und die bereitgestellten Links angesehen, verstehe sie aber immer noch nicht.
Bobthemac

@ Bobthemac: Siehe meine Bearbeitung
Samaursa
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.