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_angle
mit current_speed / max_speed
, wo max_speed
eine 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))