Nichtlineare Bewegung

Einstiegsfragen, Mathematik, Physik, künstliche Intelligenz, Engine Design
Antworten
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Zudomon »

knivil hat geschrieben:
Aber wenn die FPS steigen, dann ist die Bewegung natürlich verfälscht.
Wie waere es denn erstmal mit einem FPS unabhaengigen Gameloop?
Im Notfall wird mir da nichts anderes übrig bleiben. Sollte man ja für Physikberechnungen und dergleichen eigentlich auch machen.
Krishty hat geschrieben:Edit: Gerade implementiert. Bei einem Faktor von 0.2 ist es SO weich, dass es schon fast wehtut. Bei 0.5 ist alles großartig glatt.
Weich bekomme ich das ja auch, aber ebend nicht FPS unabhängig, da liegt das Hauptproblem.
Benutzeravatar
Krishty
Establishment
Beiträge: 8240
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Krishty »

Zudomon hat geschrieben:Weich bekomme ich das ja auch, aber ebend nicht FPS unabhängig, da liegt das Hauptproblem.

Code: Alles auswählen

// Die virtuelle Rotation deiner Kamera.
const float l_fVirtualXRotation = …;
const float l_fVirtualYRotation = …;

// In einer Sekunde soll sich die Kamera zu 99% an die virtuelle Position (die Zielposition) anpassen.
const float l_fCameraInertiaPerSecond = 1.0f - 0.99f;

// Füllst du mit der erwarteten Zeit dieses Frames, in Sekunden.
const float l_fFrameTimeInSeconds = …;

// Gibt an, wie stark sich die Kamera ergo innerhalb dieses Frames an die Zielposition anpasst.
const float l_fThisFramesCameraInertia = ::pow(l_fCameraInertiaPerSecond, l_fFrameTimeInSeconds);

// Jetzt bloß noch wie gehabt interpolieren …
const float l_fXRotation = (l_fVirtualXRotation * (1.0f - l_fThisFramesCameraInertia)) + (l_fXRotation * l_fThisFramesCameraInertia);
const float l_fYRotation = (l_fVirtualYRotation * (1.0f - l_fThisFramesCameraInertia)) + (l_fYRotation * l_fThisFramesCameraInertia);
Habe es mit 40 und vier fps getestet.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Zudomon »

Stimmt, so ist das weich und Zeitunabhängig! Super! Danke für den Code!

===== NACHTRAG =====
Wenn man das so für die Position nimmt, klappt das auch gut.
Das einzigste, was jetzt noch rein müsste, wäre, dass man sich schneller bewegt, wenn man schneller die Maus bewegt.
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Helmut »

Wahrscheinlich willst du das jetzt nicht hören, aber ich würde solche Sachen nicht fps unabhängig programmieren. Zum einen ist es ziemlich anstrengend und aufwendig (manchmal sogar unmöglich) sowas so zu programmieren, zum anderen verlierst du so den Determinismus und erschwerst zB die Kollisionsberechnungen erheblich.
Eine feste FPS mit Frameskip hat eigentlich kaum Nachteile finde ich:)

Ciao
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Nichtlineare Bewegung

Beitrag von eXile »

IMHO gibt es gerade bei Multiplayerspielen häufig eine Obergrenze (z.B. bei Doom 3 60 Hz). Das liegt daran, dass gerade wenn neben Physik und KI auch noch Netzwerk mit reinspielen, ganz komische Nebeneffekte auftreten können.
Benutzeravatar
Krishty
Establishment
Beiträge: 8240
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Krishty »

Zudomon hat geschrieben:Das einzigste, was jetzt noch rein müsste, wäre, dass man sich schneller bewegt, wenn man schneller die Maus bewegt.
Das müsste aber selbst bei simpelsten Implementierungen der Mausbewegungen der Fall sein … wie berechnest du denn die Rotation/Position aus der Mausbewegung?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Zudomon »

Krishty hat geschrieben:
Zudomon hat geschrieben:Das einzigste, was jetzt noch rein müsste, wäre, dass man sich schneller bewegt, wenn man schneller die Maus bewegt.
Das müsste aber selbst bei simpelsten Implementierungen der Mausbewegungen der Fall sein … wie berechnest du denn die Rotation/Position aus der Mausbewegung?
Klar, an sich ist das ja drin... also wenn man in einem Frame die Maus 10 Pixel bewegt, dann ist sind es auch nur 10 Einheiten, die bewegt werden... bei 20 Pixel ebend dann 20 Einheiten...
Was ich jetzt da noch gerne hätte wäre, das wenn man innerhalb von 0.1 Sekunden die Maus 10 Pixel bewegt, dass das z.B. dann nur halb so weit ist, wie wenn man die Maus 10 Pixel innerhalb von 0.05 Sekunden bewegt.

Vielleicht ist das alles übertrieben, das mal so exakt zu erörtern, aber ich würde es gerne mal "richtig" implementieren. ;)

Gruß
Zudomon
Benutzeravatar
Krishty
Establishment
Beiträge: 8240
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Krishty »

Achso, jau, das ist dann das, was in den meisten Games als nichtlineare Bewegung tituliert wird … ganz einfach :)
Du berechnest aus der Mausbewegung und der aktuellen Frame-Zeit, um wieviel Einheiten (Grad oder Bogenmaß oder Meter) sich die Maus pro Sekunde bewegt … den Wert potenzierst du dann (Quadrat müsste reichen, aber kannst gerne experimentieren, interessiert mich auch) … multiplizierst dann wieder mit der Frame-Zeit und das ist dann die „neue“ Mausbewegung, mit der du im gewohnten Mechanismus weiter rechnen kannst.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Zudomon »

Okay :D
Ich werde mich da gleich nochmal rannsetzen...
Krishty hat geschrieben:...als nichtlineare Bewegung tituliert wird.
Da bin ich ja froh, dass der Threadname dann doch nicht so falsch gewählt war!

Ich schätze mal, um die Mauswegung dann richtig zu erfassen, sollte man dann so einen fließenden Mittelwert ( oder wie das heißt ) einsetzen...
Benutzeravatar
Krishty
Establishment
Beiträge: 8240
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Krishty »

Ja, wenn bei hohen Frameraten die Mausbewegung immer nurnoch entweder null oder ein Pixel groß ist, wird das Verhalten wieder linear … dann über mehrere Frames zählen. Bis 100fps sollte es aber gut funktionieren.

So extrem wie Helmut, dass man mit einer fixen Framerate arbeiten soll, sehe ich es zwar nicht – aber Bildwiederholraten über der Monitor-Aktualisierungsrate sind imho von Spezialanwendungen und Tests abgesehen Schwachsinn. Von daher würde ich den Mehraufwand für das Abdichten so hoher Framerates überhaupt nicht eingehen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Zudomon »

Irgendwie habe ich das Gefühl, ich bin zu dumm.
Also den gleitenden Mittelwert habe ich nun... gezählt wird das mittel der Differenz der Maus über 0.1 Sekunden. Nun das ganze zum Quadrat und diesen Wert mit der Mausverschiebung multiplizieren. Das funktioniert wunderbar... bei 1000 FPS... bei 100 ist wirkt die exponentiale Komponente viel stärker... wenn ich nun noch einfach das TimeDelta rein multipliziere bringt das auch nichts...

Bei der normalen Mausverschiebung darf man das Timedelta nicht mit rein multiplizieren, weil das durch die Art der Datenerfassung schon passiert ist. Wenn man nun den Mittelwert über 0.1 Sekunden berechnet, ist das ja auch schon eine entsprechende Integration und vom Gefühl her würde ich sagen, dass man da ebenfalls kein TimeDelta reinmultiplizieren darf.
Benutzeravatar
Krishty
Establishment
Beiträge: 8240
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Krishty »

Du hast es also doch so implementiert … sind mehr als 100 fps denn wirklich soooo wichtig? Und du bist auch noch irgendwie total mit den Größen durcheinander gekommen …

Also, von Anfang an:

Du berechnest den gleitenden Mittelwert der Mausbewegung. Der Wert liegt dann – wie jede Mausbewegung – in Pixeln vor. (Floats benutzen!)

Durch die Division durch die Framezeit berechnest du die aktuelle Bewegungsgeschwindigkeit der Maus in Pixeln÷Sekunden.

Dann korrigierst du diesen Wert nach deinen Vorlieben (z.B. quadrieren).

Das multiplizierst du wiederum mit der Rotationsempfindlichkeit des Betrachters in Bogenmaß÷Pixel. Das Ergebnis ist die Rotation des Betrachters in Bogenmaß÷Sekunde.

Diesen Wert multiplizierst du mit der aktuellen Framezeit. Das Ergebnis (Bogenmaß) ist die Rotation, die du zu der des vorherigen Frames aufaddierst (bzw zur „virtuellen“ Rotation, wenn man unseren Glättungs-Mechanismus berücksichtigt).

Da wird nichts quadriertes mit der Mausbewegung multipliziert. Darum bin ich übrigens dafür, Dimensionsanalyse standardmäßig allen Programmiersprachen hinzuzufügen … ;)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Zudomon
Establishment
Beiträge: 2254
Registriert: 25.03.2009, 07:20
Kontaktdaten:

Re: Nichtlineare Bewegung

Beitrag von Zudomon »

Danke für die ausführliche Beschreibung. Ich will es noch nicht beschwören, aber ich glaube, jetzt funktioniert es.
Allerdings gibt es da noch ein paar Stolperfallen:

Der gemittelte Mittelwert, da darf man nicht durch die Anzahl der Samples teilen ( was mein Problem war ). Also speichert sich alle Datenwertepaare XY und den Zeitstempel, am besten in einem Ringarray. Dann durchläuft man dieses und summiert alle XY Paare, die kleiner als der gewünschte Zeitbereich ist.
Außerdem summiert man die Länge aller XY Paare, um diese "Beschleunigung" nicht Richtungsabhängig zu haben.

Der 2D Vektor der summierten Paare wird normalisiert, damit man eine gemittelte Richtung der Mausbewegung bekommt. Der Längenwert wird wie Krishty schon sagte,
erstmal durch die betrachtete Zeit geteilt, um die Änderung auf Sekunden um zu rechnen, und dann den Bedürfnissen angepasst... z.B. quadriert und skaliert.
Anschließend wird die Länge auf das TimeDelta des Frames runterskaliert und mit der gemittelten Richtung multipliziert.

Das Ergebnis dann auf die echte Rotation aufaddiert. Die virtuelle Rotation kann dann durch die vorgeschlagene weiche interpolation ermittelt werden.
Danke für eure Hilfe!! Ich probier das jetzt noch ein wenig aus, in der Hoffnung, diesmal endlich am Ziel zu sein. :D

Für alle, die sich fragen, warum denn diese exponentielle Bewegung: Ich will dadurch erreichen, dass man durch Rotation jeden Punkt mit der Maus ansteuern kann... was bei einer linearen Übertragung nicht Möglich ist.

Edit: Funktioniert nach ein paar weiteren Tests auf jeden Fall immernoch stabil. Bei 100, wie 1000 FPS alles super! Auch für die Postionierung der Kamera ist geeignet. Habe übrigens erstmal einen kleinen Wert von 1.25 als Exponent genommen. Cool ist auch das nun automatisch entstehende MotionBlur durch die flüssige Bewegung. :)
Antworten