How to use a 'timer/timing device' for fast refresh

Hello Everyone,

This is a general question that I keep bumping into on the Windows 10 OS with Xojo, what kind of timer/timing device can I use to get fast refresh rates and perform data updates to the UI?

I am able to have fast refresh rates for making games which involve higher frames-per-second of greater than 15 fps when I use a thread, which can literally get into the hundreds of refreshes per second, but I keep running into the ThreadAccessingUIException for updating mouse positions, and updating data on the Window.

A timer on Windows is not an option due to the resolution of about 15 ms

[quote]Limitations on Microsoft Windows
On Windows, the standard system timer is used which has a default resolution of about 15ms.[/quote]

When more objects and drawings are added to the OpenGLSurface or Canvas, then the Xojo program considerably slows down with a timer.

Is there another timer/timing device that can be used with Xojo for fast graphics drawing with the Canvas/OpenGlSurface, because the amount of workarounds that are needed for a half-decent refresh rate for graphics are getting quite difficult for even the simplest of programs.

Thanks for your thoughts…

15 ms is already slightly above 60 frames per second. But indeed long operations will slow it down.

I wonder how fast you can get by calling me.invalidate or event me.Refresh from the end of the Paint event itself. You need a flag or something to stop that potentially infinite loop, but it should be the shorter time available between redraws.

I got the answer.

[code] static i as integer
static previousMicrosecond as double = Microseconds
system.debuglog format(Microseconds-previousMicrosecond, “###”)

g.drawrect(i, i, 10,10)

i = i + 1
previousMicrosecond = Microseconds
if i < 150 then me.Invalidate [/code]

Most of the cycles are done in 50-70 MICROseconds.

Some take longer line 100, 300, or even 1200, probably because the system needs to yield. But yet, we are talking 1.2 Millisecond !

Of course my drawing is minimal, so more complex will take longer, but you will probably need to SLOW THIS DOWN to keep to 100 fps…

At any rate, here is a timer that goes way under 15 ms. You can simply use a canvas as fast timer BTW.

I have made a more elaborate project, using one canvas as fast timer, the other to draw.

i as integer is a window property

Canvas1

[code]Sub Paint(g As Graphics, areas() As REALbasic.Rect)

static previousDrawing as double = Microseconds

if Microseconds-previousDrawing >= 10000 then
Canvas2.Invalidate
previousDrawing = Microseconds
end if

if i < 320 then me.Invalidate

End Sub
[/code]

Canvas2

[code]Sub Paint(g As Graphics, areas() As REALbasic.Rect)
g.fillrect(i, i, 30,30)

i = i + 1

End Sub
[/code]

Michel, as always, thank you for your kind and helpful replies. Was there any issues receiving keyboard input when the Canvas has the posted code in Canvas1 and Canvas2? I may be doing something wrong, as I find that having the update loop then begins to prevent/ignore keyboard input. An example is when I am pressing w,a,s,d to change the position of a camera in the OpenGL world, the key buffer tends to sometimes fail to work at a rapid speed while the OpenGLSurface control is quickly refreshing. The reason for adding a Thread is to allow quick refreshing of the Control while accepting keyboard input. This is where I run into the issue of a thread and the ThreadAccessingUIException.

Below is code that I am using to achieve a consistent target framerate of 60 frames-per-second in a thread. This loop works well except for the ThreadAccessingUIException. When placing this code directly in the render event handler, the keyboard buffer seems to significantly lag.

[code] //Create variables
Dim LastTime, CurrentTime, DeltaTime as UInt32
//Convert FPS to Microseconds
//MSPF = Microseconds per frame
Dim MSPF as UInt32 = 1/TargetFPS*1000000

LastTime = Microseconds //read the current time
Do Until MyPressedKey = “q” //quit
CurrentTime = Microseconds //Read the time now
DeltaTime = CurrentTime-LastTime //Determine how much time has passed
If (DeltaTime > MSPF) then //If the amount of time is more than the target FPS rate
AnAngle = AnAngle + 1 //set the angle 5 more degrees to turn a model
OpenGLSurface1.Render //Draw the cube again
LastTime = Microseconds // Set the current time to now
End If
Loop[/code]

Thank you.

If you need a timer on Windows with more than 60 fps, please try our TimesMBS class

https://www.monkeybreadsoftware.net/class-timermbs.shtml

Eugene, as far as I can tell, there is absolutely no slow down because of the paint events loop. Note that it behaves exactly like a regular timer, and yields like any other timer.

I added a TextArea, and typing is as smooth as ever.

I believe you can adapt the code you posted above rather easily.

Thanks Michel. I will give it another try.

How do you get the keys in MyPressedKey ?

The timer code that I posted is in a thread, and reading the Key in the KeyDown event updates the global MyPressedKey string value. When my code is placed in the OpenGLSurface Render control, then the loop seems to not update the Key String because most of the CPU time is spent within the timing loop.

You may want to use AsyncKeyDown instead. It is probably less sensitive.

I also believe your present code using a tight Do Loop is locking the CPU as it never yields.

In the timer canvas I suggest, or TimerMBS, you would not have the same issue since the loop if needed would take place in a succession of events, not in a single one.

I have been working with Xojo for many years, and I didn’t know that AsyncKeyDown existed until you mentioned it. Thanks Michel!