I don't know why I considered this because graphics is not one of my comfort zones. Fortunately, one of dodicat's comfort zones is graphics so I unashamedly 'pinched' his code from here.
When I had finished, the CPU load of the two approaches was pretty much the same; about 0.75% I was hoping to see my code with a smaller load. I decided that my code was not worth posting.
However, I could't get a very high frame rate from dodicat's code unless I reduced the System clock's timer interval. I did this by using my 'TimerInterval (Win10)'.
The reason for posting is that I had 'TimerInterval (Win10)' running when testing my code. If the resolution, second parameter of timeSetEvent, was set to less than 16 then the System clock's interval was set to the same value.
At MSDN the resolution is described as
No mention of the System clock.Resolution of the timer event, in milliseconds. The resolution increases with smaller values; a resolution of 0 indicates periodic events should occur with the greatest possible accuracy. To reduce system overhead, however, you should use the maximum value appropriate for your application.
At the PowerBASIC forum very nearly everyone uses a resolution of zero. There are some where the resolution is not zero and greater than 15.625ms. I have used resolutions greater than 15.625ms where the delay was large; 60000 for example. If the resolution is linked to the System clock then using a resolution in excess of 15.625ms will not not make a blind bit of difference because 15.625ms is as good as it can get.
With a resolution of zero I expected an interval of 0.5ms because my system will accommodate that. That did not happen - an interval of 1ms was used.
Some of you may have known that the resolution was linked to the System clock but it was news to me - we are after all using a multimedia timer. With speeds less than 16ms, but keeping the resolution at 16ms, the graphics certainly speed up and the System clock's interval is not changed. However, the graphics is a bit flaky and on some occasions the application stopped responding. To avoid that I introduced
Code: Select all
If speed < 16 Then resolution = speed\2
With 'speed = 1' then the resolution will be set at zero but we will get 1ms. Sometimes the screen locks up - we need a better resolution. So, speed is limited to 2ms. With a speed of 2 and resolution of 1 the graphics move pretty much as the fastest speed I can get from dodicat's code. The CPU load for both codes is now at about 1.25%
Somebody else must know that the resolution is linked to the System clock. It took a while but I found an article at Code Project which had a link to an old blog which said "timeSetEvent will call timeBeginPeriod to set the timer resolution to the resolution specified in the call to timeSetEvent." However, the blogger did not mention where he got that from. The blog mentioned that timeSetEvent was obsolete - the blog was written 12 years ago. Oh, dear. <laugh>
So, there we have it, further evidence of the Windows APIs 'dumbing down' on details.<smile>
So, does timeSetEvent have role to play in graphics code? Well, since I am not a graphics guy I am not qualified to make a judgement and really should not have stuck my nose in. I am going to hazard a guess and say no. If any graphics members reckon that it is a bad idea I should tell you that I already have a towel ready to throw into the ring. It was an interesting exercise and I learned something about timeSetEvent; even though it was by accident. I wonder how many of those at PowerBASIC, if any, realise that by setting a resolution of zero the System clock's timer interval is changed to 1ms.
For what it is worth here is the code.
Code: Select all
#include once "windows.bi"
#Include Once "win/mmsystem.bi"
Dim As Uint speed, resolution
Dim TimerID As Uint_Ptr
Sub DisplayProc( uTimerID As Uint, uMsg As Uint, dwUser As Dword Ptr, dw1 As Dword_Ptr, dw2 As Dword_Ptr )
Static x As Long = 10
Static y As Long = 10
Static dx As Long = 1
Static dy As Long = 1
x += dx : y += dy
If x<10 Or x>630 Then dx = -dx
If y<10 Or y>470 Then dy = -dy
Screenlock
Cls
Circle(x,y),10 'draw the ball
Screenunlock
End Sub
Screen 18
speed = 16 ' Reduce to speed up
If speed < 2 Then speed = 2
resolution = 16
If speed < 16 Then resolution = speed\2
TimerID = timeSetEvent( speed, resolution, Cast( LPTIMECALLBACK, @DisplayProc ), 0, TIME_PERIODIC )
Sleep
timeKillEvent TimerID
Sleep