Frameunabhängig programmieren

Übersicht BlitzBasic FAQ und Tutorials

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

 

IonPainter

Betreff: Frameunabhängig programmieren

BeitragDo, Mai 06, 2004 14:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Frameunabhängig programmieren
=============================

ein Tutorial von IonPainter



1) Warum Frameunabhängig programmieren?
=======================================

Wer Frameunabhängig programmiert, stellt sicher das auf jedem Computer, und sei er auch noch so langsam, sein Spiel mit immer gleichbleibender Geschwindigkeit läuft. Das ist besonders bei Multiplayerspielen wichtig die syncron laufen müssen.

2) Wie programmiere ich Frameunabhängig?
========================================

Es gibt viele Moglichkeiten, von abenteuerlichen FPS kalkulationen mit denen dann dividiert wird bis hin zu RenderWorld Parametern, u.s.w. Das ist eigentlich alles zu kompliziert, es geht auch viel einfacher: Man misst die Zeit die ein Schleifendurchlauf braucht und multipliziert sämtliche Bewegungsabläufe mit diesem Wert.

Beispiel:

Code: [AUSKLAPPEN]

Graphics 640, 480
SetBuffer Backbuffer()

While Not Keyhit(1)
StartZeit = Millisecs()
Cls

;Bewegen des Quadrats
Position = Position + (1 * SchleifenZeit)

;Wenn Quadrat ganz Rechts dann setze Quadrat nach ganz links
if Position > (640 - 16) then Position = 0

;Zeichnen des Quadrates
Rect Position, (240 - 8), 16, 16

Flip 0 ;60FPS Begrenzung ausschalten

SchleifenZeit = Millisecs() - Startzeit
Wend


Das Rechteck bewegt sich relativ schnell und flüssig von Links nach Rechts. Um jetzt zu testen ob es wirklich Frameunabhängig läuft, verlangsamen wir die Ausführung.

Code: [AUSKLAPPEN]

Graphics 640, 480
SetBuffer Backbuffer()

While Not Keyhit(1)
StartZeit = Millisecs()
Cls

;Bewegen des Quadrats
Position = Position + (1 * SchleifenZeit)

;Wenn Quadrat ganz Rechts dann setze Quadrat nach ganz links
if Position > (640 - 16) then Position = 0

;Zeichnen des Quadrates
Rect Position, (240 - 8), 16, 16

Delay Rand(25)

Flip 0 ;60FPS Begrenzung ausschalten

SchleifenZeit = Millisecs() - Startzeit
Wend


Hier werden zufällig kleine Pausen bis 25 Millisekunden in die Hauptschleife eingefügt. Trotzdem bewegt sich das Quadrat zwar ruckelnd, aber gleich schnell! Ganz schlaue (und faule) schreiben sich noch eine Funktion:

Code: [AUSKLAPPEN]

Global SchleifenZeit

Graphics 640, 480
SetBuffer Backbuffer()

While Not Keyhit(1)
StartZeit = Millisecs()
Cls

;Bewegen des Quadrats
Position = Position + SZ#(1)

;Wenn Quadrat ganz Rechts dann setze Quadrat nach ganz links
if Position > (640 - 16) then Position = 0

;Zeichnen des Quadrates
Rect Position, (240 - 8), 16, 16

Delay Rand(25)

Flip 0 ;60FPS Begrenzung ausschalten

SchleifenZeit = Millisecs() - Startzeit
Wend

Function SZ#(Bewegung)

   Wert# = Bewegung * SchleifenZeit
   Return Wert#

End Function


Nun braucht man nur noch SZ#(1) statt 1 * SchleifenZeit zu Tippen. Ausserdem bleibt der Code übersichtlicher. Hoffe mal das nun mehr BB-Programmierer das eigentlich so einfache frameunabhängige Programmieren praktizieren. Anregungen, Kritik, u.s.w. bitte hier Posten.

Credit Me,
IonPainter
==========

Keimax

BeitragDo, Sep 09, 2004 10:31
Antworten mit Zitat
Benutzer-Profile anzeigen
IonPainter zeig mir mal wie ich eine flüssige Bewegung von Links nach Rechts hinbekomme.
Mit Flip 0 geht das nicht.
Also bei mir auf jedenfall. Vielleicht liegts ja an meinem Monitor Wink
Erst wenn ich Flip auf 1 stelle siehts halbwegs vernünftig aus.

cu
XP3000, FX6600, 1024DDR, BB2d @ W2k,
- > Diesen Text bitte nicht beachten <-

Tobchen

BeitragDo, Sep 09, 2004 18:19
Antworten mit Zitat
Benutzer-Profile anzeigen
So große Sprünge können einem die Kollision richtig versauen. Kann man das anders machen? Ich hatte immerCode: [AUSKLAPPEN]
If TolleZeit + 25 < MilliSecs() Then ...
Und diese Methode kann man auch ziemlich vergessen, wenn die FPS nicht viel sind.
Tobchen - die Welt von Tobi!

Freeman

BeitragDo, Sep 09, 2004 22:08
Antworten mit Zitat
Benutzer-Profile anzeigen
warum nutzt man hier nich die Timer funktion ? also createTimer und dann waittimer? damit kann man doch die fps rate auf nem bestimmten niveau halten, zumindest so das es nicht mehr überschritten wird...und ma ganz ehrlich, würdest du ne delay(time) funktion in deine schleife reinbaun? ich glaub wohl nich....


FrEeMaN
 

walski

Ehemaliger Admin

BeitragDo, Sep 09, 2004 22:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Bei der frameabhängigen Programmierung geht es ja darum, hohe Rechnergeschwindigkeiten zur genaueren, flüssigeren Berechnung der Szenen zu nutzen, ohne dass es schneller abläuft als auf nem langsamen Recher.

Ein Begrenzen der Framerate auf beispielsweise 100 oder meinetwegen auch nur 40 ist schön und gut, aber warum soll der 3GHZ, Radeon 9800 Pro XTR GT SuperDuper [HierBeliebigesWichtigklingendesSuffixEinsetzen] Besitzer nicht auch seine Hardware nutzen können, indem er halt 900 Frames pro Sekunde rendert und alles schöööööön flüssig von der Hand geht? Oder andresrum, was machst du mit Usern die wirklich an der "40-FPS"-Grenze kratzen und bei denen sich gerade im Hintergrund ICQ zu Wort meldet... läuft das Spiel dann auf einmal langsamer... Im Netzwerk wäre dass dann doof Wink

Das nur zur Daseinsberechtigung des Ganzen.

walski
buh!

Bura.Tino

BeitragDi, Aug 30, 2005 12:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Sache ist doch die, daß das menschliche Augen 24 Frames pro Sekunde braucht um es nicht mehr als einzelne Bilder, sondern als Animation wahrzunehmen.
Deswegen kann man ein Spiel doch locker auf 30 FPS reduzieren. Auch wenn der Rechner 900 FPS bringen würde, so macht es doch gar keinen Sinn !
Für das menschliche Auge macht es nicht den geringsten Unterschied, ob das nun 30 oder 900 FPS sind.

Fazit: Flüssig ist Flüssig. Alles andere ist egal.
 

MegaTefyt

BeitragDi, Aug 30, 2005 13:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ist definitiv falsch. Selbst wenn man (evt.!) keinen Unterschied sieht ist meist das Spielgefühl ein anderes, man spürt FPS-Unterschiede. Daher ist von einer 30 (oder weniger) FPS-Begrenzung abzuraten.

Im übrigen ist es sinnvoll sich eine Zusatzvariable für die MilliSecs() anzulegen, z.B. PAUSETIME%. Sprich überall wo MilliSecs() benutzt wird macht man ein MilliSecs() - PAUSETIME draus. Warum? Ganz einfach, die meisten wollen sicher eine Pause- (oder Menu-)Funktion in ihrem Spiel haben. Dabei läuft natürlich MilliSecs() weiter, obwohl das eigentliche Spiel gar nicht läuft. Das hat meistens ungewollte Folgen. Bei jeder Pause misst man die Zeit, wie lange das Spiel pausiert war, und addiert diesen Wert zur PAUSETIME dazu. Damit läuft das Spiel trotz Pausierung normal weiter wie es sollte.

Xaron

BeitragDi, Aug 30, 2005 14:08
Antworten mit Zitat
Benutzer-Profile anzeigen
MegaTefyt hat Folgendes geschrieben:
Das ist definitiv falsch. Selbst wenn man (evt.!) keinen Unterschied sieht ist meist das Spielgefühl ein anderes, man spürt FPS-Unterschiede.


Das liegt dann aber eher an der schlechten Programmierung. Sehen tut man den Unterschied wirklich nicht, "fühlen" auch nicht, wenn es ordentlich gemacht wurde - wie auch?

Gruß - Xaron
Cerberus X - Monkey X Reloaded!
 

MegaTefyt

BeitragDi, Aug 30, 2005 14:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Dann sind also alle Shooter schlecht programmiert, ja? Weil die sind das beste Beispiel dafür. Sie spielen sich allesamt besser mit 100+ FPS als nur mit 30 FPS, obwohl es laut euch ja keine Unterschiede geben dürfte. Rolling Eyes

Bura.Tino

BeitragDi, Aug 30, 2005 14:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja das wüsste ich auch zu gerne. Ich denke, das es nicht den geringsten Unterschied macht. Sehen tut man den Unterschied mit Sicherheit nicht, und fühlen denke ich auch nicht. Also ich bleibe dabei, das es keinen Unterschied gibt !

/edit: Wieso spielen die sich besser ???

D2006

Administrator

BeitragDi, Aug 30, 2005 15:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Beispiel:

Angenommen ein Objekt (Quadrat ... 5x5px) bewegt sich im Spiel auf eine 5px Mauer zu. Das ganze mit einer Geschwindigkeit von 200 Pixel pro Sekunde. Das bedeutet, das pro Schleifendurchgang das Objekt bei ...

... 30 FPS ganze 6 Pixel und 2/3 Pixel (was gerundet 7 Pixel macht) verschoben werden muss und bei ...

... 100 FPS das Objekt nur 2 Pixel verschoben werden muss.

Sofort fällt auf, dass bei 30 FPS derart große Sprünge gemacht werden, dass die gute Mauer einfach übersprungen wird, obwohl das auf keinen Fall passieren darf. Ist sie erstmal übersprungen, lässt sich eine Kollision kaum noch feststellen. Bei 100 FPS allerdings macht das Objekt kleine Schritte und muss zwangsläufig irgendwann die Mauer berühren, wodurch wir eine Kollision ermitteln können.
Man bemerkt: Je mehr FPS man hat, desto besser und genauer sind Berechnungen wie die der Kollision.

Übrigens hier mal ein feiner Beispielcode:

Code: [AUSKLAPPEN]
Graphics 640,480,32
SetBuffer BackBuffer()

fps# = 30

While Not KeyHit(1)
start = MilliSecs()



Cls

fps# = fps# + (KeyDown(205)-KeyDown(203))/5.0
Text 10,10,fps#

Rect x#,50,10,10,1
x#=x# + zeit/2.0
If x#>640 Then x#=-20

f=0
Repeat
f=f+1
Until MilliSecs()>timer + (1/fps#)*1000
timer=MilliSecs()

Text 10,80,f
zeit = MilliSecs() - start

Flip 0
Wend
End


Mit Links/Rechts könnt ihr die FPS (obere Zahl) manipulieren. Nun sagt mir einer mal, dass das bei 30 FPS genauso aussieht wie zB bei 90. Die untere Zahl gibt übrigens an, wie viel Rechenpower man verschenkt. Wenn da eine 1 steht und sich das Quadrat langsam bewegt, sind die FPS zu hoch eingestellt.

MfG
D2006

Xaron

BeitragDi, Aug 30, 2005 16:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Da muss ich widersprechen. Tokamak z.B. verwendet nicht ohne Grund keine fps-basierte sondern eine frame-basierte Technik, um die Physik zu berechnen. Es kann sonst nämlich bei hohen FPS-Werten aufgrund zu kleiner Zahlen sehr schnell zu sehr großen Problemen kommen.

Dazu empfehle ich mal, folgenden Artikel zu lesen:
http://www.gaffer.org/articles/Timestep.html

Bei Standard-0815-"Physik"-Experimenten ist das natürlich anders. Wink

Gruß - Xaron
Cerberus X - Monkey X Reloaded!

Bura.Tino

BeitragDi, Aug 30, 2005 16:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Also irgendwas stimmt an Deinem Code nicht. Bei 30 FPS läuft er flüssig und bei 900 springt das Quadrat.
Es ist dann keine wirkliche Animation mehr zu erkennen !

D2006

Administrator

BeitragDi, Aug 30, 2005 17:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Xaron hat Folgendes geschrieben:
Da muss ich widersprechen. Tokamak z.B. verwendet nicht ohne Grund keine fps-basierte sondern eine frame-basierte Technik, um die Physik zu berechnen. Es kann sonst nämlich bei hohen FPS-Werten aufgrund zu kleiner Zahlen sehr schnell zu sehr großen Problemen kommen.

Dazu empfehle ich mal, folgenden Artikel zu lesen:
http://www.gaffer.org/articles/Timestep.html

Bei Standard-0815-"Physik"-Experimenten ist das natürlich anders. Wink


Ähem. Sorry. Da bist du wohl ein klein wenig am Thema vorbei geschossen. Wir reden doch hier über diese eine Methode des frameunabhängigen Programmierens. Du beschreibst ein anderes, vielleicht sogar besseres, für das Programmieren von Hobbyprojekten vielleicht nicht notwendiges Verfahren.
Bei diesem Verfahren hier geht es aber NUR darum, die Physikberechnungen an die Framezahl anzupassen.

Um zum Thema zurück zu kommen: Siehst du nun, dass es bei 90 FPS besser aussieht als bei 30 FPS oder stimmt etwas mit deinen (vielleicht auch meinen) Augen nicht?

@Bura.Tino:
Irgendwas machst du falsch. Um 900 FPS auszuprobieren, musst du auf jedenfall Flip 0 einsetzen. Ich mage zumindest bezweifeln, dass dein Monitor eine Bildwiederholfreqeunz von 900 Hz hat. Wie gesagt, ist die untere Zahl "1", so sind die FPS zu hoch gewählt. (Etwa bei 2000 FPS ist das sowieso der Fall, weil dann die Millisekundenschritte kleiner 1 wären, was natürlich nicht geht, da MilliSecs() ja eine Integerfunktion ist)

MfG
D2006

Bura.Tino

BeitragDi, Aug 30, 2005 18:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Flip ist auf 0 gesetzt !
Ich habe den Code so übernommen wie Du ihn gepostet hast. Und trotzdem kann da was nicht stimmen.
Je höher ich in den FPS gehe, desto mehr ruckelt es.
Die untere Zahl wie Du sie nennst ist keineswegs "1" ! Sie bewegt sich im 5-stelligen Bereich !

Oder hab ich da was falsch verstanden ? Confused

SpionAtom

BeitragDo, Sep 15, 2005 0:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Bura.Tino hat Folgendes geschrieben:
Die Sache ist doch die, daß das menschliche Augen 24 Frames pro Sekunde braucht um es nicht mehr als einzelne Bilder, sondern als Animation wahrzunehmen.


^^ Auch ich möchte hier meinen Senf dazugeben. Denn auch ich halte diese Aussage für falsch. Richtig ist, dass bei 24-25 Bildern pro Sekunde keine Einzelbilder mehr zu erkennen sind. Arrow Idea Aber dennoch erfährt man mit zunehmenden FPS eine angenehmere Animation. Alles wirkt flüssiger und weicher, weil weniger Bilder ausfallen. (Im Idealfall, was nie zu erreichen sein wird, fehlen theoretisch gar keine Animationsschritte; und man will programmiertechnisch ja wenigstens so weit wie möglich die Theorie einholen Wink )

d-bug

BeitragDo, Sep 15, 2005 7:28
Antworten mit Zitat
Benutzer-Profile anzeigen
@Bura.Tino
Bisschen Spät jetzt, aber dieser Effekt ist doch eigentlich schon Standard. Ich nehme einfach mal an, daß du deinen Test im Fenstermodus gemacht hast. Dieser Effekt nennt sich tearing. Ein wenig Lektüre zum tearing findest du hier...
 

Silvio

BeitragFr, Feb 03, 2012 22:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab das angewandt, aber jetzt bewegen sich alle Figuren sehr sehr schnell. Sie werden ja jeden Schleifendurchlauf mindestens 1 Pixel bewegt. Wie kann ich jetzt langsame Bewegungen herstellen? Ich kann ja nicht die SchleifenZeit mit was kleinerem als 1 multiplizieren, da man nicht um 0.1 Pixel oder so bewegen kann.

ozzi789

BeitragFr, Feb 03, 2012 23:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Du hast einen Thread aus 2005 ausgegraben, das bestimmt ein Rekord!
Wird hier nicht so gerne gesehn..

Doch du verwendest einen Float und verwendest eine zweite Variable für Drawimage die du mit Ceil und Int bearbeitest.

Oder du erhöhst es jeden 2ten Schleifendurchgang was weis ich..
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Eingeproggt

BeitragFr, Feb 03, 2012 23:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Ohne das Tut angeschaut zu haben würde ich meinen das mit 0.1 Pixel geht sehr wohl, siehe dazu den Datentyp Float, verwendbar wenn man ein # hinter eine Variable schreibt:
BlitzBasic: [AUSKLAPPEN]
speed#=0.1

Dann wird intern mit 0.1 gerechnet... dass sich die Figur dann aber nur recht "stückweise" über den Bildschirm bewegt da sie auf gerundete ganze Pixelwerte gezeichnet wird ist halt ein anderes Problem für das ich aktuell keine Lösung hab... Aber bis jetzt sah so ein Vorgehen durchaus brauchbar aus.

mfG, Christoph.
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group