Author Topic: Consistent Framerate  (Read 8646 times)

0 Members and 1 Guest are viewing this topic.

Offline Xalthorn

  • Amiga 1200
  • ****
  • Posts: 331
  • Karma: 100
    • View Profile
Consistent Framerate
« on: August 22, 2008 »
I'm sure I've seen a thread about this, but I can't find it.

How do people maintain a consistent frame rate in freebasic across different computers?

I've had code before where if I run it full screen it runs normally, but if I run it in a window it goes mental.

I might have missed the obvious, but is there a way to check if we've had a vertical refresh or some other standard method of maintaining consistency?

I know we can read the timer and then have a little loop at the end of our main loop to wait until the timer has increased by a certain amount, but it just feels clunky.
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Consistent Framerate
« Reply #1 on: August 22, 2008 »
It's impractical to force a maximum refresh rate by waiting.
Instead just "skip" the frames you couldn't display because you were busy drawing the last one.
Look how much time has passed since the last frame and move all objects scaled by that time-delta.
Unluckily there's no realiable way to count the vsyncs, but those wouldn't help much anyway because the refresh-interval varies from pc to pc.
Challenge Trophies Won:

Offline mazemaker

  • C= 64
  • **
  • Posts: 28
  • Karma: 11
    • View Profile
Re: Consistent Framerate
« Reply #2 on: August 22, 2008 »
put this in your main loop

Code: [Select]
    do until nextupdate>timer

{ game logic goes here }

        nextupdate=nextupdate+mydelay
    loop

{ rendering goes here}


Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Consistent Framerate
« Reply #3 on: August 22, 2008 »
Xalthorn, The delta timing method I always use is just to base all the movement off the difference between the internal timer at the start of the main loop and the end.

Unfortunately you can't rely on people to have v-sync enabled, and even if you use opengl to do your programming, you can request a refresh rate but there doesn't seem to be a straight forward way of ensuring that it will be set.

I can't really see how this works;

put this in your main loop

Code: [Select]
    do until nextupdate>timer

{ game logic goes here }

        nextupdate=nextupdate+mydelay
    loop

{ rendering goes here}


Seems like it wouldn't work well.

So just do what Hellfire says..

By the way if you are making scrolling texts or anything smooth pixelwise scrolling  then you'd do well to use floating point variables to keep track of the offset because otherwise you'll end up with some horrible glitches using integers and delta timing.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Consistent Framerate
« Reply #4 on: August 23, 2008 »
I think it would work, and I've seen people do it.

Imagine you wrote your code on a computer that ran at 60Hz all the time.  That way you could avoid doing any time based calculations and just assume that the movement is going to happen in 16.67milliseconds.
If you then end up running on a slower machine, say it was only doing 20fps, then you could call your movement code 3 times each frame and only render once.  The problem comes that the slower your machine runs, the more times you have to call the movement code, which makes the machine run even slower.  So there does come a point where it breaks.

The technique most of us use, which Shockwave calls Delta Timing, is to assume that the frame you are calculating will take roughly the same amount of time as the last frame you drew.  So, if you time how long it takes to do each frame you can use that time as an input into the next frame's physics calculations.
The problem with this technique is that now your movement is non-linear in time, which can make things like collision detection difficult.  It can also make some time-based calculations unstable if your delta time goes outside some sensible range.  One way round that is to insist that if your frame only took 1ms to render then you should probably be friendly to the OS and just sleep for 10ms or so.  I much prefer this technique though.

Jim
Challenge Trophies Won:

Offline Xalthorn

  • Amiga 1200
  • ****
  • Posts: 331
  • Karma: 100
    • View Profile
Re: Consistent Framerate
« Reply #5 on: August 28, 2008 »
Argh!

The reason I'm looking into this is because I'm working on another entry for the reduced res challenge and running it in a window was making it run way too fast.  With some fiddling (simply reading the timer at the start of the loop and then waiting until the timer was at least 0.02 seconds advanced before starting again to keep it at 50 frames a second, in theory) it's running better.

I then went back to watch my xalboy and bluegold entries again and they're going ballistic, way too fast.  I know I installed some directx update to try and watch someone elses demo, and I daresay windows saw fit to update itself with some stuff, but this is ridiculous.

I tried to add the same delay to those demos and the effect I'm now getting is that it races, pauses, races, pauses, and so on which is arguably more annoying to watch.

Can I ask how fast (insane?) the xalboy and bluegold demos run?  They should be speedy, but watchable.  In the xalboy demo, the bubbly plasma should be smooth not ... mad, and the dragon walking should be a fair pace that you'd expect to see in a gameboy game, not throwing as many frames to the screen as possible, same with the clouds on the title screen.

I also ran some demos by other people and they seem to be having a similar issue.  I'm hoping it's just my machine having a bit of a fit, but this is my nightmare with PC coding, an inconsistent platform :(
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Consistent Framerate
« Reply #6 on: August 28, 2008 »
Quote
Code: [Select]
    do until nextupdate>timer

{ game logic goes here }

        nextupdate=nextupdate+mydelay
    loop
that's rather bungling.
let's say you implemented the "game logic" (update interval) to run fine at 120hz.
how often do you repeat the loop at a refresh-rate of 70hz?
that's basically the essential problem when porting console-games from ntsc (60hz) to pal (50hz) - and it fails frequently.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Consistent Framerate
« Reply #7 on: August 28, 2008 »
Yeah, you end up stuttering, based on common multiples of 70 and 120...83 frames of 1 and then 1 frame of 2.  Nasty, and you get bumping, kind of like when you try to convert a 24fps video to 30fps.

Xalthorn, your stuff ran OK, which is cool, if you have real problem can you start another thread about it?

Jim

Challenge Trophies Won:

Offline mazemaker

  • C= 64
  • **
  • Posts: 28
  • Karma: 11
    • View Profile
Re: Consistent Framerate
« Reply #8 on: August 29, 2008 »
you probably mis-understand how my code works.

it's called frameskipping, and gives the appearence of the logic being updated regularly.

if your video refresh-rate is 70hz, then i take that to mean that your rendering takes about 14 millisecs. at a logic rate of 120hz, the 'mydelay' value is about 8. that means there will be an average of 1.75 logic updates per video update. if the video happens to take longer, then the logic will be updated more times, depending on how long the video update took to complete.

as long as the logic update code doesn't take longer than <mydelay> millisecs, it works great. plus it's numerically stable, unlike the delta time method. also, it's easier to control your logic update frequency.



Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Consistent Framerate
« Reply #9 on: August 29, 2008 »
Nah, it's pretty clear that the intention is to get the average number of updates as you say...but the problem is that on any given frame there must be a whole number of updates, so that if the software is running at 2/3rd speed, there will be 2 updates on even frames and 1 update on odd frames.  That will look a bit odd, don't you think?

As I have already said, you do get the numerical stability and that is a big plus for your technique, but you lose the ability to move anything linearly if you are not running at full frame rate.  It's not that you're wrong, not at all, it's that it's important to know the pros and cons of the possible techniques.  Thanks for bringing it up so we can talk about it :)

Jim
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Consistent Framerate
« Reply #10 on: August 29, 2008 »
Hi Mazemaker,  thanks for clarifying that, it works how I thought :)

The only really satisfactory way of doing this is to use delta timing as far as I am concerned.

I have attached a recent remake I just released, this uses delta timing for everything except the starfield.

If you run it in windowed mode and experiment with different refresh rates it should make very little difference to the movement pattern of the bobs and the speed of the scroller.

These are classic effects where glitches would be really noticeable.

Here is the main loop from that remake:

Code: [Select]
ANIMTIMER=TIMER
WHILE (GETASYNCKEYSTATE(VK_ESCAPE) <> -32768 AND PTC_GETLEFTBUTTON = FALSE)    
    
    GXA=XAR
    GYA=YAR
    DELTA=TIMER
    XV=XV+(GXA*MOVE)
    YV=YV-(GYA*MOVE)
    IF TIMER-ANIMTIMER>=.015 THEN
        
                    ANIM=ANIM+1
                    IF ANIM>36 THEN ANIM=1
                    ANIMTIMER=TIMER
    END IF
    IF TIMER-KEYD>=.1 THEN KEYBOARD()
    DRAWSTARS()
    DRAWGLOBES()
    SCROLLER()
    PTC_UPDATE@BUFFER(0)
    ERASE BUFFER
    SLEEP 2
    MOVE=((TIMER-DELTA)*200)+.00001
WEND
END

The command "TIMER" returns the value held in the internal timer as a double so it's really accurate.
The variable "ANIMTIMER" is concerned with limiting the animation to 50fps (its' speed on the Amiga)

A variable called "MOVE" is calculated at the end of each loop, this is a factor for movement since it takes into account how long the last frame took.

hth :)
« Last Edit: August 29, 2008 by Shockwave »
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Consistent Framerate
« Reply #11 on: August 29, 2008 »
Sorry Jim, I was replying at the same time as you!
Shockwave ^ Codigos
Challenge Trophies Won:

Offline mazemaker

  • C= 64
  • **
  • Posts: 28
  • Karma: 11
    • View Profile
Re: Consistent Framerate
« Reply #12 on: August 29, 2008 »
ok so for smooth movement, the time delta is probably best. especially if it's used to interpolate, not just increment.

and for timing things like frame animation, and more complex movement (inertia, some bounciing balls with gravity, acceleration etc), frameskipping is better.

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2757
  • Karma: 493
    • View Profile
    • https://www.rbraz.com/
Re: Consistent Framerate
« Reply #13 on: August 29, 2008 »
@Xalthorn: the best way to archive this is using high performance counter/frequency, take a look here:
http://www.geisswerks.com/ryan/FAQS/timing.html
Challenge Trophies Won:

Offline Xalthorn

  • Amiga 1200
  • ****
  • Posts: 331
  • Karma: 100
    • View Profile
Re: Consistent Framerate
« Reply #14 on: August 30, 2008 »
Thanks for that link rbz and thanks for the responses folks, time to do some experimenting with another demo of sorts I think.  Maybe something with things that are moving along a predictable path where jumps will be noticeable.
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Consistent Framerate
« Reply #15 on: August 30, 2008 »
and for timing things like frame animation, and more complex movement (inertia, some bounciing balls with gravity, acceleration etc), frameskipping is better.

I have had exactly the same problem!

Just out of interest, I was delta timing other stuff but what I did in the end was to use a sine wave and if sin (theta) produced a negative result I just inverted the sign which gave a perfectly consistent bounce no matter what the refresh rate (ok I admit it's a very specific example and not practical in all situations).

Thanks for that link rbz and thanks for the responses folks, time to do some experimenting with another demo of sorts I think.  Maybe something with things that are moving along a predictable path where jumps will be noticeable.

There's another comp on the horizon where this will be really significant if you're interested :)
It's the Amiga remake comp and thanks to Rbz the prize fund is doubled.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Xalthorn

  • Amiga 1200
  • ****
  • Posts: 331
  • Karma: 100
    • View Profile
Re: Consistent Framerate
« Reply #16 on: August 30, 2008 »
Thanks for that link rbz and thanks for the responses folks, time to do some experimenting with another demo of sorts I think.  Maybe something with things that are moving along a predictable path where jumps will be noticeable.

There's another comp on the horizon where this will be really significant if you're interested :)
It's the Amiga remake comp and thanks to Rbz the prize fund is doubled.

I'd like to have a play with that, if only to investigate how things were done, but I really don't expect to place in that one.  Won't stop me trying though ;)
Challenge Trophies Won: