Timebased Movement: Unterschied zwischen den Versionen
Flo (Diskussion | Beiträge) (→Absolute Genauigkeit per Hardware: auch hier das gleiche) |
Flo (Diskussion | Beiträge) (→Prinzip: Abschnitt stark verlängert.) |
||
Zeile 1: | Zeile 1: | ||
== Kurz-Beschreibung == | == Kurz-Beschreibung == | ||
'''Timebased Movement''' sorgt dafür, dass die Bewegungsgeschwindigkeiten nicht vom CPU-/Renderspeed abhängen. | '''Timebased Movement''' sorgt dafür, dass die Bewegungsgeschwindigkeiten nicht vom CPU-/Renderspeed abhängen. | ||
+ | |||
+ | |||
+ | |||
== Prinzip == | == Prinzip == | ||
− | + | Nehmen wir an wir möchten einen Ball darstellen der sich mit konstanter Geschwindigkeit vom linken Bildschirmrand zum rechten Bildschirmrand bewegt. | |
+ | |||
+ | Das erste Bild wird den Ball ganz links zeigen. Auf dem nächsten Bild wird der Ball ein stück weiter sein, die Frage ist nur wie weit? Die länge der Strecke die der Ball zurücklegen muss legen wir nun mal willkürlich auf 1 Längeneinheit (kurz: LE) fest. Die Strecke soll er in 5 Sekunden zurück legen. | ||
+ | |||
+ | Ein Rechner A braucht 1 Sekunde um 1 Bild zu Berechnen. Um das gewünschte Ergebnis zu erreichen müssten wir den Ball nach jedem Bild 0.2 Felder weiterbewegen. | ||
+ | |||
+ | In einer Sekunde hätten wir also folgende Bilder: | ||
+ | * Bild 0: Ball Position: 0.0 | ||
+ | * Bild 1: Ball Position: 0.2 (weiterbewegt um 0.2 LE in 1.0 Sekunden) | ||
+ | * Bild 2: Ball Position: 0.4 (weiterbewegt um 0.2 LE in 1.0 Sekunden) | ||
+ | * Bild 3: Ball Position: 0.6 (weiterbewegt um 0.2 LE in 1.0 Sekunden) | ||
+ | * Bild 4: Ball Position: 0.8 (weiterbewegt um 0.2 LE in 1.0 Sekunden) | ||
+ | * Bild 5: Ball Position: 1.0 (weiterbewegt um 0.2 LE in 1.0 Sekunden) | ||
+ | |||
+ | Ein Rechner B braucht nur 0.5 Sekunden um ein Bild zu berechnen. | ||
+ | * Bild 0: Ball Position: 0.0 | ||
+ | * Bild 1: Ball Position: 0.1 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 2: Ball Position: 0.2 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 3: Ball Position: 0.3 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 4: Ball Position: 0.4 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 5: Ball Position: 0.5 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 6: Ball Position: 0.6 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 7: Ball Position: 0.7 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 8: Ball Position: 0.8 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 9: Ball Position: 0.9 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | * Bild 10: Ball Position: 1.0 (weiterbewegt um: 0.1 LE in 0.5 Sekunden) | ||
+ | |||
+ | Bei dem einen Rechner muss der Ball bei jedem Bild um 0.2 LE bewegt werden, beim andern Rechner nur 0.1 LE pro Bild. Tut man dies nicht, bewegt sich der Ball zu schnell oder zu langsam. | ||
+ | |||
+ | Doch woher weiß man nun wie weit man seinen Ball auf den jeweiligen Rechner pro Bild bewegen muss? | ||
+ | |||
+ | In unserem Beispiel bewegt sich der ball mit der konstanten Geschwindigkeit von 0.2 LE pro Sekunde. Mit folgender Formel können wir bei konstanter Geschwindigkeit die neue Position berechnen: | ||
+ | |||
+ | neue_Position = Geschwindigkeit*vergangene_Zeit + alte_Position | ||
+ | |||
+ | Wir brauchen also nur eine Geschwindigkeit festlegen und messen wieviel Zeit vergangen ist um die neue Position zu berechnen zu können. | ||
+ | |||
+ | Wohlgemerkt gilt diese Formel nur wenn sich das Objekt mit konstanter Geschwindigkeit fortbewegt. | ||
== Berechnung == | == Berechnung == |
Version vom 18. August 2006, 19:56 Uhr
Inhaltsverzeichnis
Kurz-Beschreibung
Timebased Movement sorgt dafür, dass die Bewegungsgeschwindigkeiten nicht vom CPU-/Renderspeed abhängen.
Prinzip
Nehmen wir an wir möchten einen Ball darstellen der sich mit konstanter Geschwindigkeit vom linken Bildschirmrand zum rechten Bildschirmrand bewegt.
Das erste Bild wird den Ball ganz links zeigen. Auf dem nächsten Bild wird der Ball ein stück weiter sein, die Frage ist nur wie weit? Die länge der Strecke die der Ball zurücklegen muss legen wir nun mal willkürlich auf 1 Längeneinheit (kurz: LE) fest. Die Strecke soll er in 5 Sekunden zurück legen.
Ein Rechner A braucht 1 Sekunde um 1 Bild zu Berechnen. Um das gewünschte Ergebnis zu erreichen müssten wir den Ball nach jedem Bild 0.2 Felder weiterbewegen.
In einer Sekunde hätten wir also folgende Bilder:
- Bild 0: Ball Position: 0.0
- Bild 1: Ball Position: 0.2 (weiterbewegt um 0.2 LE in 1.0 Sekunden)
- Bild 2: Ball Position: 0.4 (weiterbewegt um 0.2 LE in 1.0 Sekunden)
- Bild 3: Ball Position: 0.6 (weiterbewegt um 0.2 LE in 1.0 Sekunden)
- Bild 4: Ball Position: 0.8 (weiterbewegt um 0.2 LE in 1.0 Sekunden)
- Bild 5: Ball Position: 1.0 (weiterbewegt um 0.2 LE in 1.0 Sekunden)
Ein Rechner B braucht nur 0.5 Sekunden um ein Bild zu berechnen.
- Bild 0: Ball Position: 0.0
- Bild 1: Ball Position: 0.1 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 2: Ball Position: 0.2 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 3: Ball Position: 0.3 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 4: Ball Position: 0.4 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 5: Ball Position: 0.5 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 6: Ball Position: 0.6 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 7: Ball Position: 0.7 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 8: Ball Position: 0.8 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 9: Ball Position: 0.9 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
- Bild 10: Ball Position: 1.0 (weiterbewegt um: 0.1 LE in 0.5 Sekunden)
Bei dem einen Rechner muss der Ball bei jedem Bild um 0.2 LE bewegt werden, beim andern Rechner nur 0.1 LE pro Bild. Tut man dies nicht, bewegt sich der Ball zu schnell oder zu langsam.
Doch woher weiß man nun wie weit man seinen Ball auf den jeweiligen Rechner pro Bild bewegen muss?
In unserem Beispiel bewegt sich der ball mit der konstanten Geschwindigkeit von 0.2 LE pro Sekunde. Mit folgender Formel können wir bei konstanter Geschwindigkeit die neue Position berechnen:
neue_Position = Geschwindigkeit*vergangene_Zeit + alte_Position
Wir brauchen also nur eine Geschwindigkeit festlegen und messen wieviel Zeit vergangen ist um die neue Position zu berechnen zu können.
Wohlgemerkt gilt diese Formel nur wenn sich das Objekt mit konstanter Geschwindigkeit fortbewegt.
Berechnung
Der Faktor um wieviel sich alles zu bewegen hat, kann zum Beispiel über die, seit der letzen Abfrage vergangen, Zeit ermittelt werden.
Allgemein:
VergangeneZeit:= (Zeit1-Zeit0)/Frequenz;
Diese vergangende Zeit(eigentlich immer in Sekunden oder Sekundenbruchteilen) ist nun der ZeitFaktor, den wir nutzen um zu bestimmen um wieviel sicht etwas bewegt.
Die Bewegung dann:
Position := Position + Geschwindikeit*VergangeneZeit;
Möglichkeiten
Millisekunden genau unter Windows
Die wohl einfachste Möglichkeit unter Windows so etwas zu realisieren besteht darin mit Hilfe von GetTickCount die Zeit (in Millisekunden) seit dem letzen Windows-Start zu ermitteln.
//Benötigte Variablen var BerechnungsZeit:LongWord; procedure BeimStart;//Was hier drinnen steht sollte zum Start ausgeführt werden begin BerechnungsZeit := GetTickCount(); end; procedure BerechnungsCheck;//Alle nötigen Berechnungen durchführen const Frequenz=1000;//Durch Windows festgelegt var AktuelleZeit:LongWord; begin AktuelleZeit := GetTickCount(); Berechne((AktuelleZeit - BerechnungsZeit) /Frequenz); BerechnungsZeit := AktuelleZeit; end; procedure Berechne(ZeitFaktor:Double); begin {Alle Berechnungen stehen hier } //z.B Pos.X := Pos.X + Speed.X*ZeitFaktor; if Pos.X > 20 then Pos.X := 0; end;
Absolute Genauigkeit per Hardware
Man kann auch die Hardware zur Zeitmessung nutzen um so noch genauere Ergebnisse zu erziehlen. Es kann jedoch theoretisch sein(auch jetzt noch?), dass diese nicht zur verfügung steht.
//Benötigte Variablen var BerechnungsZeit:Int64; Frequenz:Int64; procedure BeimStart;//Was hier drinnen steht sollte zum Start ausgeführt werden begin if not QueryPerformanceFrequency(Frequenz) then//Frequenz ermitteln raise Exception.create('Kein Hardware Timer vorhanden'); QueryPerformanceCounter(BerechnungsZeit);//Aktuelle Zeit ermitteln end; procedure BerechnungsCheck;//Alle nötigen Berechnungen durchführen var AktuelleZeit:Int64; begin QueryPerformanceCounter(AktuelleZeit); Berechne((AktuelleZeit - BerechnungsZeit) /Frequenz); BerechnungsZeit := AktuelleZeit; end; procedure Berechne(ZeitFaktor:Double); begin {Alle Berechnungen stehen hier } //z.B Pos.X := Pos.X + Speed.X*ZeitFaktor; if Pos.X > 20 then Pos.X := 0; end;