Hi Zak,
thanks for sharing your discoveries!
I would add one more advice, which makes possible to not use SLEEP at all, and still have full control.
The approach with:
Has the general problem of being too dependant on performance on given machine.' -- This results in increasing x by 0.1 once per FRAME x = x + 0.1
If the script runs at 60FPS, holding the key for 1 second will make the object moved by 0.1 * 60 = 6 units
If the script runs at 1000FPS (yes, it is possible), holding the key for 1 second will make the object moved by 0.1 * 1000 = 100 units.
If we take unit as meter, it is difference of 6 meters vs. 100 meters... quite a lot
The approach used for example in computer games, or other application, is performance synchronised movement.
This very simple technique consists in measuring the actual time the frame took to render, and scaling the movement by this.
You can achieve this by measuring the time one frame takes to render on your own, for example using the new cTimer class, or HiResTimer_Get commands.
Even simpler is to use build in TBGL_GetFrameRate function, which will return a number reporting how many frames per second the loop can run.
There is simple relation between these two, where:
The second approach can be applied quite simply in two steps:timeSpentRenderingFrame = 1 / frameRate ' -- in seconds
frameRate = 1 / timeSpentRenderingFrame ' -- in frames per second
- retrieving the current frame rate once per render cycle:
- scaling the movement by this value:frameRate = TBGL_GetFrameRate
This approach is independent on PC performance, and will most likely result in the same speed of movement across different PCs.' -- This means holding the key will result in movement of 0.1 meter per second x = x + 0.1 / frameRate
I wrote "most likely", because the measurement works with 1 frame old data, so in case the frame rate changes a lot, it can introduce slight imprecision. This can be filtered out by using more advanced math mechanisms (various filters, using average and so on).
I modified the first example to demonstrate this and slightly modernised the used commands. The movement is now done in way it occurs at 1 m/s and the rotations at 90 degrees/second, but this can be of course tuned as you wish:
Uses "TBGL" Dim hWnd As DWord Dim Distance As Single = 3 Dim Rot_Y As Single = 45 hWnd = TBGL_CreateWindowEx("move the light: z_coord:WS xy_coord: DA, rotate: arrow keys >,<", 640, 480, 32, %TBGL_WS_WINDOWED) TBGL_ShowWindow Dim LightX, LightY, LightZ As Single LightX = 0: LightY = 1:LightZ = 0 TBGL_UseLighting TRUE TBGL_UseLightSource %GL_LIGHT0, TRUE TBGL_SetLightParameter %GL_LIGHT0, %TBGL_LIGHT_DIFFUSE, 1, 1, 1, 1 TBGL_SetLightParameter %GL_LIGHT0, %TBGL_LIGHT_POSITION, LightX, LightY, LightZ, 0 TBGL_ResetKeyState() ' Resets ESC key status before checking Dim frameRate As Double While TBGL_IsWindow(hWnd) frameRate = TBGL_GetFrameRate TBGL_ClearFrame ' Camera settings TBGL_Camera 0, Distance, Distance, 0, 0, 0 TBGL_Rotate Rot_Y, 0, 1, 0 TBGL_SetLightParameter %GL_LIGHT0, %TBGL_LIGHT_POSITION, LightX, LightY, LightZ, 0 TBGL_Color 255, 255, 255 TBGL_Box 0.5, 0.5, 0.5 TBGL_PushMatrix TBGL_Color 255, 128, 0 TBGL_Translate LightX, LightY, LightZ TBGL_Sphere 0.1 TBGL_PopMatrix tbgl_DrawFrame If TBGL_GetWindowKeyState(hWnd, %VK_RIGHT) Then Rot_Y -= 90/FrameRate ' 90 degrees/second If TBGL_GetWindowKeyState(hWnd, %VK_LEFT) Then Rot_Y += 90/FrameRate If TBGL_GetWindowKeyState(hWnd, %VK_W) Then LightZ -= 1/FrameRate ' 1 meter/second EndIf If TBGL_GetWindowKeyState(hWnd, %VK_S) Then LightZ += 1/FrameRate ' 1 meter/second EndIf If TBGL_GetWindowKeyState(hWnd, %VK_A) Then LightX -= 1/FrameRate ' 1 meter/second If TBGL_GetWindowKeyState(hWnd, %VK_D) Then LightX += 1/FrameRate ' 1 meter/second If TBGL_GetWindowKeyState(hWnd, %VK_P) Then LightY += 1/FrameRate ' 1 meter/second If TBGL_GetWindowKeyState(hWnd, %VK_L) Then LightY -= 1/FrameRate ' 1 meter/second If TBGL_GetWindowKeyState(hWnd, %VK_ESCAPE) Then Exit While Wend TBGL_DestroyWindow
Petr
Bookmarks