Hallo Leute,
k?nntet ihr euch mal was ansehen?
Ich habe hier einen Timertest gemacht, der die FPS - Unterschiede ausgleichen sollte! Dummerweise tut er das nicht in der Art, wie ich mir das Vorgestellt habe.
K?nntet ihr mir hier kurz helfen? Die Idee ist folgende:
Die maximale Bildrate bei GLB betr?gt 500FPS! Also legen wir in dieser Zeit eine gewisse Strecke zur?ck!
Haben wir dabei nur 50FPS mu? das Programm quasi 10x gr??ere Schritte machen um gleich weit zu kommen!
Deshalb folgende Rechnung:
((Maximale FPS * 100%) / Aktuelle FPS) / 100%
((500 * 100) / 50FPS) / 100
Das m??te eigentlich den Wert ergeben, mit dem man die Bewegung gleich gro? machen k?nnen m??te.
Soweit haut auch alles hin, wie meine beiden FPS.INI - Versuche zeigen:
- FPS.INI zeigt die Schritte bei 500 FPS
- FPS2.INI zeigt sie bei 50 FPS
Soweit so gut, dennoch f?hrt unser Rechteck bei weitem langsamer als gedacht!
Habe ich hier irgendwo einen Denkfehler eingebaut? Hier unten das Beispiel dazu:
GLOBAL schritt[]
DIM schritt[5000]
LIMITFPS 50
WHILE TRUE
FPS = INTEGER(1000 / (GETTIMERALL()-Tim)) ; Tim = GETTIMERALL()
multiplikator = ((500 * 100) / EinFrameZeit) / 100
FPS = FPS * multiplikator
x = x + FPS * 0.001
b = b + 1
schritt[b] = x
IF x > 500
ex()
ENDIF
DRAWRECT 0 + x, 100, 10, 10, RGB(255, 255, 255)
PRINT EinFrameZeit * 0.001, 0, 0
PRINT schritt[b], 0, 20
SHOWSCREEN
WEND
FUNCTION ex:
INIOPEN "fps2.ini"
FOR tmp = 1 TO b
tmp$ = tmp
INIPUT "fps", "schritt" + tmp$, schritt[tmp]
NEXT
END
ENDFUNCTION
Gru?
W.
[attachment deleted by admin]
"Test.gbas"(12) warning : probably unassigned variable : EinFrameZeit
And Crashes..
..sorry my german is bad, but i have an interest in what your doing..
Could you explain this in english too?
The google translator isnt accurateenough.
Ok, stimmt, soweit klar! Leider ist das noch nicht der springende Punkt! Irgendwo habe ich noch einen Denkfehler drinnen und den finde ich soweit aber nicht... :'(
Was genau meinst du eigentlich mit "..bewegt sich weit langsamer als gedacht" ?
Wenn ich dein Codebeispiel richtig verstehe und es nur um die reine Geschwindigkeit geht: die Geschwindigkeit deines Rechtecks wird doch im Wesentlichen gar nicht von deinem errechneten Korrektur-Multiplikator, sondern von einem fixen Faktor bestimmt. Ich mein diese Zeile hier:
x = x + FPS * 0.001
Der geschwindigkeitsbestimmende Faktor ist hier doch eher das 0.001 und nicht dein Korrektur-FPS, oder?
Ich habe das Problem gel?st! Das, worum es mir bei diesem Beispiel gegangen ist, war folgendes:
Unabh?ngig davon, wieviele FPS auf dem Bildschirm dargestellt werden, bewegt sich das weisse Rechteck immer gleich schnell gleich weit in der selben Zeit!
Testet das Beispiel mal durch, ver?ndert einfach das FPS - Maximum, dann seht ihr, was ich meine:
GLOBAL schritt[]
DIM schritt[5000]
LIMITFPS 25
WHILE TRUE
FPS = INTEGER(1000 / (GETTIMERALL()-Tim)) ; Tim = GETTIMERALL()
multiplikator = ((500 * 100) / FPS) / 100
m = POW(multiplikator, 2)
FPS = FPS * m
x = x + FPS * 0.001
b = b + 1
schritt[b] = x
IF x > 500
ex()
ENDIF
DRAWRECT 0 + x, 100, 10, 10, RGB(255, 255, 255)
PRINT FPS * 0.001, 0, 0
PRINT schritt[b], 0, 20
SHOWSCREEN
WEND
FUNCTION ex:
INIOPEN "fps2.ini"
FOR tmp = 1 TO b
tmp$ = tmp
INIPUT "fps", "schritt" + tmp$, schritt[tmp]
NEXT
END
ENDFUNCTION
Habe Deinen Thread jetzt nur ?berflogen..aber w?re es nicht einfacher nur mit Gettimer() die Anzahl der vergangenen Millisekunden seit dem letzten Showscreen zu erhalten und diese Zeit mit einer Geschwindigkeit zu multiplizieren (die dann in Pixel pro Millisekunde angegeben ist?)
also zb. x=x+0.01*fpstime
wobei x die Position ist, 0.01 die gegebene Geschwindigkeit pro ms und fpstime die Zeit, die f?r die letzte Frameberechnung gebraucht wurde...
Ehrlich gesagt, keine Ahnung wie du meinst! Kannst du mein Beispiel soweit ab?ndern, da? wir schauen k?nnen?
Wom?glich bekommen wir eine Version zusammen, die man dauerhaft ins System integrieren k?nnte...
while true
x=x+0.02*fpstime
drawsprite 4711,x,y
fpstime=int(gettimer())
showscreen
wend
Ist jetzt mal eben zwischen T?r und Angel...
Der Sinn dahinter ist folgender: Du kannst mit dem Befehl Gettimer() die abgelaufene Zeit zwischen zwei Showscreens ermitteln (in millisekunden). Wenn Du deinen Speed in Pixel pro Millisekunden angibst (hier 0.02), wei?t Du dass das Sprite 4711 in dem Beispiel sich in einer Sekunde 20 Pixel auf der x-Achse bewegen w?rde (1000ms * 0.02)
Dass Problem, auf dass Du ja hinauswillst, ist, dass Du nicht weisst wieviele Frames pro Skunde auf dem Zielsystem laufen. Da wir aber jetzt Timerabh?ngig bewegen (pro ms) statt pro Frame, hast Du mit dem obigen Beispiel immer eine Strecke von 20 Px pro Sekunde, denn: Sind auf dem Zeilsystem nur 2 FpS m?glich, w?rde das bedeuten, dass ein Frame 500 ms zur Berchnung brauchte. Diesen Wert gibt Gettimer() uns zur?ck. 500*0.02 sind 10. Also 10 Pixel Bewegung + 10 Pixel f?r den zweiten berechneten Frame in der Sekunde und Du bist wieder bei den 20.
W?ren auf dem Zielsystem 50 Frames pro Sekunde m?glich, w?rde berechnet 20 Millisekunden (1000 ms=1 Sek geteilt durch 50 Frames=20 ms pro Frame (das w?re der R?ckgabewert von gettimer() in diesem Fall) multipliziert mit 0.02 =0.4 Pixel pro berchnetem Frame. da insgesamt 50 Frames pro sekunde m?glich sind: 50 *0.4= 20 Pixel pro Sekunde Bewegung.
Egal wieviele Frames pro Sekunde m?glich sind, das Sprite wird sich pro Sekunde imer gleich weit bewegen.
Ermittle einfach mit gettimer() die Berechnungsdauer des letzten Frames, lege den Wert in einer Variablen ab und multilpliziere bei jedem bewegten Objekt den Speed mit der Framezeit (hier: fpstime)
P.S.Es kann sein, dass die Frameberechnung weniger als 1 ms dauert, dann w?re fpstime immer 0 und nichts w?rde sich bewegen, also sollte man die fpstime immer aufrunden, falls man weiss dass das Zielsystem dermassen schenll ist...
Quote from: Ocean on 2009-Jun-29
F?r eine plattform-unabh?ngige Darstellung solltest Du die physikalische Geschwindigkeiten der einzelnen Objekte in deiner virtuellen Welt binden an die Framerate...
Wieso an die Framerate binden? Ist doch quatsch.
Es soll doch Frameunabh?ngig laufen, damit es ?berall gleichschnell ist.
Need stable fps check?
FUNCTION FPS: ShowFpsBOOL //STABLE FPS!
// 1 sec update, using law of averaging :)
// Extremely Accurate i believe, and easy to read.
//
// For Every frame update with this instead:
// FPSValue = INTEGER(1000 / (GETTIMERALL()-Tim)) ; Tim = GETTIMERALL()
//
// ShowFpsBOOL=BOOL expression tells function to print the value to the corner of the screen
//
// Usage: myfpsvalue=FPS(FALSE)
// Updates a stable FPSValue Every One Second Interval:
STATIC TimeBuffer,FrameCount, FPSValue
LOCAL FrameTime
FrameTime=GETTIMER(); TimeBuffer=TimeBuffer+FrameTime; FrameCount=FrameCount+1
IF TimeBuffer>999; TimeBuffer=TimeBuffer-1000; FPSVALUE=FrameCount; FrameCount=0; ENDIF
IF ShowFpsBOOL=TRUE THEN PRINT "FPS="+FPSVALUE,10,10
RETURN FPSValue
ENDFUNCTION
Mein Beispiel verfolgt in dem Fall den 2. Weg! In dem Fall nehme ich an, da? die maximalen FPS einfach 100% sind und alles darunter erh?ht sich um den entsprechenden Prozentsatz hoch 2!
Quote from: Ocean on 2009-Jun-29
Quote from: Schranz0r on 2009-Jun-29
Quote from: Ocean on 2009-Jun-29
F?r eine plattform-unabh?ngige Darstellung solltest Du die physikalische Geschwindigkeiten der einzelnen Objekte in deiner virtuellen Welt binden an die Framerate...
Wieso an die Framerate binden? Ist doch quatsch.
Es soll doch Frameunabh?ngig laufen, damit es ?berall gleichschnell ist.
Da hast Du recht, aber wir benutzen nur zwei Wege zum gleichen Ziel:
- Du bindest die Bewegung direkt an die Zeitachse
- Ich mache das gleiche, in dem ich die genaue Dauer einer jeden Display-Schleife messe
Um eine frameunabh?ngige Bewegung zu erhalten muss man zwangsl?ufig ?ber die Zeit gehen (Punkt 1). Die genaue Dauer eines Schelifendurchlaufs messe ich ja auch - mit Gettimer().
Der einzige Unterschied ist, dass Du , soweit ich deinen ersten Thread richtig verstehe, die Zeiten mehrerer vergangener Schleifen speicherst und einen Durchschnittswert daraus bildest.
Ich habe ?ber diese Idee fr?her auch nachgedacht, es aber verworfen, da eventuelle Framerate-Spitzen nach oben oder unten einem "nachlaufen" und das Bewegungs-Ergebnis sp?terer Durchl?ufe zu sehr verf?lschen...selbst wenn Du das mathematisch versuchst zu gl?tten...
Vielleicht habe ich Deinen Post aber auch nur missverstanden?!
Quote from: WPShadow on 2009-Jun-29
Mein Beispiel verfolgt in dem Fall den 2. Weg! In dem Fall nehme ich an, da? die maximalen FPS einfach 100% sind und alles darunter erh?ht sich um den entsprechenden Prozentsatz hoch 2!
Woher wei?t Du, welche maximale Framerate es gibt? Auf meinem PC schmei?t mir GLBasic teilweise Ausrutscher auf 1000FpS aus. Dauern zwar nur den Bruchteil einer Sekunde, w?rden aber deine Bewegungen doch ziemlich verf?lschen.
GLBasic limitiert zwar von Haus aus auf 500FpS, aber 100%ig einhalten kann man es eben nie...
Oder meinst Du die max. Framerate, die auf dem Zielsystem m?glich ist? Die kannst Du aber doch gar nicht kennen...
Ich habe in dem Fall einfach mal Gernot gefragt, wo die Obergrenze f?r FPS liegt! Diese ist lt. ihm bei exakt 500FPS.
Auch wenn dieser Wert hier und da ?berschritten wird, bleibt der Gro?teil dennoch immer bei 500.
Dabei nehme ich keinen Durchschnitt an, sondern nutze einfach eine ganz simple Schlu?rechnung!
machst du aber LIMITFPS 20000 hast du mehr FPS als 500 ...
hab da so an die knapp 4000
@WPShadow
Du erreichst die 500 FPS aber nur wenn VSYNC OFF ist und nat?rlich der Rechner flott genug ist. Ich erreich das schon mal eh nicht. =D Du hast bei LIMITFPS -1 ja nur Maximale Geschwindigkeit. Aber wenn auf dem Zielrechner VSYNC On ist, l?ufts ohne der Framebegrenzung ja nur mit der eingestellten Frequenz. Bei mir zum Beispiel dann maximal 75. :) Du kannst also nicht davon ausgehen das die Syncronisation aus ist und du viele Frames hast. :)
Cheers
Deshalb wird die L?sung wohl folgenderma?en sein:
LIMITFPS 100 =D
Ich ?berlegen wegen einem Systemcheck, der beim ersten Start des Programmes die max. m?glichen FPS messen kann und aufgrund dessen die Rate automatisch anpassen kann!
Quote from: WPShadow on 2009-Jul-08
Deshalb wird die L?sung wohl folgenderma?en sein:
LIMITFPS 100 =D
Ich ?berlegen wegen einem Systemcheck, der beim ersten Start des Programmes die max. m?glichen FPS messen kann und aufgrund dessen die Rate automatisch anpassen kann!
Du bindest die Bewegung wieder an die Frames. Das ist nicht frameunabh?ngig und wird zwangsl?ufig zu verf?lschten Bewegungen auf bei sehr verschiedenen Systemen f?hren!
Du testet mit Deiner Methode am Anfang die max. Fps f?r eine bestimmte Situation. Im richtigen Spiel kommen dann aber wahrscheinlich noch Berechungen f?r Bewegungen, Verhalten, Level?berwachung (Gameover, Bonusleben etc) dazu. Das erg?be eine andere max. FpS.
Ausserdem steigt der Berechungsaufwand pro Sprite nicht linear an (1Sprite=max. 500 Fps, 2 Sprites= max. 250 Fps usw.).
Wenn Du also einen "Stresstest" mit 10000 Sprites (zoomend und rotierend) durchf?hrst, hei?t das nicht, dass Du mit nur 1000 Sprites auch entsprechend 10x schnellere Fps kriegst.
Zus?tzlich m?sste der Test am Anfang jeder Spielsession durchgef?hrt werden, da ja durchaus auf einem PC auch andere Progs im Hintergrund laufen k?nnen und bei der n?chsten Spielsession dann wieder nicht...
Einen Test mit einer "gestellten" Spielsituation etc halte ich daher f?r eher kontraproduktiv.
Die Limitierung der Fps per Befehl ist im Bezug auf eine Geschwindigkeit angegeben in Pixel pro Frame (wovon ich ausgehe, sonst w?rdest Du ja ?ber die Zeit verkn?pfen und das ganze anders aufziehen) nur sinnvoll, wenn klar ist, dass die maximal eingestellten Frames auch immer erreicht werden. Zu niedrige Framerate bedeutet dann zu langsame Bewegungen. Man sichert also nur gegen zu schnelle Bewegungen ab.
Ich glaube, Du machst es dir zu kompliziert. Aber vielleicht verstehe ich Deinen Ansatz auch nur falsch....
Hab ich auch mal gemacht, bei erfolgreicher Umsetzung gibt sich aber ein kleines ( =D ) Problem: Wenn aufgrund irgendeiner cpu-Schwankung die fps einbrechen l?uft viel schief: z.B. Kollisionen werden verf?lscht (also wenn man vor der Wand steht und sich pl?tzlich 100 statt 10 Einheiten weiter darauf zubeweget k?nnte man auf der anderen Seite stehen :whistle:
Im sorry about not being able to communicate in german...
I think I know a solution for everyone(hopefully).
If you can understand this, please translate it for the others:
The problem isnt just with FPS.
The problem is a combined issue for a movement rate, relative to FPS, AND screensize.
If you want movement to be the same on any computer with your program,
you must scale and factor everything (time, screen size, movement size).
Proof of concept is in the particle system i recently created.
In order to make all the particles move on any computer, the same relative size factor as on some other computer(which may be a different screen size and different FPS), i had to create a movement size algorithm, which is factored in every frame.
No matter what i set in LIMITFPS.....all particles movement size is relavant to time and screensize.
If the FPS are low at 10, or high at 800....the particles will still travel across the screen in the same distance during the same amount of time!
The idea is this: If a particle moves across a screen, from one side to another, in one second time....it must do the same thing on any computer, using any screensize.
So i built this algorithm to cover any screensize, with any FPS:
MovementFactorPerFrame = ( ScreenHeight / 2) * 0.001 * GETTIMER()
(Algorithm translation: half the screen height is a relavant movement size factor of 1, divided by frame time.)
To change the real speed.....use a multiplier:
MovementSize = MovementFactorPerFrame * SpeedMultiplier
I have been pounding my head for years to solve this issue...this algorithm is a GOLDEN EGG.
As soon as V7 beta is full version, my particle system will be available, and you will be able to see this algorithm in action. To test...use 2 computer with the same program, and move the particles on both computers at the same time......all objects should move roughly the same relative speed, and the same relative distance compared to the screen size.
Note: And as others have said, make sure you VSYNC FORCED OFF, and set LIMITFPS 10000.
If you dont do this...your(any computer your program is on) FPS are limited to your video refresh rate.
If FPS>VSYNC is needed for your program to function properly....make sure you document this information about VSYNC in your help file, stating in it, to force vsync off!
Hopfully, someone can help properly convey the idea here.
In the event that this document is irrelavant to the topic, i blame it on my translator :)
Hemlos, why pound your head to a wall when you have but to ask? If you download my first GLBasic program you have the solution there. It's called Worms and can be found on my homepage.
Is it possible to see the timer in there???
I found the program and the source, but not the timer inside! :'(
Did you try this?
MovementFactorPerFrame = ( ScreenHeight / 2) * 0.001 * GETTIMER()
If you need help with it, let me know.
Ok for 2D! But is it useful for 3D too?
I tried to make a timer for 2D and 3D together and 3D is the biggest problem... ;/
Quote from: WPShadow on 2009-Aug-03
Ok for 2D! But is it useful for 3D too?
I tried to make a timer for 2D and 3D together and 3D is the biggest problem... ;/
I dont think you need this algorithm with 3d...
..perhaps just a timer testing the last frame time is all that is needed:
Because, there is no variation in the world size from one computer to the next,
Unlike 2d where the screensize is the area that may differ in movement factors.
This should be good enough for 3d:
MovementFactorPerFrame = 0.001 * GETTIMER()
I will be testing this variation with my particle system. If i find anything unusual about movement timers in 3d, ill report back here again.
Great, thx for your help!
No problem. Cheers :booze: