Speed

Game development specific discussions.
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Speed

Post by deltarho[1859] »

badidea wrote:In blue, with 'fatal error' and a sad smiley?
That goes without saying. <wink>

On my machine, the following web browsers all settle down to 15.625ms: Firefox, FlashPeak Slimjet, Microsoft Edge and Internet Explorer 11. This has not always been the case.

On the other hand, go to YouTube and the resolution increases to 1ms. Added: So too with www.bbc.co.uk/news - they are still using Flash, tch, tch!

So, I do not see any online/offline 'stuff' with web browsers.

One way to change the resolution in Windows is too use one of my portable utilities, both copyrighted but no license. You can use them. <smile>

In this respect, Windows 10 differs to earlier platforms but you will not find any details at Microsoft. It took me a while to 'fathom out' what was going on. We can 'dial in' any resolution we like subject to the min/max allowable. I wrote 'TimerInterval (Win10)' to prove this and followed up with 'TimerInterval2 (Win10)'. Here is a screenshot of 'TimerInterval (Win10)', setting the resolution to 9.8765ms, alongside 'TimerInterval2 (Win10)'. It is not an exact science and why we get a reading of 9.8763ms.

Image

TimerRes was written a few years earlier for Win7 but will work to Win10. 'TimerInterval2 (Win10)' will not work with pre-Win10 and does not check the OS.

Image

TimerRes.zip
TimerInterval2 (Win10).zip

TimerRes radio buttons respond to a change in resolution and we change the resolution by clicking on a radio button.

'TimerInterval2 (Win10)' changes the resolution via the System Menu.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Speed

Post by dodicat »

badidea
You cannot put screensync along with regulate in my above code.
It renders regulate useless, you may as well omit regulate.
Google speed can be maintained offline with

Code: Select all


declare function settimer       alias "timeBeginPeriod"(as Ulong=1) as long
declare function freetimer      alias "timeEndPeriod"  (as Ulong=1) as long


Function Regulate(Byval MyFps As long,Byref fps As long) As long
    Static As Double timervalue,_lastsleeptime,t3,frames
    frames+=1
    If (Timer-t3)>=1 Then t3=Timer:fps=frames:frames=0
    Var sleeptime=_lastsleeptime+((1/myfps)-Timer+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    _lastsleeptime=sleeptime
    timervalue=Timer
    Return sleeptime
End Function


screen 18
dim as long fps,x=10,y=10,dx=1,dy=1
do
    x+=dx
    y+=dy
    if x<10 or x>630 then dx=-dx
    if y<10 or y>470 then dy=-dy
    screenlock
    cls
    draw string(100,100),"Framerate  " &fps
    circle(x,y),10
    screenunlock
    settimer
    sleep regulate(300,fps)
    freetimer
    loop until len(inkey)
       
This forces a 1 ms resolution in even the crappiest Window box from Ebay.<from the computer section>
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Speed

Post by badidea »

dodicat wrote:You cannot put screensync along with regulate in my above code.
I know, I only used regulate to update the fps value.
I meant screensync as an alternative for sleep, resulting in a nice 60 Hz in most cases.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Speed

Post by MrSwiss »

ScreenSync is useless nowadays, since we're no longer use Cathode-Ray-Tube-Screens ...
(no longer a ray trace-back (ray switched off), from bottom/right to top/left of screen)
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Speed

Post by badidea »

MrSwiss wrote:ScreenSync is useless nowadays, since we're no longer use Cathode-Ray-Tube-Screens ...
(no longer a ray trace-back (ray switched off), from bottom/right to top/left of screen)
Agreed, forget about screensync. I looked up some some my older game projects. Nowhere do I use screensync. Always sleep 1,1 in combination with screenlock/unlock. And e.g. x-position of the player, I update every loop with x += speed * dt. Where dt is the time between iterations (loops). So things should be independent on this 'interrupt' time resolution. Only when dt becomes too large (for whatever reason), weird things will happen (but this could probably be detected and handled properly if needed).
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Speed

Post by deltarho[1859] »

When I first got involved in the timer resolution I noticed that it took two ticks before timeBeginPeriod(1) took effect so used this before a 'Sleep 1' was required.

Code: Select all

TimeBeginPeriod(1)
Sleep 16
With dodicat's code

Code: Select all

settimer
Sleep regulate(300,fps)
freetimer
settimer is changing the resolution from 15.625ms to 1ms requiring, I thought, two ticks before the 1ms came into effect. No matter what regulate() came back with Sleep would have a resolution of 15.625ms.

However, this is clearly not the case. I have done some tests and found that timeBeginPeriod(1) takes effect immediately with Windows 10.

The two ticks saga was spotted when I was using Windows 7. I don't have access to Windows 7 now so cannot test dodicat's regulate() on that platform. If I am right then we will get a fps of 64 regardless of what we 'dial in' to regulate().

There is an answer to this but I don't want to go there just yet.

Will someone kindly test dodicat's code on Windows 7. The two ticks saga may also be true with Windows 8 and Windows 8.1 but I never had them.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Speed

Post by jj2007 »

With Win7-64, I see once Framerate 1, then Framerate 300 +/-1
Is this what you expected?
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Speed

Post by deltarho[1859] »

jj2007 wrote:Is this what you expected?
In a word, no.

Microsoft must have corrected the two ticks saga in one of their later updates. I did a lot of testing on this issue and the two ticks were invariably the case. Of course, they could not tell us about the change because they did not tell us about the two ticks in the first place. Chances are they did not realize until someone told them. I didn't tell them but I did give them a right slating in a post at PowerBASIC. Microsoft is a PowerBASIC customer so maybe someone at Microsoft saw my post. Probably not, but who knows? If they did they wouldn't get back to me after the 'verbal' I gave them. <smile>

Anyway, this is good news for dodicat's code which, incidentally, is a very clever piece of code.

I should add that had I not worked through dodicat's code I would have continued to use the 'Sleep 16' trick on Windows 10.

Thanks for testing for me jj2007.
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Speed

Post by deltarho[1859] »

The plot thickens.

Running dodicat's code as is, using timeBeginPeriod, but using 'Sleep regulate(1000,fps)' my fps 'tops out' at 800 fps. On the other hand if we comment settimer and freetimer and put settimer just before the Do Loop then I 'top out' at 500 fps.

If we comment the last edit then we get 64 fps, as expected. If I then run my 'TimerInterval (Win10)' and set a 1ms resolution then I 'top out' at 500 fps again. If I go to YouTube I 'top out' at 500 fps.

The first port of call must be the code within the Do Loop to see if anything there will throttle the fps, but I cannot find anything.

It would appear then the system is throttling. Perhaps it has taken exception to the application being given a resolution of 1ms, which, of course, means that the whole system is using a 1ms resolution for the application session because a change in resolution is system-wide. The thread scheduler does not like a 1ms resolution for too long because it switches tasks more often.

On my machine regulate() takes about 0.3 microseconds so bracketing it with settimer/freetimer does not give the system long enough to get upset.

I am, of course, guessing here but the moral seems to be to use settimer at the last minute, so to speak, and use freetimer at our earliest opportunity.

This is another reason I am glad I examined dodicat's code because with the two ticks saga, as was, I would not have dreamed of bracketing so tightly.
dodicat wrote:Google speed can be maintained offline with
With a tight settimer/freetimer bracketing the potential performance seems to be better than 'Google speed'.

Don't forget that I am Windows 10 and the above ramble mean not be true for earlier platforms.

BTW, besides Sleep and SleepX being affected by a 1ms resolution so is timeGetTime, timeGetSystemTime and timeSetEvent.
deltarho[1859]
Posts: 4308
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Speed

Post by deltarho[1859] »

@dodicat

Just a bit of fun and a thank you for Regulate. The attached unzips to 'dodicat's Regulate.exe'. This is a stripped down version of 'TimerInt (Win10)' (screenshot above) and only took a few minutes to knock out.

Usage: Run your original code, without time*Period, and use 'Regulate(1000,fps)'.

Now run 'dodicat's Regulate'. On opening, a default frame rate of 100 is set. The bouncing ball will now show a 100ish frame rate. Change the frame rate to 200, 300, 400 and 470 and click 'Set' or press Enter.

However, once we go beyond 470 'throttling' starts to 'kick in'. With a request for 1000 we get very close to the 500 ceiling found with TimerInterval2 (Win10) or YouTube. That is because we are setting a system-wide value as opposed to a tight settimer/freetimer.

Anyway, like I said, just a bit of fun. (56KB on disk)

Check out the Property Sheet. It is copyrighted but you can use it - no one else can. (Just kidding <smile>)

dodicat's Regulate.zip

Added: When you close your code don't leave 'dodicat's Regulate' running - it changes the timer resolution.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Speed

Post by dodicat »

Thanks Deltarho{}
That works well on Win 10.
I'll figure out how you did it later (try).
In the meantime I an on Linux,
I captured 40 Giga bytes of the hard drive on my old machine,
I got hold of Scientific Llinux (32 bit) live cd, and installed on the new partition to dual boot with XP (which I don't really use any more).
I have had my old box for many years, but it has quite a good spec really:

Code: Select all

  Architecture:          i686
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                2
On-line CPU(s) list:   0,1
Thread(s) per core:    1
Core(s) per socket:    1
Socket(s):             2
Vendor ID:             GenuineIntel
CPU family:            15
Model:                 4
Model name:            Intel(R) Xeon(TM) CPU 3.00GHz
Stepping:              3
CPU MHz:               3000.000
BogoMIPS:              5984.84
L1d cache:             16K
L2 cache:              2048K
[root@localhost ~]# 
So for all these years my old machine was actually 64 bit capable.
It has actually two seperate cpu's with hyperthread opotion, giving four cpu's if needed.
I have freebasic up and running.
The graphics seem a bit slow, but I'll maybe give them a hyperthread boost later (tweak the bios)
ITomi
Posts: 154
Joined: Jul 31, 2015 11:23
Location: Hungary

Re: Speed

Post by ITomi »

Hello everybody!

After a long time I started to make an FPS game in FreeBasic and I would like it should be good in terms of speed, that is let it at similar speed both on slow and swift computers.
Based on previous experience I understood that for this I need to know the delta time and the fps of the program, but it is not yet clear for me, why not smooth the movement in this sample code on the basis of using delta time and fps?
Just because if I insert a "Sleep 1000" command at the last line, then it will be too slow. But how can I control my program without the "Sleep" command?
So, without "Sleep" the program will be too fast, with "Sleep" it will be too slow, beyond that I use delta time and fps too.
Then what should I do to complete the program? Is it totally wrong?

Code: Select all

dim as single dt
dim as single LastTime = Timer
dim as single ActTime = Timer
dim as single StartTime = Timer

dim as integer fps=0,frame=0,xplace=1
const speed=4
	
do
        cls
        
	ActTime = Timer
	dt = ActTime - LastTime
	LastTime = ActTime
        
        if timer-StartTime>1 then
            fps=frame
            StartTime=timer
            frame=0
        else
            frame+=1
        end if
		
		Locate 1,1 
		Print "Actual time: " & ActTime
		Print "dt: " & dt
        print "FPS: " & str(fps)
        print "dt*speed: " & str(dt*speed)
        print "dt*fps*speed: " & str(dt*fps*speed)
        
        locate 20,xplace : print "O"
        xplace=xplace+(dt*fps*speed)
        if xplace>80 then xplace=1
        
        'Sleep 1000
		
loop until Inkey <> ""
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Speed

Post by dodicat »

You can stabilize the speed by altering the sleep time between frames using a function (regulate)

Code: Select all



 #define map(a,b,x,c,d) ((d)-(c))*((x)-(a))/((b)-(a))+(c)
 #define inbox (mx>125) and (mx<475)' and (my>300) and (my<350)
 #define incircle(cx,cy,radius,x,y) (cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
 
 #macro display
    fr=map(125,475,cx,10,65)
    screenlock
    cls
    draw string(20,20),"Actual Framerate     = " &fps
    draw string(20,40),"Requested Framerate  = " &fr
    draw string(20,60),"Sleeping time        = " &sleeptime
    draw string(100,280),"10"
    draw string(480,280),"65"
    draw string(250,280),"<--slider-->"
    angle+=.1
    drawline(600,200,.2*sin(angle)-pi/2,300,4)
    line(100,300)-(500,350),2,bf
    circle(cx,cy),25,5,,,,f
    screenunlock
    
    sleep sleeptime,1
    
#endmacro

#macro mouse
Dim As Long x=mx,y=my,dx,dy
While mb = 1
    Display
    Getmouse mx,my,,mb
    If inbox Then
        If mx<>x Or my<>y  Then
            dx = mx - x
            dy = my - y
            x = mx
            y = my
            cx=x+dx
            if cx<125 then cx=125
            if cx>475 then cx=475
        End If
    End If
Wend
#endmacro

sub drawline(x as long,y as long,angle as single,length as long,col as ulong)
    var x2=x+length*cos(angle)
    var y2=y-length*sin(angle)
     line(x,y)-(x2,y2)
     circle(x2,y2),10,6,,,,f
end sub

Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
    Static As Double timervalue,_lastsleeptime,t3,frames
    Var t=Timer
    frames+=1
    If (t-t3)>=1 Then t3=t:fps=frames:frames=0
    Var sleeptime=_lastsleeptime+((1/myfps)-T+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    _lastsleeptime=sleeptime
    timervalue=T
    Return sleeptime
End Function



screen 19
dim as long mx,my,mb
dim as long cx=125,cy=325,fps,fr,sleeptime
dim as single angle,pi=4*atn(1)
do
    getmouse mx,my,,mb
    
    display
    
    if incircle(cx,cy,25,mx,my) and mb=1 then
        mouse
        end if
   
    sleeptime= regulate(fr,fps)
   
    loop until len(inkey) 
You can increase framerate in windows by using timebegin/end period.
This is because the resolution (sleep 1) is now between 1 and 2 milliseconds, otherwise it is about 15 milliseconds.

Code: Select all

 #ifdef __FB_WIN32__
declare function settimer       alias "timeBeginPeriod"(as Ulong=1) as long
declare function freetimer      alias "timeEndPeriod"  (as Ulong=1) as long
#endif

 #define map(a,b,x,c,d) ((d)-(c))*((x)-(a))/((b)-(a))+(c)
 #define inbox (mx>125) and (mx<475)' and (my>300) and (my<350)
 #define incircle(cx,cy,radius,x,y) (cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
 
 #macro display
    fr=map(125,475,cx,10,350)
    screenlock
    cls
    draw string(20,20),"Actual Framerate     = " &fps
    draw string(20,40),"Requested Framerate  = " &fr
    draw string(20,60),"Sleeping time        = " &sleeptime
    draw string(100,280),"10"
    draw string(480,280),"350"
    draw string(250,280),"<--slider-->"
    angle+=.1
    drawline(600,200,.2*sin(angle)-pi/2,300,4)
    line(100,300)-(500,350),2,bf
    circle(cx,cy),25,5,,,,f
    screenunlock
     #ifdef __FB_WIN32__
    settimer
    #endif
    sleep sleeptime,1
     #ifdef __FB_WIN32__
    freetimer
    #endif
#endmacro

#macro mouse
Dim As Long x=mx,y=my,dx,dy
While mb = 1
    Display
    Getmouse mx,my,,mb
    If inbox Then
        If mx<>x Or my<>y  Then
            dx = mx - x
            dy = my - y
            x = mx
            y = my
            cx=x+dx
            if cx<125 then cx=125
            if cx>475 then cx=475
        End If
    End If
Wend
#endmacro

sub drawline(x as long,y as long,angle as single,length as long,col as ulong)
    var x2=x+length*cos(angle)
    var y2=y-length*sin(angle)
     line(x,y)-(x2,y2)
     circle(x2,y2),10,6,,,,f
end sub

Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
    Static As Double timervalue,_lastsleeptime,t3,frames
    Var t=Timer
    frames+=1
    If (t-t3)>=1 Then t3=t:fps=frames:frames=0
    Var sleeptime=_lastsleeptime+((1/myfps)-T+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    _lastsleeptime=sleeptime
    timervalue=T
    Return sleeptime
End Function



screen 19
dim as integer mx,my,mb
dim as long cx=125,cy=325,fps,fr,sleeptime
dim as single angle,pi=4*atn(1)
do
    getmouse mx,my,,mb
    
    display
    
    if incircle(cx,cy,25,mx,my) and mb=1 then
        mouse
        end if
   
    sleeptime= regulate(fr,fps)
   
    loop until len(inkey) 
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Speed

Post by grindstone »

Generating a constant and precise delay is quite simple:

Code: Select all

Dim timecomp As Double

timecomp = Timer + .001 'add requested delay in (fraction of) seconds
Do While Timer < timecomp
	'waste some time...
Loop
paul doe
Moderator
Posts: 1733
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Speed

Post by paul doe »

ITomi wrote: Mar 06, 2023 10:16 ...
After a long time I started to make an FPS game in FreeBasic and I would like it should be good in terms of speed, that is let it at similar speed both on slow and swift computers.
...
Check these discussions (old, but still valid today):

https://dewitters.com/dewitters-gameloop/
https://gafferongames.com/post/fix_your_timestep/

Dodicat's function is a variant of the 'FPS dependent on Constant Game Speed', described in the first link.

Here's also a very interesting discussion about frame tearing/stuttering:

https://medium.com/@alen.ladavac/the-el ... 8f899aec92
Post Reply