2011-01-15 16 views
2

Um Objekte mit einer variablen Zeitschritt bewegen muss ich nur tun:variable Zeitschritt und Beschleunigung

ship.position += ship.velocity * deltaTime; 

Aber wenn ich versuche, dies mit:

ship.velocity += ship.power * deltaTime; 

ich unterschiedliche Ergebnisse mit unterschiedlichen Zeitschritten erhalten . Wie kann ich das beheben?

EDIT:

Ich Modellierung ein Objekt in den Boden an einer Achse mit einer einzigen festen Kraft (Schwerkraft), die auf ihn fällt.

+0

Wie unterscheiden sich die Ergebnisse? Wenn Sie den Zeitschritt auf eine sehr kleine Zahl einstellen, sollten Sie gute Ergebnisse erzielen. Funktioniert das für dich? Bitte Code anzeigen? Es ist schwer dir zu helfen. – nielsle

+0

@nielsle Ich habe hier einen Testfall gemacht: http://paste.ubuntu.com/554854/ Das scheint perfekt mit 1ms Zeitschritt und 100ms zu funktionieren. Also habe ich keine Ahnung, was ich vor –

Antwort

7
ship.position = ship.position + ship.velocity * deltaTime + 0.5 * ship.power * deltaTime^2; 
ship.velocity += ship.power * deltaTime; 

http://www.ugrad.math.ubc.ca/coursedoc/math101/notes/applications/velocity.html

Die Geschwindigkeit Teil Ihrer Gleichungen korrekt ist, und sie müssen in jedem Zeitschritt beide aktualisiert werden.

Dies alles setzt voraus, dass Sie eine konstante Leistung (Beschleunigung) über die DeltaTime haben, wie von belisarius angegeben.

+0

falsch gemacht habe, aber Sie nicht ship.velocity ändern? –

+0

Die Geschwindigkeitsgleichung in der Frage ist korrekt, es sei denn, die Beschleunigung ist über DeltaTime nicht konstant. –

+0

Brian Ich kann meine Köpfe nicht um Schiff wickeln. Geschwindigkeit ändert sich nicht. Könnten Sie sich meine derzeitige Funktion ansehen und sehen, was ich meine? http://paste.ubuntu.com/554516/ –

1

Dies ist ein inhärentes Problem, das versucht, numerisch zu integrieren. Es wird ein Fehler angezeigt. Durch das Senken von Delta erhalten Sie genauere Ergebnisse, aber mehr Berechnungen sind erforderlich. Wenn Ihre Power-Funktion integrierbar ist, könnten Sie das versuchen.

+0

Oder Sie können bei größeren Zeitschritten bleiben und ein Integrationsschema höherer Ordnung verwenden (sagen Sie Runga-Kutta 2. oder höher) .... – dmckee

4

Was Sie (mathematisch) tun, ist Integrale zu bewerten. Im ersten Fall ist die lineare Näherung genau, da Sie eine lineare Beziehung haben.

Im zweiten Fall haben Sie mindestens eine Parabel, also sind Ihre Ergebnisse nur ungefähr. Sie können bessere Ergebnisse erzielen, wenn Sie eine kleinere deltaTime verwenden oder die reellen Integralgleichungen verwenden, falls verfügbar.

bearbeiten

Antwort Brians ist richtig, solange die ship.power immer konstant bleibt, und Sie neu berechnen ship.velocity bei jedem Schritt. Es ist in der Tat die Integralgleichung für eine konstante beschleunigte Bewegung.

0

Sie können Verlet integration verwenden, um Position und Geschwindigkeit des Objekts zu berechnen. Beschleunigung können Sie aus a = m * F berechnen, wobei m Masse und F die Kraft ist. Dies ist einer der einfachsten Algorithmen

1

Ihre Simulation löst numerisch die Bewegungsgleichung für einen einzelnen Massenpunkt. Die Zeitdiskretisierung, die Sie verwenden, heißt "Euler method", und es kann gezeigt werden, dass sie keine Energie speichert (wie es die genaue Lösung in irgendeiner Weise tut). Eine viel bessere und doch einfache Art, Bewegungsgleichungen zu lösen, ist die "leapfrog integration".

+0

Ich denke, dass es schwer ist, aus seinem Code zu sehen, wenn er bereits den Leapfrog benutzt Methode. Wir brauchen mehr Code, bevor wir das beurteilen können. – nielsle

+0

@nielsle: Er ist offensichtlich nicht - es würde den Fall der konstanten Beschleunigung genau lösen. –

+0

Die Gleichungen für die Leapfrog-Integration sind x [i + 1] = x [i] + v [i + 1/3] * dt – nielsle

0

In Ihrem Code verwenden Sie setInterval (moveBoxes, 20), um die Boxen zu aktualisieren, und anschließend verwenden Sie (new Date()). GetTime()), um deltaT zu berechnen. Dies ist etwas redundant, weil Sie die Zahl 20 direkt für die Berechnung von deltaT hätten verwenden können.

Es ist besser, den Code so zu schreiben, dass Sie während jedes Zeitschritts genau den gleichen Wert für deltaT verwenden. (Mit anderen Worten, deltaT sollte nicht vom Wert von (new Date()) abhängen. GetTime())). Auf diese Weise wird Ihr Code reproduzierbar und es ist einfacher für Sie, Komponententests zu schreiben.

Betrachten wir eine Situation, in der der Browser für kurze Zeit weniger CPU-Zeit zur Verfügung hat. In dieser Situation möchten Sie langfristige Auswirkungen auf die Dynamik vermeiden. Wenn die CPU-Zeit knapp ist, möchten Sie, dass der Browser in einen Zustand zurückkehrt, der von der kurzen CPU-Zeit nicht betroffen ist. Dies erreichen Sie, indem Sie in jedem Zeitschritt den gleichen Wert von deltaT verwenden.

Übrigens. Ich denke, dass der folgende Code

if(box.x < 0) { 
     box.x = 0; 
     box.vx *= -1; 
    } 

konnte mit

if(box.x < 0) { 
     box.x *= -1 ; 
     box.vx *= -1; 
    } 

Viel Glück mit dem Projekt ersetzt werden - und bitte Codebeispiele in der ersten Version Ihrer Frage nächste Mal, wenn Sie fragen, sind :-)

+0

Ich fand, dass auf einigen Browsern (Internet Explorer) das Zeichnen der beweglichen Elemente langsamer als das Intervall war. Daher die Notwendigkeit für variable Zeitschritte. –

+0

Ich sehe dich Punkt. In diesem Fall würde ich lieber einen Code hinzufügen, der die Langsamkeit des Browsers erkennt und deltaT auf einen neuen konstanten Wert erhöht. Wenn die gesamte CPU-Zeit für das Zeichnen der Grafiken aufgewendet wird, können Sie Ihren Differentialgleichungslöser möglicherweise zwischen den einzelnen Aktualisierungen der Grafiken mehrere Zeitschritte ausführen lassen. – nielsle