GLBasic forum

Codesnippets => Math => Topic started by: bigsofty on 2012-Sep-05

Title: Constant Game Speed independent of Variable FPS
Post by: bigsofty on 2012-Sep-05
Here is my take on deWitters famous game loop code. It makes for a smoother game, runs you code at same speed on any platform too.

This removes the need for your program to update its logic at the same time as the frame is rendered (why check for a key press at 60 fps for example). Also, your code does not need to wait till a frame is rendered to continue. Another advantage is predicted interpolation, this means for much smoother graphics with a more powerful platforms or "best fit" with low powered platforms. On top of that you can choose at what frame speed your game runs at, without worrying about the speed the graphics are being rendered at, great for physics simulations for example. The chances are that if you have seen a really smooth game running on different platforms, then it uses code like this.

About the demo:

The demo code is based on a small code listing from here, http://www.glbasic.com/forum/index.php?topic=8425.msg71420#msg71420
I simply converted it, to show you how a traditional gameloop piece of code would be converted to run with independent game logic. Its not the best example (the juddering when the two boxes meet is because of the original code) but I did not want to change it further to add confusion

Important: Set "Maximum Frame rate [hz]" to -1 in your project options

Also on some GFX cards you may have to "Vertical Sync" off if it is forced on in your driver options.


Read This: http://www.koonsolo.com/news/dewitters-gameloop/

This explains it better than I ever could.


New Game Loop Lib:
Code (glbasic) Select
// --------------------------------- //
// Project: gameloop (Ian Thompson - Sept 12)
// Start: Wednesday, September 05, 2012
// IDE Version: 11.001

// Based on "deWiTTERS Game Loop" ( see http://www.koonsolo.com/news/dewitters-gameloop/ )

GLOBAL  interpolation#

FUNCTION GameLoop:
    CONSTANT TICKS_PER_SECOND% = 30 // Runs at 30fps
    CONSTANT SKIP_TICKS% = 1000 / TICKS_PER_SECOND
    CONSTANT MAX_FRAMESKIP% = 5

    LOCAL next_game_tick% = GETTIMERALL()
    LOCAL loops%

    LOCAL game_is_running% = TRUE
    WHILE( game_is_running )

        loops% = 0
        WHILE( GETTIMERALL() > next_game_tick% AND loops < MAX_FRAMESKIP%)
            Update()

            next_game_tick = next_game_tick + SKIP_TICKS
            INC loops
        WEND

        interpolation# = ( GETTIMERALL() + SKIP_TICKS - next_game_tick ) / SKIP_TICKS

        Render()
    WEND
ENDFUNCTION


FUNCTION Interpolate#: cur#, old#, interp#
RETURN old# + (cur# - old#) * interp#
ENDFUNCTION



Demo:

Code (glbasic) Select
// --------------------------------- //
// Project: Constant Game Speed independent of Variable FPS demo (Ian Thompson - Sept 12)
// Start: Wednesday, September 05, 2012
// IDE Version: 11.001

GLOBAL x#=100,Ox#
GLOBAL y#=100,Oy#
GLOBAL angle#=0
GLOBAL speed#=4

GLOBAL mx#,my#,Omx#,Omy#,b1,b2

SETSCREEN 640,480,0

WHILE TRUE
GameLoop()
WEND

// These two routines are the basis of your new game loop

// Only for game logic updating
FUNCTION Update:
LimitMouse()
MoveObjectToMouse()
ENDFUNCTION

// Only for drawing
FUNCTION Render:
DRAWRECT Interpolate(mx,Omx,interpolation#),Interpolate(my,Omy,interpolation#),32,32,RGB(255,0,0) // Mouse#
DRAWRECT Interpolate(x,Ox,interpolation#),Interpolate(y,Oy,interpolation#),32,32,RGB(255,255,255) // Object
PRINT "Rendering at "+getfps()+" FPS",10,10
SHOWSCREEN
ENDFUNCTION

FUNCTION LimitMouse:
Omx=mx;Omy=my // Cache anything that moves(or scales, rotates) before they change for frame by frame interpolation.
MOUSESTATE mx, my,b1, b2
IF mx<0 THEN mx=0
IF mx>640-32 THEN mx=640-32
IF my<0 THEN my=0
IF my>480-32 THEN my=480-32
// SETMOUSE mx, my
ENDFUNCTION

FUNCTION MoveObjectToMouse:
Ox=x;Oy=y // Cache anything that moves(or scales, rotates) before they change for frame by frame interpolation.
angle = ATAN(my - y, mx - x)
x=x+COS(angle)*speed
y=y+SIN(angle)*speed
ENDFUNCTION


//Frames per sec calc
FUNCTION getfps:
STATIC fps_time,fps_counter,fps,fps_temp
    fps_time = GETTIMERALL()
    fps_counter = fps_counter + 1
        IF (fps_time-fps_temp)>1000
            fps_temp = fps_time
            fps = fps_counter
fps_counter = 0
        ENDIF
    RETURN fps
ENDFUNCTION

// Orginal frame based code ( see http://www.glbasic.com/forum/index.php?topic=8425.msg71420#msg71420 )
//GLOBAL x#=100
//GLOBAL y#=100
//GLOBAL angle#=0
//GLOBAL speed#=20
//
//GLOBAL mx#,my#,b1,b2
//
//SETSCREEN 640,480,0
//
//WHILE TRUE
//
// PRINT mx,10,10
// PRINT my,10,20
//
// LimitMouse()
//
// DRAWRECT mx,my,32,32,RGB(255,0,0) // Mouse#
// DRAWRECT x,y,32,32,RGB(255,255,255) // Object
//
// MoveObjectToMouse()
//
// SHOWSCREEN
//
//WEND
//
//FUNCTION LimitMouse:
// MOUSESTATE mx, my,b1, b2
// IF mx<0 THEN mx=0
// IF mx>640-32 THEN mx=640-32
// IF my<0 THEN my=0
// IF my>480-32 THEN my=480-32
// SETMOUSE mx, my
//ENDFUNCTION
//
//FUNCTION MoveObjectToMouse:
// angle = ATAN(my - y, mx - x)
// x=x+COS(angle)*speed
// y=y+SIN(angle)*speed
//ENDFUNCTION


I hope this of use to someone.


Ian



[attachment deleted by admin]
Title: Re: Constant Game Speed independent of Variable FPS
Post by: r0ber7 on 2012-Sep-06
The article is very interesting. Got me thinking...
Right now, the benefits of implementing this in my game are negligable. However, if I am to write a multiplayer mode, it might reduce the network traffic. Sending a packet every frame is unnecessary and might cause problems on slower connections. This solution could improve multiplayer performance, no? Hmm...

Thanks for the read. Bookmarked. :)
Title: Re: Constant Game Speed independent of Variable FPS
Post by: Slim on 2012-Sep-06
Hi bigsofty,

Thanks for this code.

Title: Re: Constant Game Speed independent of Variable FPS
Post by: bigsofty on 2012-Sep-06
Your very welcome.

Since the game timing is no longer dependant of a fixed frame rate then I think networking should be easier, knowing that all the various clients are running at the same speed.

One strange unexpected thing I found was that I had a generally faster game with this technique. The amount of time that I was spending repeatedly doing the same task unnecessary was reduced, freeing up more time for interpolated rendering or other tasks. The update() will steal back time from the rendering if it needs the CPU time, this will be pretty unnoticeable though due to the interpolation smoothing this transition out.

EDIT: BTW I built this using V11 beta, I think the -1 project option is able on V10?
Title: Re: Constant Game Speed independent of Variable FPS
Post by: erico on 2012-Sep-06
This looks so great! Must bookmark, even though it is going to be a couple years before I funnly understand. :good:
Thanks!
Title: Re: Constant Game Speed independent of Variable FPS
Post by: Asmodean on 2012-Sep-06
QuoteEDIT: BTW I built this using V11 beta, I think the -1 project option is able on V10?

Works without a problem under V10 with the -1 in "project option"

Many thanks bigsofty for both, the Code and the Link.  I think both is very, very helpful for me.
Title: Re: Constant Game Speed independent of Variable FPS
Post by: Wampus on 2012-Sep-06
Bump for good content. :)

Interpolation is a nice final touch. I haven't added that to my own games yet so they sometime stutter a bit.
Title: Re: Constant Game Speed independent of Variable FPS
Post by: bigsofty on 2012-Sep-06
I have used the above technique in a very large project, this project has lots of things moving around the screen, scrolling with a separate camera and so far it has worked very well. I thought I would mention this as its always reassuring to know that someone else has taken the plunge with something like this that forces you to dramatically alter the code base of your game. For me, it was worth it.  ;)

Title: Re: Constant Game Speed independent of Variable FPS
Post by: Hemlos on 2012-Oct-09
Reminds me of a couple tutorials i wrote for consitant mouse, and object, independant movement.

http://www.glbasic.com/forum/index.php?topic=8313.0
http://www.glbasic.com/forum/index.php?topic=8287.0
Title: Re: Constant Game Speed independent of Variable FPS
Post by: mentalthink on 2012-Oct-09
This it´s very interesting... I don´t use in my actual project... too much thing to change... but this it´s very very interesting, and Usefulll!!!
:nw: :nw: :nw:
Title: Re: Constant Game Speed independent of Variable FPS
Post by: r0ber7 on 2012-Dec-01
I've started implementing this in my game. In preparation for multiplayer, I'm using this to make sure all clients run at the same game speed. From what I've noticed so far, game quality remains the same (thanks to the interpolation) and I suspect the processor load is greatly reduced. The actual rewriting of code wasn't that big of a deal cause I already had most of my drawing commands in one place. Now it's a case of fishing out the last rogue drawing commands, doing some standardizing, and I'm set. :)

All in all, this is something I will definitely recommend.  :good: I will also start off all my future games from this framework.
Title: Re: Constant Game Speed independent of Variable FPS
Post by: bigsofty on 2012-Dec-02
I'm glad its of use to you.  :)

I too am using it on Android and Windows currently. Tt scales well on multi-platforms/devices BTW. I have not used it across a network though, I will be interested to hear how it works out for yourself.
Title: Re: Constant Game Speed independent of Variable FPS
Post by: r0ber7 on 2012-Dec-03
Hey bigsofty, you have any tips on how to handle camera movement interpolation?

My camera is a little bit jittery. I'm interpolating between x, and x0, using xn as the interpolated value. Then I draw the tiles like, tile.x - xn. I know this isn't the best of a description, but if you've got any tips, I'd like to know. :) It jitters sometimes, and sometimes not. It may be something else that's causing it though... (That's the problem with big rewrites, bugs can hide in so many places. :P)
Title: Re: Constant Game Speed independent of Variable FPS
Post by: Hemlos on 2012-Dec-04
camera, 3d?

jitters can happen when you try to render things that are outside the opengl world boundaries.

i can offer several solutions to this, but i need to know the layout of your world first.

is it wide like a dukenumem with gravity and such?
or is it huge 3d outer space style, is it infinite sized?
or is it just a side scroller in 3d?

each of these layouts can be setup easily to be infitely large without any glitching due to cam position.
basically, you put the cam at 0, and move everything else...and end rending of objects that are far away from the cam.
Title: Re: Constant Game Speed independent of Variable FPS
Post by: bigsofty on 2012-Dec-04
Quote from: r0ber7 on 2012-Dec-03
Hey bigsofty, you have any tips on how to handle camera movement interpolation?

My camera is a little bit jittery. I'm interpolating between x, and x0, using xn as the interpolated value. Then I draw the tiles like, tile.x - xn. I know this isn't the best of a description, but if you've got any tips, I'd like to know. :) It jitters sometimes, and sometimes not. It may be something else that's causing it though... (That's the problem with big rewrites, bugs can hide in so many places. :P)

How does your camera operate? Is it a virtual camera, everything moves left using an offset variable when the camera pans right for example? Or is it using another method?

An easy fix sometimes is to check for a rogue int to float or float to int type conversion as this would mess up the interpolated values. Also try putting your verticle sync back on, in you project options and your gfx cards control panel and see if that makes it better of worse.
Title: Re: Constant Game Speed independent of Variable FPS
Post by: r0ber7 on 2012-Dec-04
Quote from: bigsofty on 2012-Dec-04
Is it a virtual camera, everything moves left using an offset variable when the camera pans right for example?

Yes. Objects have their x & y position in the world. object screen drawing position = (object world position - camera position). So on the one hand I'm interpolating the camera position, on the other hand I'm interpolating any moving objects. Camera position is an int, and so is everything else I use for drawing.

Vsync is set to "let the program determine" in my nVidia screen, and project options of max fps -1 & 60 both give the same result.

Thanks for the comments, I'll figure it out eventually. :)
Title: Re: Constant Game Speed independent of Variable FPS
Post by: Slydog on 2012-Dec-04
@r0ber7

You *may* want to try converting your camera position 'ints' to 'floats'. (And perhaps your object positions too)
Do all math and updates to those using floats also.
Then, you will be able to handle sub/fraction pixel movement smoothly.

When I implemented my 'kinetic scroll' algorithm to mimic iPhone's scrolling, it would only work with floats, or else it would be very jerky when it was at a fraction of an int speeds.

But, if your speed is say 2 constantly, and you're still getting jerkiness, then I suppose you may have another problem somewhere.
Title: Re: Constant Game Speed independent of Variable FPS
Post by: kanonet on 2012-Dec-04
But if you do your camera etc. in float you may get the same camera shivering that we know from 3D.
When you add a number that are really different in size like 0.1 vs 1000 etc. then you get float inaccuracy...
Title: Re: Constant Game Speed independent of Variable FPS
Post by: Slydog on 2012-Dec-04
@kanonet

All the calculations and updates are done to a float variable, then converted by GLB to an int when used for a position.  But I suspect that's not what you're questioning.

I'm not too sure what you mean by "camera shivering that we know from 3D".
In my game my 3D camera is positioned using my tween / easing library. 
When it gets to its destination (smoothly), it stops and remains fixed, no 'shivering'.
My tween library *sets* the camera position each frame (it knows where the camera should be), it doesn't just add an offset value to the current position, so this may have something to do with it.

I also don't know what you were leading to regarding float inaccuracy.
In that if you keep incrementing a position variable by a floating value, eventually it will drift away from what you are expecting?  Or because '0.1' and '1000.0' are far apart . . . and . . . dang, still don't know what you were inferring.  I guess without an example situation (not code) I may not.

I understand the nature of floats, I just can't readily come up with a situation where they could be a problem (with positioning specifically).  (But mind you, in my programming career, I sure had run ins with float inaccuracy bugs! ha)

[Cool, my '777'th post!  Dang, now I can't make any new posts or I will ruin it!]
Title: Re: Constant Game Speed independent of Variable FPS
Post by: bigsofty on 2012-Dec-04
TBH if the problem was a float to int conversion, then I would expect to see constant shivering. not just intermediate shivering.

I use this system in 3D, so I interpolate between vectors, which are all floats, this may be why I dont get the same problems. I would not like to use ints internally though, even for 2D, as the interpolation relies on the fact that it can use sub-pixel accuracy when calculating the next point on the screen, for really slow moving objects for example.

For example it has enough time to render 10 frames and it only has to move a sprite 4 pixels. It will try and increment each frame 0.4 pixels. You would loose the interpolation accuracy if using ints. The same would be true of the camera.

This still may not me the problem though as there are other factors that could be producing this effect. Rober7, if you could provide a simple cut-down example of the problem, I would take a small look if you like?
Title: Re: Constant Game Speed independent of Variable FPS
Post by: r0ber7 on 2012-Dec-05
Hmm... yeeesss... :)

Ok. So, I have to use ints. This is because of the z_project lib I use. If I use floats I'll get tiny errors when scaling on different screens, which looks as if the screen has been "sliced up". I don't think that using ints is the cause of the problem anyway, because (in the name of science!) I did change all position related variables to floats this afternoon, and it was still jittery. Intermediate indeed, bigsofty. I have another idea now: put the camera movements inside the draw() function. I know, this is cheating a bit, but hey, might work. :P

Maybe if that doesn't work I'll post some code here. Thanks for all the suggestions you guys. I suspect this has something to do with internal game specifics rather than the actual gameloop code though, so I feel bad for derailing the thread. :P
Title: Re: Constant Game Speed independent of Variable FPS
Post by: Hemlos on 2012-Dec-13
If its not your code, Im willing to bet your camera is out of opengl's boundary limits.
The size of the opengl world is -32000 to 32000 in each dimension, if you go further it causes problems.

http://www.glbasic.com/forum/index.php?topic=3904.msg28557#msg28557

I suspect this is your problem because you are using integer for 3d coordinates.
You should use floats in the 3d world, otherwise(ints) you are wasting precious 3d space.

64000.0 total opengl world width would be 64km wide.
Build all objects relative to 1 xyz position=1 meter. eg 0.5 would be a half meter.

Furthermore, the best way to setup a camera in opengl is move the world, not the camera.
In your case, alternatively, you can make grids and shift the grids and the camera relative to 000 xyz when the camera goes too far.




Title: Re: Constant Game Speed independent of Variable FPS
Post by: Wampus on 2012-Dec-14
Quote from: r0ber7 on 2012-Dec-05
Ok. So, I have to use ints. This is because of the z_project lib I use. If I use floats I'll get tiny errors when scaling on different screens, which looks as if the screen has been "sliced up". I don't think that using ints is the cause of the problem anyway, because (in the name of science!) I did change all position related variables to floats this afternoon, and it was still jittery. Intermediate indeed, bigsofty. I have another idea now: put the camera movements inside the draw() function. I know, this is cheating a bit, but hey, might work. :P

Tiny errors when scaling causing sliced up look? Hmm, you know that sounds like a sprite extrusion issue. Here is a thread about a similar problem (or the same problem) and solutions: http://www.glbasic.com/forum/index.php?topic=5057.0 (http://www.glbasic.com/forum/index.php?topic=5057.0). Confused me a lot tbw.