Qbasicnews.com

Full Version: A faster frame rate using TIMER
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
What can you show me, that I can use, to get a faster Frame Rate to run the animations in my Game Program?

Is there something out there that can make the delay faster than .001?

Delay = .001
t = TIMER


DO

IF TIMER - t > Delay THEN
t = TIMER

"GAME CODE"

END IF

LOOP
Timer gets innacrrurate at around 0.0186 (or is it 0.00186?)


Here's a dynamic FOR/NEXT delay I made for MOoRPG:
Code:
SCREEN 13
fps! = TIMER
updFPS! = TIMER
delayFN& = 10000 'Set a dummy starting value
desiredFPS% = 20 'Set the desired FPS

DO 'Mainloop


'Do all the game/program stuff here, such as draw, get user input whatever.
FOR a = 0 TO 1000 'just a dummy thing
PSET (320 * RND, 200 * RND), 256 * RND
NEXT



LOCATE 1, 1: PRINT "FPS: "; fps$, "Delay:"; delayFN& 'print the FPS and delay out

FOR blipp& = 1 TO 2 'This is the actuall delay
FOR dada& = 1 TO delayFN&
NEXT
NEXT

fps& = fps& + 1
IF TIMER - updFPS! > 1 OR TIMER - updFPS! < 0 THEN
IF TIMER - fps! <> 0 THEN
  fps$ = LTRIM$(RTRIM$(STR$(CINT(fps& / (TIMER - fps!)))))

  delayFN& = delayFN& * ((fps& / (TIMER - fps!)) / desiredFPS%)'Adjust the delay

  IF TIMER - fps! > 3 OR TIMER - fps! < 0 THEN fps! = TIMER: fps& = 0
   'reset every 3 seconds,
   'to get a better value,
   'average get's more and
   'more innacurate as the
   'program runs, resetting
   'prevents this.
   'This can be removed to
   'create a smoother FPS
   'rate.

END IF
updFPS! = TIMER
END IF
LOOP WHILE INKEY$ = ""'Exit on keypress

You might want to store the delayFN value in a file, to avoid the peek or plumet in FPS at start.


As you can see it requires some code, and uses the TIMER to work, but the actuall delay can be very small, and accurate. Although this goes for periods of time, not momentary readings.

FPS might get to 15, or even 25, but will on average be 20 (in the example above that is)


Note that the first few seconds (unless loading up an old delayFN value) can be insanely high or low.
This is another reason for the higher frame rate I need.

The following program has an array called box in which I use x and y coordinates for numbers 1 through whatever I have. This array I use to tell the computer where I am in the game.

The PUT statement then needs x and y coordinates in steps of 16 in order to place the graphic on the screen correctly. In this case it is a Blue Box that I call: Blue Tag

It is a 16x16 graphic that I BSAVEed and BLOADed for this program.

I'm having the program place the Blue Box randomly on the screen until the desired screen area I want to cover is then covered.

The frame rate I use is either too slow or too fast or something because I can't control the speed at which it runs.

I want this game to run on any speed computer and that is why I am using a timer based Frame Rate.

When I set my Delay to .001 , it is still too slow and that is why I'm looking for a faster Frame Rate.


z = 0
FOR y = 0 TO 176 STEP 16
FOR x = 3 TO 18
z = z + 1
Box(x, y / 16) = z
NEXT x
NEXT y

z = 0

DO

j = INT(RND * 19)
k = INT(RND * 12)

SELECT CASE j
CASE 1
j = j + 2
CASE 2
j = j + 1
END SELECT

IF Box(j, k) <> 0 THEN
z = z + 1
Box(j, k) = 0
PUT (j * 16, k * 16), Blue.Tag, PSET
END IF
i$ = INKEY$
LOOP UNTIL z = 192
For loops are inconsistent, especially if you have windows or other programs running because the computer can speed up and slow down. Plus, you have to spend at least a second or two to build up an accurate for loop count.
Code:
FUNCTION CLOCK&
  ' Get the number of timer ticks at
  ' 0000:046C

  DEF SEG = 0
  Ticks& = PEEK(&H46C)
  Ticks& = Ticks& + PEEK(&H46D) * 256&
  Ticks& = Ticks& + PEEK(&H46E) * 65536&
  DEF SEG

  ' Latch the counter and obtain the PIT
  ' countdown status.
  OUT &H43, &H4
  LSB = INP(&H40)
  HSB = 255 - INP(&H40)

  ' Compute the CLOCK& value
  CLOCK& = Ticks& * 256 + HSB
END FUNCTION

'to test it:
CLS
DO
  timerVal! = TIMER
  clockVal! = CLOCK / 4660.859#
  LOCATE 1
  PRINT USING "CLOCK: #####.###"; clockVal!
  PRINT USING "TIMER: #####.###"; timerVal!
LOOP UNTIL LEN(INKEY$)

This refreshes the system timer, which ticks every 2.15x10^-4 seconds. Should be accurate enough for all rights and purposes.
HOWEVER, there is a chance the timer will be off by 1/18.2 (standard refresh) seconds if you're running it in Windows.

There are some other cool ways around the timer conundrum, including an interrupt placed by Windows that allows dos programs to access a timer control, which ticks every millisecond. I've lost the link to it though. Ideally, you'd have both timer solutions and detect Windows at the start of the program, though that's a bit far.
1/18.2 = 0.0549

Which is quite much, a FOR/NEXT is extremely accurate (if done properly, and dynamicaly updtaed, just like my code)


When using the common:
DO: LOOP UNITL Delay => DesiredDelay

You get a lot of slowdown, average my computer goes through that is ~0.018

And if you want a delay of 0.001, then it's clearly not accurate enough.

The above is true for both TIMER and CLOCK&

That's why I decided to use FOR/NEXT


It has been tested on quite a few computers now, and if you store the old delayFN value, you won't get more off then at most, 25% (unless you are willingly slowing down your system, or running like a million things at the same time, which will slowdown all things)

But even so, the max offtime would be 2 sec.


And the off FPS is, like i said, rarely more then 25%.



I know FOR/NEXT should be avoided at all cost, because being inconsistent and all, but try it, you'll be surprised.


With the algo I'm using I can get the time it takes to perform a FOR/NEXT, down to where it takes exactly (it varies and updates automatically) 0.001 seconds.
I'm not quite sure I understand what you mean by using the FOR and NEXT.

I know from using the for and next statements that it goes a certain speed for different speed computers which is exactly what I don't want.

I want some frame rate I can use in my program that can run the same speed. In other words if I programmed a frame rate for a 486 then I want that same frame rate speed to run the same speed on a Pentium on up.

Unless any of these codes can live up to that then I'm looking for a program code that can.

I do want it to be as accurate as possible even if I do need to use a .Lib for it. I just hope it isn't too big but if that's the only thing that I can get to do this then so be it.
IMO, for a game, where you want a stable FPS, the go with the code i posted.

It works fine, and is dynamic, speed will be guaranteed to be the same.


The windows timer (highly accurate) that jofers speak of is incompatible with some windows versions (can't remember if it's XP, 98 or some other, damit)


And the CLOCK& way is just as off as TIMER when it comes to small values.


I use the code i posted in MOoRPG, and it works fine, FPS is average 30, which is just what it's supposed to be. Tested on 6 different machines, most off was 15, and 46 (This will get even lower later, I have some ideas on how to fix it)

But it was only off for 1 or 2 seconds, after that it was pretty much stable on around 30 (28 to 32, but you can never get away from fluktuations, no matter what you use)


The thing about the code i posted is that it automatically adapts to the computer it is being runned on.


Try it.
Ok! I'll give it a try but be prepared to help me along while I do it. I tend to not get it at first and then after awhile I end up understanding it ; it just takes me awhile than others who catch on to all of this faster.

8) Be see'in you around. Later
Quote:You might want to store the delayFN value in a file, to avoid the peek or plumet in FPS at start.

What do you mean by this?
When the program/Game ends, you store that value in a file.

[syntax="QBASIC"]'Initialize the game:
Open "File.txt" for append as #1 'open file, creating if it does not exist
lo& = lof(1) 'just check so it exists, this get's the size of the file.
close #1 'close it again

if lo& =0 Then ' File does not exist.
delayFN = 1000 ' default value
Else 'File exist
Open "File.txt" for input as #1 'open it so we can read
Input #1, delayFN 'read the old delayFN value
Close #1 'close the file
End If
'Done initializing, now playing Tongue
'[Game code, and the for/next delay thingy here]


'Game over, or user quit, or whatever:

'Store the value
Open "file.txt" For output as #1 'open the file, clearing it
print #1, delayFN 'store the value
Close #1 'close the file
[/syntax]
Pages: 1 2