2009-06-03 16 views
1

Ich bin auf der Suche nach einer Möglichkeit, die Geschwindigkeit einer kreisförmigen Bewegung sanft zu erhöhen oder zu verringern.Ändern der Geschwindigkeit einer kreisförmigen Bewegung

die Parametergleichung eines Kreis verwendet, kann ich ein Objekt in einem Kreis im Laufe der Zeit bewegen:

x = center_x + radius * sin(time * speed) 
y = center_y + radius * cos(time * speed) 

Das Problem bei diesem Ansatz ist, dass ich nicht einfach speed = speed + 1 tun kann, um das Objekt, weil es zu beschleunigen führt zu ruckartigen Bewegungen. Dies ist sinnvoll, da die x- und y-Werte für jedes Bild auf der Basis absoluter Werte und nicht relativ zur vorherigen Position des Objekts neu berechnet werden.

Ein weiterer Ansatz könnte sein, einen Vektor zu verwenden, die die Geschwindigkeit des Objekts darstellt, dann stattdessen eine kreisförmige Bewegung auf den Vektor gelten:

v_x = radius * sin(time * speed) 
v_y = radius * cos(time * speed) 
x = x + v_x 
y = y + v_y 

Das Problem bei diesem Ansatz ist, dass, wenn ich die Geschwindigkeit ändern, dann der Radius wird wachsen oder schrumpfen. Dies ist sinnvoll, da die Bewegung relativ zur aktuellen Position ist und somit die Zeit im Wesentlichen übersprungen wird, wenn ich die Geschwindigkeit verändere.

Eine Implementierung, die ich mir vorstellen kann, ist die Verwendung eines Vektors, der vom Objekt zum Mittelpunkt des Kreises zeigt. Dann könnte ich die Tangente des Kreises an der Objektposition berechnen, indem ich den senkrechten Vektor verwende, ihn normalisiere und ihn nach der Geschwindigkeit skaliere. Ich habe das noch nicht implementiert, weil es für ein Problem wie dieses Overkill zu sein scheint. Bitte lassen Sie mich wissen, ob es eine einfachere Lösung gibt. Vielen Dank!

Antwort

6

Die Geschwindigkeit ist die Geschwindigkeit der Änderung des Winkels, eine Änderung der Geschwindigkeit wirkt sich nur auf die Änderung des Winkels für das letzte Intervall, so:

delta = time - lastTime 
angle = angle + delta * speed 

x = center_x + radius * sin(angle) 
y = center_y + radius * cos(angle) 

wo Lasttime muss die Zeit des letzten Zyklus halten , verstehen?

+0

Dies hat das gleiche Problem wie meine zweite Implementierung. Probieren Sie es selbst aus. – Kai

+0

@Kai: umm, nein sollte es nicht ... – ephemient

+0

Ah, meine Implementierung war falsch, nicht dieser Algorithmus (so dumm aussehen). Vielen Dank! – Kai

3

Sie verwenden Beschleunigung nicht korrekt, wenn Sie einfach speed = speed + 1 tun. Allgemeiner, Sie dies tun wollen:

accel = 1; 
speed = speed + (accel * timeDelta); 

Auch accel = 1 ist eine recht große Winkelgeschwindigkeitsänderung in Radiant - versuchen, einen kleineren Wert, sagen PI/16. Wenn Sie möchten, dass die Beschleunigung so groß ist und Sie die Sichtbarkeit von ruckartigen Bewegungen minimieren möchten, sollten Sie eine Bewegungsunschärfe ausprobieren.

0

Sie müssen in Bezug auf die Winkelgeschwindigkeit darüber nachdenken. Sie berechnen den Winkel Theta als Zeit * Geschwindigkeit, die keinen Sinn macht, wenn Geschwindigkeit der konventionelle Sinn der Geschwindigkeit ist, dh Entfernung/Zeit. Die Winkelgeschwindigkeit ist Winkel/Zeit (dh Radianten/Sekunde oder Grad/Sekunde). Konventionelle Geschwindigkeit ist der Abstand zwischen Anfangs- und Endpunkt/Zeit nach dem Anwenden der Winkelgeschwindigkeit.

3

Für einen glatten Anstieg der Winkelgeschwindigkeit, müssen Sie eine Winkelbeschleunigung

x = radius * cos (theta)
y = radius * sin (theta)

theta (t) = hinzuzufügen theta (0) + omega (0) * t + 0,5 * alpha * t^2

wo t ist die Zeit, Theta (0) ist die Winkelposition zum Zeitpunkt 0, omega (0) ist die Winkelgeschwindigkeit zum Zeitpunkt 0 (wäre gleich Ihrem Geschwindigkeitsparameter) und Alpha ist der Winkelbeschleunigungsparameter, den Sie wählen, um etwas passendes zu sein.

+1

Dies setzt voraus, dass alpha konstant bleibt. Natürlich könntest du es stückweise-kontinuierlich machen - führe es bis zu einer Zeit T fort und initialisiere es dann in diesem Zustand. –

0
x = center_x + radius * sin(time * speed + offset) 
y = center_y + radius * cos(time * speed + offset) 

def change_speed(new_speed): 
    offset = time * (speed - new_speed) + offset 
    speed = new_speed 

offset kann bei 0 oder wirklich einen beliebigen Wert beginnen ... es wird benutzt, um Kontinuität zu wahren, als

time * old_speed + old_offset == time * new_speed + new_offset 
4

sagte Sie es selbst: Sie die Winkelgeschwindigkeit-ändern möchten. Jetzt wird die Änderung der Winkelgeschwindigkeit in der realen Welt durch die Winkelträgheit eines Objekts begrenzt. Dies bedeutet, dass es nicht in Schritten von 1 "diskret" gehen kann.

Vielmehr ist die Winkelgeschwindigkeit das Integral der Winkelbeschleunigung. Der Winkel Position ist das Integral der Winkelgeschwindigkeit.

So für eine konstante Winkelbeschleunigung, können Sie

Geschwindigkeit (t) = t * acc + vel [t = 0] sagen.

und

Winkel (t) = t 2 * acc/2 + VEL [t = 0] * t + Winkel [t = 0].

Dann können Sie Ihre kartesische Position mit dem Sinus und Cos des Winkels berechnen.

Die Winkelbeschleunigung kann variieren (ziemlich) diskret.

+0

Das ist eine großartige Erklärung dessen, was ich falsch gemacht habe, danke, dass du mir geholfen hast, das zu verstehen! – Kai

2

time * speed 

Wie weit der Kreis, um anzuzeigen, verwenden gereist ist einfach falsch. Es macht nur Sinn, wenn sich die Geschwindigkeit niemals ändert.

Stattdessen müssen Sie die zurückgelegte Strecke in einer Variablen speichern und dann die Variable um einen Betrag erhöhen, der von der aktuellen Geschwindigkeit und dem Zeitintervall seit der letzten Zeichnung abhängt.

Die Vorschläge, andere Beschleunigung zu verwenden, sind auch gut. Versuchen Sie etwas wie

v = v + a; 
d = d + delta * v; 

x = center_x + radius * sin(d) 
y = center_y + radius * cos(d) 
+0

'time * speed' macht manchmal Sinn, wenn Ihre Zeitschritte nicht immer gleich sind (zB wenn Sie Framespip). – ephemient

+0

Sie haben die richtige Idee. Vielleicht möchten Sie einen variablen Zeitschritt haben, wie in d + = v * delta; v + = a * delta; Das ist natürlich Eulers Integration. Runge-Kutta wäre genauer. –