Frameunabhängigkeit klappt nicht

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

Meik

Betreff: Frameunabhängigkeit klappt nicht

BeitragFr, Sep 04, 2009 18:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Moin Smile

Zuerst: Wer das Pröglein testen mag braucht die Plot.png. Muss im selben Verzeichnis wie das Programm liegen. (Ist keine leere Seite. Das Bild ist nur 16 x 16 px Groß und ist ein weißer Kreis ^^)
http://img215.imageshack.us/img215/9704/plot.png
Achso und ich hab Draw3D V3.2 mit eingebaut.

Letztens kam das ps3 3.0 Update raus. Diese Version hat den standard Hintergrund "aufbereitet" und mit so "Glühwürmchen" versehen (Particle die kurz aufleuchten und dann wieder schwächer werden).

Da dacht ich mir "Boah, sieht das cool aus. Das muss ich mal nachprogrammieren." Gesagt getahn! Der Code funktioniert so wie er ist einwandfrei für mein verständnis Wink. Jetzt will ich bei dem Projekt wieder was dazu lernen und hab mir mal das Thema "Frameunabhängig programmieren" zu Herzen genommen weil bei mehreren "Glühwürmchen" der Rechner ja irgendwann in die Knie geht.

Code:
Code: [AUSKLAPPEN]
Global SW% = 800, SH% = 600
Graphics3D SW%, SH%, 32, 1
SetBuffer( BackBuffer() )
SeedRnd( MilliSecs() )

Local frametimer% = CreateTimer( 60 )
Local Camera% = CreateCamera()

Include "Includes\Draw3D.bb"
DrawInit3D( Camera% )
Origin3D( SW%, SH% )

Global Font = LoadFont3D( "Fonts\Standard.png" )
SetFont3D( 0.5, 1.0, 0.0, 0.0 )
;Global Background% = LoadImage3D( "Background.bmp" )

Global ParticleTimer% = MilliSecs()
Global ParticleDelay% = ParticleTimer% + 50
Global NumParticle% = 0
Global NumParticlePerFrame% = 1
Global MaxParticle% = 200

Global FPSC# = 0 ;C = Counter
Global FPS# = 0
Global FPSF# = MilliSecs() + 1000 ;F = Finish

Global ms# = MilliSecs()
Global mse# = 0.0
Global dif# = 0.0

Global dot% = LoadImage3D( "Plot.png" )
Type TParticle
   Field img%
   Field dir%
   Field x#, y#
   Field mx#, my#
   Field r%, g%, b%, a#
   Field life%
   Field hlife%
   Field scale#
   Field scaleperframe#
End Type

While Not KeyDown( 1 )
   ms# = MilliSecs()

   FPSC# = FPSC# + 1
   If( ms# > FPSF# )
      FPS# = FPSC#
      FPSC# = 0
      FPSF# = ms# + 1000
   EndIf
   
   ;ParticleTimer% = MilliSecs()
   ;If( ParticleTimer% > ParticleDelay% )
      For i = 1 To NumParticlePerFrame%
         If( NumParticle% < MaxParticle% ) Then CreateParticle()
      Next
      
      ;ParticleDelay% = ParticleTimer% + 50
   ;EndIf
   
   ColorG3D( 255, 255, 255, 1 )
   ;DrawImage3D( Background%, 0, 0 )
   UpdateParticle()
   
   Text3D( Font, -SW% / 2, 0, "FPS: " + FPS# )
   Text3D( Font, -SW% / 2, -12, "FPS Counter: " + FPSC# )
   Text3D( Font, -SW% / 2, -24, "FPS Finish: " + FPSF# )
   Text3D( Font, -SW% / 2, -36, "ms: " + ms# )
   Text3D( Font, -SW% / 2, -48, "mse: " + mse# )
   Text3D( Font, -SW% / 2, -60, "dif: " + dif# )
   
   mse# = MilliSecs()
   dif# = mse# - ms#
   
   WaitTimer( frametimer% )
   RenderWorld()
   Clear3D()
   Flip 0
Wend
End

Function CreateParticle()
   NumParticle% = NumParticle% + 1

   Local p.TParticle = New TParticle
   ;p\img% = GrabImage3D( dot%, 0, 0, 1, 1, 1, 1 )
   p\img% = LoadImage3D( "Plot.png" )
   p\x# = Rand( -(SW% / 2), SW% / 2 )
   p\y# = Rand( -(SH% / 2), SH% / 2 )
   p\dir% = Rand( 360 )
   p\mx# = Cos( p\dir% ) * Rnd( 0.1, 0.5 )
   p\my# = Sin( p\dir% ) * Rnd( 0.1, 0.5 )
   p\r% = 200
   p\g% = 200
   p\b% = 200
   p\a# = Rnd( 0.3, 1.0 )
   p\life% = Rand( 20, 80 )
   p\hlife% = p\life% / 2
   p\scale# = 0
   p\scaleperframe# = Rnd( 0.005, 0.01 )
End Function

Function UpdateParticle()
   For p.TParticle = Each TParticle
      p\x# = p\x# + p\mx#
      p\y# = p\y# + p\my#
   
      ;p\x# = p\x# + p\mx# / FPS#
      ;p\y# = p\y# + p\my# / FPS#
      
      ;p\x# = p\x# + p\mx# * dif#
      ;p\y# = p\y# + p\my# * dif#
      
      p\life% = p\life% - 1
      If( p\life% > p\hlife% )
         p\scale# = p\scale# + p\scaleperframe#
      Else
         p\scale# = p\scale# - p\scaleperframe#
      EndIf
      
      ColorG3D( p\r%, p\g%, p\b%, p\a# )
      DrawImage3D( p\img%, p\x#, p\y#, 0, 0, p\scale#, 0 )
      
      If( p\life% <= 0 )
         p\x# = Rand( -(SW% / 2), SW% / 2 )
         p\y# = Rand( -(SH% / 2), SH% / 2 )
         p\dir% = Rand( 360 )
         p\mx# = Cos( p\dir% ) * Rnd( 0.1, 0.5 )
         p\my# = Sin( p\dir% ) * Rnd( 0.1, 0.5 )
         p\r% = 200
         p\g% = 200
         p\b% = 200
         p\a# = Rnd( 0.3, 1.0 )
         p\life% = Rand( 20, 80 )
         p\hlife% = p\life% / 2
         p\scale# = 0
         p\scaleperframe# = Rnd( 0.005, 0.02 )

         ;NumParticle% = NumParticle% - 1
      EndIf
   Next
End Function


die FPS zu mässen (oder messen? weiss ich grad nicht ^^, zu zählen ) hab ich hinbekommen.

Aus einem meiner alten Bücher über c++ und DirectX hab ich das Beispiel:
Code: [AUSKLAPPEN]
p\x# = p\x# + p\mx# / FPS#
p\y# = p\y# + p\my# / FPS#


So wird die Frameunabhängigkeit aber nur einmal pro Sekunde aktualisiert da sich die FPS nur einmal pro Sekunde ändern.

Jetzt hab ich hier mal im Forum gelesen die Zeitdifferenz vom Anfang der Schleife zum Ende der Schleife zur Berechnung zu benutzen. Hab ich auch probiert. Ergebnis:

Code: [AUSKLAPPEN]
[...]
Global ms# = MilliSecs()
Global mse# = 0.0 ;Millisekunden am Ende der Schleife
Global dif# = 0.0
[...]
While Not KeyDown( 1 )
   ms# = MilliSecs()
   [...]
   mse# = MilliSecs()
   dif# = mse# - ms#
Wend
End

Function UpdateParticle()
   For p.TParticle = Each TParticle
      p\x# = p\x# + p\mx# * dif#
      p\y# = p\y# + p\my# * dif#
      [...]
   Next
End Function


Und jetzt nach langer Erklärung das eigendliche Problem:
dif# wechselt sich immer zwischen 0.0 und 4.0. Warum ist das so? Was hab ich in meinem Code anders gemacht als es hier in den vielen Beispielen beschrieben ist?

Meine rechenkünste sind zu bescheiden um von den dif# auf Frames umzurechnen aber rein logisch gesehen müsste bei ca 60 FPS dif# höher sein als 4.0.

Hoffe ihr habt mich (mal wieder ^^) verstanden wo mein Problem liegt Smile
Ich will euch nur nicht auf den Zeiger gehen mit meinem Pipi Progrämmchen und meinen Ellenlangen Texterklärungen Smile

Edit: Habe bei 500 Glühwürmchen 11 FPS und eine Millisekundendifferenz von 2? wie geht das? :O Zählt mein Rechner schneller als er die Bilder aufbauen kann? hmm...

hectic

Sieger des IS Talentwettbewerb 2006

BeitragFr, Sep 04, 2009 20:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab dein Code nicht gleich sofort verstanden, dann neu angefangen dir das Frameunabhängige mal zu erklären. Dazu habe ich ein kleines Testprogramm geschrieben:

Code: [AUSKLAPPEN]
Graphics 800,100,0,2
SetBuffer BackBuffer()

Local Timer=CreateTimer(60)
Local Warten
Local MSNeu=MilliSecs()
Local MSAlt
Local MSDiff#

Local XPos#=100
Local XSpeed#=5




While Not KeyHit(1)
   
   MSAlt=MSNeu
   MSNeu=MilliSecs()
   MSDiff=(MSNeu-MSAlt)/16.666 ; Entspricht (1000MS/Sek)/60FPS
   
   Text 20,14,"Langsamen Rechner simulieren mit [SPACE]"
   Text 20,34,"Ist gerade Aktiv = "+Warten
   If KeyHit(57) Then Warten=1-Warten
   If Warten=1 Then Delay 40
   
   If KeyDown(203) Then XSpeed=XSpeed-0.1*MSDiff
   If KeyDown(205) Then XSpeed=XSpeed+0.1*MSDiff
   
   Rect XPos,54,10,10,1
   
   XPos=XPos+XSpeed*MSDiff
   
   If XPos>800 Then XPos=-10
   If XPos<-10 Then XPos=800
   
   Text 20,74,"DifferenzMultiplikator: "+MSDiff
   
   WaitTimer Timer
   Flip 0
   Cls
Wend
End


Im großem und ganzem brauchst du nicht unzählige MilliSecs() aufrufe pro Schleifendurchlauf. Es reicht erstmal nur einer. Auch eine FPS-Berehnung brauchst du nicht. Was dur brauchst ist einfach nur die Differenzzeit de sletzten Schleifendurchlaufs. Und dieser errechnet sich aus den folgenden drei Zeilen:

Code: [AUSKLAPPEN]
   MSAlt=MSNeu
   MSNeu=MilliSecs()
   MSDiff=(MSNeu-MSAlt)/16.666


Im Idealfall (das wäre, das Programm läuft mit 60 FPS was 1000/60 = 16.6666 entspricht) läuft die Berechnung auf den Wert 1.0 zu. Läuft dein Programm zum Beispiel nur mit 30 FPS, dann wird MSDiff zu 2.0 etc... Diesen Wert mußt du dann zu jeder Geschwindigkeitsvariable (auch bei der Beschleunigung!!!) mit einberechnen. Also Multiplizieren. Fertig ist das ganze.

Edit1:

Zitat:
Edit: Habe bei 500 Glühwürmchen 11 FPS und eine Millisekundendifferenz von 2? wie geht das? :O Zählt mein Rechner schneller als er die Bilder aufbauen kann? hmm...


Wenn deine Grafikkarte sehr leistungsschwach ist, kann es passieren, dass der Rechner tatsächlich Bilder im vorraus berechnet und die Grafikkarte bis zu einer Sekunde hinterher hinkt, bis es dann den Speicher frei gibt und das Aufbauen der Verzögerung wieder von neuen beginnt. zumindest habe ich das Problem bei meiner abgespeckten und ur-alten ATI, wenn zuviele 3D-Sachen berechnet werden, der Prozessor sich aber langweilt.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D

Nicdel

BeitragFr, Sep 04, 2009 20:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Zu beachten:

Code: [AUSKLAPPEN]
CreateTimer(60)


begrenzt nicht auf 60 sondern auf 62.5 FPS.
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7

hectic

Sieger des IS Talentwettbewerb 2006

BeitragFr, Sep 04, 2009 20:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Jo, das stimmt wohl. Habe es zwar auch schon seit einiger Zeit feststellen müssen, habe mir aber nicht die Mühe gemacht die tatsächliche Zeit zu messen.

Aber eben mal ausprobiert, statt: MSDiff=(MSNeu-MSAlt)/16.666 dann MSDiff=(MSNeu-MSAlt)/16 zu nehmen, macht das ganze noch unruhiger wie ich finde. Auch wenn /16 dann genau 1000/62.5 entsprechen.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D
 

Meik

BeitragFr, Sep 04, 2009 20:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Erstmal herzlichen Dank Very Happy

Ich hab hier tatsächlich eine uralt mühle die WIRKLICH uralt ist. Die Grafikkarte ist auch schon vor dem ersten Weltkrieg alt gewesen ^^.
Vielleicht packt der Rechner das ja wirklich nicht und ich muss das mal auf einem anderen Rechner Probieren Smile

Ich werd mal mein kleines Glühwürmchen Projekt in dein Frameunabhängiges Programm "einbauen" und schauen ob ich nicht vielleicht doch was retten kann Very Happy Kann nämlich noch einige Monate dauern bis ich wieder einen Computer habe :/ Und solange will ich nicht nur Miniprogramme basteln.

Danke euch beiden für die Hilfe und die Infos Smile

btw: Sobald man Draw3D erwähnt kommt hectic irgendwie immer dazu ^^ Ist nicht böse gemeint aber das ist sowas wie das "Batman" symbol am Himmel *g*

MFG Smile

Edit: Geil, jetzt klappt es dank deiner Formel, hectic! Ich weiss noch nicht was an meinem Code so blöd lief aber ich werd den nicht löschen. Mein alter Code ist ein hervorragendes Übungsobjekt für mich ^^.

Wie schön ich mir immer selbst Steine in den Weg lege um mich dann zu freuen sie wieder weg zu räumen xD *glücklich ist* ^^

Edit 2: Die Framezählung hab ich nur eingebaut weil ich testen wollte ob ich das überhaupt kann. Sie hat keinen wirklich Sinn ausser zu exestieren ^^

hectic

Sieger des IS Talentwettbewerb 2006

BeitragFr, Sep 04, 2009 22:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, immer wenn die Draw3D mit im Spiel ist schalte ich mich ein. Das liegt u.a. auch daran, dass ich immer noch auf der Suche nach möglichen Fehlern der Draw3D bin. Möchte vermeiden, dass sich Leute den Kopf zerbrechen, nur weil ich eventuell Fehler gemacht habe. So konnten auch in der V.3.2 zu älteren noch zwei solcher Fehler behoben werden.

Das waren, falls es überhaupt jemand interessiert: Einmal beeinfluste ein eingestellter Fog mit die Draw3D-Darstellung. Und zum anderem gab es Probleme, wenn jemand eine sehr große Auflösung eingestellt hat, dann war das standard voreingestellte CameraRange nicht mehr im Sichtbereich der Draw3D gewesen. Beide Fehler habe ich behoben, auf welche ich nicht gekommen wäre, da ich zum einen nicht mit FogRange arbeite noch große Auflösungen in Projekten einstelle. Wink

Für Hobbyentwickler soll programmieren ja Spaß machen. Und jeder hat da seine eigenen Vorlieben.

Im übrigen finde ich deine Glühwürmchen sehr gut umgesetzt. Ich probier das gleich mal zu Testzwecken auf meinem SED (SpriteEDitor) der automatisch Animationen für die Draw3D2 machen kann.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D
 

Meik

BeitragSo, Sep 06, 2009 17:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen dank für das Lob Very Happy

Übrigends: Das ist das mein erstes Prjekt mit Draw3D und hatte keine Probleme mit dem 0 Punkt *g* find ich Klasse so! Draw3D ansich ist Super!

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group