Author Topic: Windows 10 timer resolution - jerky movement even with _LIMIT  (Read 5895 times)

0 Members and 1 Guest are viewing this topic.

Offline IfThenOrElse

  • Newbie
  • Posts: 8
    • View Profile
Windows 10 timer resolution - jerky movement even with _LIMIT
« on: October 02, 2021, 12:19:22 pm »
Hi everyone!

My first post here even though Ive been reading for a while.
During the pandemic I started to get into programming after like 25 years. Like many of us I first got in touch with QBasic back at school and I decided to try to get into it a bit more when I had the time.

Anyway, I have started to make a few games, or experimenting around a bit. I started on Windows 7 and it worked pretty good.

I used _LIMIT 60 to limit the frame rate and cycles/game loop to 60fps since what I want is to make games similar to the older ones, Nintendo NES-games to be specific, since I love the style.

When moving sprites i use the method of moving its position once each loop, so 60 times a second. Just doing it very simple like ball.x = (ball.x + 1) or whatever speed the ball has.
In Windows 7 it looked good, smooth movement and I did not really notice anything special.
Then, I had to change to Windows 10 for job related reasons and then I suddenly noticed that the sprites was moving jerkily.. like they moved normal speed, slowed down, normal, slowed down in some "wavy pattern" yet a bit irregular. Its hard to describe.
The project was the same so no change in my source code.
I also use _DISPLAY after the _PUTIMAGE commands, at the end of the game loop where there is a section where everything gets drawn to screen.

I tried to google the issue and found out about the windows timer resolution. I downloaded a program called "TimerToolV3" and when I set the timer to 0.5 ms the sprites move a lot better but still not perfect.
I even tried using delta time by setting a start value at the top of the game loop and one at the end and if the time was less than 1/60 it measured the time again in a small loop and exited if time was 1/60 or more. Still no luck.

So, the problem I have is that it feels like the time that I get from Windows is not consistent. It "says" to QB64 that 1 unit of time has passed but the actual time that unit was, like in real life time, varies.
This is super annoying and it makes me question my coding. I am a noob sure but limit should be consistent shouldnt it?

I also downloaded some other games that people have made in QB64 using _LIMIT and I get the same result, wavy movement.

Could it have something to do with my screen? It has 60Hz as fastest update frequency and maybe the drivers for the screen was messed up/not installed correctly again after I changed to Windows 10? Ive got the latest NVIDIA drivers.
(other real games and game emulators work good with very smooth movement though).

Im lost and need some advice here... It must be possible to get a proper timing... its also just 60fps.. Feels like I am missing something fundamental.

/ Andrew








« Last Edit: October 02, 2021, 07:06:44 pm by IfThenOrElse »

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LMIMIT
« Reply #1 on: October 02, 2021, 12:39:29 pm »
IfThenOrElse what? I love that handle.

Have you tried setting the compiled .exe program to Windows 7 compatibility mode?

Right click the .exe file in Windows Explorer.
Click "Properties"
Click the compatibility tab.
Check the "Compatibility Mode" box
Click and scroll down the menu to Windows 7.
Click to select Windows 7.
Click "Apply"
Click "OK"

It may do nothing, as I often feel the MS compatibility feature is just the tip of the iceberg, but it might give us some more insight if it does change the animation timing.

Welcome to the forum,

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LMIMIT
« Reply #2 on: October 02, 2021, 12:47:52 pm »
Welcome @IfThenOrElse

Do you have a small bit of code that you can share that works differently in the two different Windows versions?

Offline IfThenOrElse

  • Newbie
  • Posts: 8
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #3 on: October 02, 2021, 07:35:30 pm »
Hi again and thanks for the fast replies!

I have tested to run the compiled program in compatibility mode for Windows 7 yes, no difference unfortunately. I have also tried a lot of different stuff in the NVIDIA control panel, like vsync settings and a lot of things I do not remember in detail right now.

As for a bit of code to share, yes I can do that. I will make a small program with just moving the sprite, I have one that I have been messing with trying to find a solution so I will check it and post it here.

I'll update the thread as soon as I have it done. I really want to solve the issue since I find it really pleasant to use qb64 and at the same time investigate how things were done back in the days game programming wise. I think the hardest part is all the mess that comes with screen resolutions and things like that, especially if you want to replicate a low resolution output stretched to about 4:3 format.. being a novice its a pretty steep learning curve but I have managed to figure out a lot of stuff like tile based terrain collision using a tile map, player to enemy hit detection and even some kind of over complicated scrolling.. lol.. it works but it really needs to get refined a bit. So, I feel that I am on to something here and thats why I dont want it to end with some inconsistent frame rate/clock cycle trouble. Especially when I experience the problem in other games made in qb64 by other people. 

I tried for example a Flappy Bird clone found in this post:
https://www.qb64.org/forum/index.php?topic=2523.0

The phenomenon is especially visible at the title screen of the game. The green ground/grass that scrolls is moving in the same wavy way that my own stuff do.. and when using the TimerTool program and timer resolution set to .5 ms its a lot better but not completely smooth...

Well, i'll write back as soon as I have some own code to share!

/ Andrew

Offline IfThenOrElse

  • Newbie
  • Posts: 8
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #4 on: October 28, 2021, 08:09:05 pm »
Ok, I have made a test program for my issue. How do I make an embedded window with the code like you guys do in your posts?
Do I just paste it between whats generated with the dropdown menu (where it says code) when I type my reply?
Don't wanna mess up the post..


I have also tried the QueryPerformanceCounter using the kernel32 library.. but lets talk about that later if needed. (Did not make much of a difference though but I could have messed it up...)


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #5 on: October 28, 2021, 08:44:04 pm »
For code window,
paste the code into the editor
highlight the code (select it)
then click the blue QB64 code icon.

or
press the blue code icon first get
code=qb64  /code   with square brackets around "code=qb64" and around "/code"
paste code between ][ brackets

Code: QB64: [Select]
  1. Print "Hello World"

looks like this:
  [ You are not allowed to view this attachment ]  
« Last Edit: October 28, 2021, 08:58:14 pm by bplus »

Offline IfThenOrElse

  • Newbie
  • Posts: 8
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #6 on: October 28, 2021, 09:39:05 pm »
Allright, thanks!

So, Ive made a simple program where an object/sprite is moving across the screen. It uses _LIMIT 60 but its possible to uncomment some lines and use TIMER instead. I don't know if it will lag on someone elses computer but we will see I guess.
What I am trying to achive is a smooth motion but its jerky like its lagging behind sort of with different intervals.
It's possible to print the elapsed time for the loop to and those numbers are also different for each loop. There must be some proper way to achive a 60fps running loop or at least something that is smooth. I am a noob here so it might be something I have not grasped yet. What I have done is how I understand it but it could be wrong.

Here is the code:

Code: QB64: [Select]
  1. 'tvscreen43& = _NEWIMAGE(1920, 1080, 32) 'Optional to test
  2. tvscreen43& = _NEWIMAGE(320, 240, 32)
  3.  
  4. SCREEN tvscreen43& '               Set tvscreen& as the screen where we will display everything in the end. The active screen.
  5. _MOUSEHIDE '                       Hide the mouse cursor.
  6.  
  7.  
  8. 'Making stuff easier to adjust
  9. CONST ScreenEndLeft = 0
  10. CONST ScreenEndRight = 320 '1920
  11. CONST ScreenEndTop = 0
  12. CONST ScreenEndBottom = 240 '1080
  13. CONST ScreenWidth = 320 '1920
  14. CONST ScreenHeight = 240 '1080
  15. CONST ScreenCenterX = (ScreenWidth / 2)
  16. CONST ScreenCenterY = (ScreenHeight / 2)
  17.  
  18. 'THIS HAS SOME LEFT OVERS BUT THEY SHOULD NOT MATTER...
  19. TYPE Shot '                        PlayerShot definition.
  20.     alive AS _BYTE '               Is the shot alive on screen or not. Can be set to false if it goes off screen or if it collides with like an enemy.
  21.     x AS SINGLE '                  X coordinate of the shot.
  22.     y AS SINGLE '                  Y coordinate of the shot.
  23.     speed AS SINGLE '              The speed of the shot. Could be adjusted according to the shot speed of different cannons etc. if needed.
  24.     spriteheight AS INTEGER '      The height of the shot sprite. A bit overkill but used for calculating when the shot is completely off the screen.
  25.     spritewidth AS INTEGER '       Same but width.
  26.     dir AS _BYTE '                 What direction is the shot travelling in?
  27.     angle AS SINGLE
  28.     stepy AS SINGLE '              These are used for trig stuff to aim etc. etc.
  29.     stepx AS SINGLE
  30.     sprite AS INTEGER '            What sprite is used for the shot
  31.     'maxshots AS SINGLE '          How many of this particular shot can be fired on screen at the same time.
  32.     'dmg AS SINGLE                 Damage value of the shot. Targets HP is reduced by this when hit.
  33. REDIM SHARED Shots(0) AS Shot '    Make it a dynamic array. Can be redimmed later to accomodate different amounts of shots.
  34.  
  35.  
  36. 'Shot sprite
  37. '8x8px
  38. '(Part of code is borrowed from somewhere like a tutorial or something...).
  39. ShotSpriteData:
  40. DATA &HFFFC00FC,&HFFFC00FC,&HFF000000,&HFF000000,&HFF000000,&HFF000000,&HFFFC00FC,&HFFFC00FC
  41. DATA &HFFFC00FC,&HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFF000000,&HFFFC00FC
  42. DATA &HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFFF7D8A5,&HFF000000
  43. DATA &HFF000000,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFF000000
  44. DATA &HFF000000,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFF000000
  45. DATA &HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFFF7D8A5,&HFF000000
  46. DATA &HFFFC00FC,&HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFF000000,&HFFFC00FC
  47. DATA &HFFFC00FC,&HFFFC00FC,&HFF000000,&HFF000000,&HFF000000,&HFF000000,&HFFFC00FC,&HFFFC00FC
  48.  
  49. RESTORE ShotSpriteData
  50. FOR y = 0 TO 7: FOR x = 0 TO 7
  51.         READ sprite#: PSET (x, y), sprite#
  52. NEXT x: NEXT y
  53. DIM SHARED shotsprite AS INTEGER
  54. _SETALPHA 0, _RGB32(252, 0, 252), shotsprite%
  55. shotsprite% = _NEWIMAGE(8, 8, 32)
  56. _PUTIMAGE (0, 0), 0, shotsprite%
  57.  
  58.  
  59. 'Set some properties of the shot
  60. Shots(0).x! = 0
  61. Shots(0).y! = 100
  62. Shots(0).spritewidth% = 8
  63. Shots(0).spriteheight% = 8
  64. Shots(0).dir%% = 0
  65. Shots(0).sprite% = shotsprite%
  66.  
  67. SCREEN tvscreen43&
  68.  
  69.  
  70.  
  71. DO '                                                      Start of the "game loop".
  72.  
  73.     _LIMIT 60 '                                           Limit fps to 60 fps...
  74.  
  75.     'LoopStartTime## = TIMER(0.001) '                     Instead of _LIMIT one can do it manually
  76.     '                                                     Get time in milliseconds at start of game loop.
  77.  
  78.     CLS
  79.     Shots(0).x! = (Shots(0).x! + 2) '                     If done with dynamic fps this line would instead be:
  80.     'Shots(0).x! = Shots(0).x! + 2 * (delta## * 60)
  81.  
  82.     'If the shot as gone off the right side screen edge, reset its position to the left side of screen.
  83.     IF Shots(0).x! >= (ScreenEndRight + Shots(0).spritewidth%) THEN Shots(0).x! = (ScreenEndLeft - Shots(0).spritewidth%)
  84.  
  85.     _PUTIMAGE (Shots(0).x!, Shots(0).y!), Shots(0).sprite% 'Put the sprite on screen
  86.  
  87.     _DISPLAY '                                            Display it hopefully flicker less...
  88.  
  89.  
  90.  
  91.     'delta## = (TIMER(0.001) - LoopStartTime##) '         Calculate time that has passed during the loop.
  92.  
  93.  
  94.  
  95.  
  96.     'SECTION FOR USING A "FIXED" FPS INSTEAD OF USING _LIMIT (UNCOMMENT _LIMIT AT TOP OF LOOP)
  97.     'Comment out _LIMIT 60 at top of loop
  98.     'Uncomment: LoopStartTime## = TIMER(0.001)
  99.     'Uncomment: delta## = (TIMER(0.001) - LoopStartTime##)
  100.     '
  101.     'Uncomment the code lines below:
  102.     '-------------------------------------------------------------------------------------------
  103.     'IF delta## < 0.0167 THEN '                           'If the time it took to complete the loop is less than 1 / 60...
  104.     '                                                      0.0167 could be replaced with (1/60)
  105.     'DO '                                                 '...enter a mini loop and check the time again and again until it is 1/60 or more.
  106.     'delta## = (TIMER(0.001) - LoopStartTime##)
  107.     '
  108.     'LOOP UNTIL delta## >= (0.0167) '                     'Again its possible to use (1 / 60) instead of 0.0167...
  109.     'END IF
  110.     '-------------------------------------------------------------------------------------------
  111.  
  112.  
  113.     'FOR DYNAMIC FPS (LOOP CAN BE AS FAST AS IT WANT BUT SHOT MOVES THE SAME DISTANCE):
  114.     'Replace: Shots(0).x! = (Shots(0).x! + 2) with: Shots(0).x! = Shots(0).x! + 2 * (delta## * 60)
  115.     '
  116.     'Comment out _LIMIT 60 in the loop
  117.     'Uncomment: LoopStartTime## = TIMER(0.001)
  118.     'Uncomment: delta## = TIMER(0.001) - LoopStartTime##
  119.  
  120.  
  121.  
  122.     'VARIANTS OF _PUTIMAGE LINE:
  123.     '-------------------------------------------------------------------------------------------
  124.     '_PUTIMAGE (INT(Shots(0).x!), INT(Shots(0).y!)), Shots(0).sprite% 'Putting it at integer values of the single type x and y values
  125.     '                                                                  that can potentially have decimals (because it cant be put between pixels...).
  126.  
  127.     'PSET ((Shots(0).x!), Shots(0).y!), &HFFF7D8A5 '                   Its the same if we only put a single pixel on the screen...
  128.  
  129.     '-------------------------------------------------------------------------------------------
  130.  
  131. _FREEIMAGE shotsprite%


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #7 on: October 28, 2021, 10:48:43 pm »
Yeah I see what you mean, here I measured loop times:
Code: QB64: [Select]
  1. Screen _NewImage(800, 600, 32)
  2. _Delay .25
  3.  
  4. Dim looptimes#(1 To 100000)
  5. t# = Timer(.001)
  6. While _KeyDown(27) = 0
  7.     Cls
  8.     j = j + 1
  9.     looptimes#(j) = Int(10000 * (Timer(.001) - t#)) / 10000
  10.     Print looptimes#(j), "press escape to see looptimes."
  11.     t# = Timer(.001)
  12.     x = x + 2
  13.     If x = _Width Then x = 0
  14.     For i = 0 To 10 Step .25
  15.         Circle (x, _Height / 2), i
  16.     Next
  17.     _Display
  18.     _Limit 60
  19. For i = 1 To 100000
  20.     If looptimes#(i) <> 0 Then Print looptimes#(i);
  21.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #8 on: October 28, 2021, 11:04:49 pm »
This gives me a tighter set of times:
Code: QB64: [Select]
  1. Screen _NewImage(800, 600, 32)
  2. _Delay .25
  3.  
  4. Dim looptimes#(1 To 100000)
  5. t# = Timer(.001)
  6. While _KeyDown(27) = 0
  7.     Cls
  8.     j = j + 1
  9.     looptimes#(j) = Int(10000 * (Timer(.001) - t#)) / 10000
  10.     Print looptimes#(j), "press escape to see looptimes."
  11.     t# = Timer(.001)
  12.     x = x + 2
  13.     If x = _Width Then x = 0
  14.     For i = 0 To 10 Step .25
  15.         Circle (x, _Height / 2), i
  16.     Next
  17.     _Display
  18.     While Timer(.001) - t# <= .0163: Wend
  19.     '_Limit 60
  20. For i = 1 To 100000
  21.     If looptimes#(i) <> 0 Then Print looptimes#(i);
  22.  

How about for you?

Offline IfThenOrElse

  • Newbie
  • Posts: 8
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #9 on: October 31, 2021, 09:31:58 am »
Yes that gives a better result indeed! Still though, it does a small jerk about every half second.
The times that gets printed shows .0169 but every now and then it shows .017. Its really not much difference but still it looks jerky.
Using the TimerToolV3 and set it to .5 ms makes it even better but not perfect..

How is it done in games where it is smooth all the time? There must be some way to get a steady clock "signal" like making a dedicated timer on its own thread or something.
That in conjunction with delta time that adjusts the speed based on the previous loop time. I don't know... It would however be very nice if it is possible to solve.
Maybe it would be less noticeable if I make the screen resolution a lot larger and up-scale the sprites instead.

Any ideas are welcome =)

In the mean time i will try to use the QueryPrecisionTimer in the same way and see if it matters...

/Andrew



Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #10 on: October 31, 2021, 11:01:04 am »
@IfThenOrElse  Remind me what TimerToolV3 is, something you have coded?

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #11 on: October 31, 2021, 11:31:11 am »
Either it does not do it on Vista or I'm missing what your talking about.

Although if you have just an single object moving on screen and your eyes are following just that object it can appear as if it pauses for an instant if your eyes line up on it just right. like a kid watching a ceiling fan spin, if they try to follow just one blade it can some times appear as if the fan is still for a brief instant. I wonder if that is what you are experiencing.

Try adding other moving objects, like a star field in the background moving the opposite direction or a target moving up and down(or better both) and see if you still experience the same thing. Give yourself other things to process as well, rather than just a single moving object on the screen.

Granted after becoming radioactive I only have a half-life!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #12 on: October 31, 2021, 12:14:47 pm »

Code: QB64: [Select]
  1. 'tvscreen43& = _NEWIMAGE(1920, 1080, 32) 'Optional to test
  2. tvscreen43& = _NEWIMAGE(320, 240, 32)
  3. ShotSprite& = _NEWIMAGE(8, 8, 32)
  4.  
  5. Temp& = _NEWIMAGE(320, 240, 32) 'mix layer before display
  6. DIM SHARED StarScreen&
  7. StarScreen& = _NEWIMAGE(320, 240, 32)
  8.  
  9. SCREEN tvscreen43& '               Set tvscreen& as the screen where we will display everything in the end. The active screen.
  10. _MOUSEHIDE '                       Hide the mouse cursor.
  11.  
  12.  
  13. 'Making stuff easier to adjust
  14. CONST ScreenEndLeft = 0
  15. CONST ScreenEndRight = 320 '1920
  16. CONST ScreenEndTop = 0
  17. CONST ScreenEndBottom = 240 '1080
  18. CONST ScreenWidth = 320 '1920
  19. CONST ScreenHeight = 240 '1080
  20. CONST ScreenCenterX = (ScreenWidth / 2)
  21. CONST ScreenCenterY = (ScreenHeight / 2)
  22.  
  23. 'THIS HAS SOME LEFT OVERS BUT THEY SHOULD NOT MATTER...
  24. TYPE Shot '                        PlayerShot definition.
  25.  alive AS _BYTE '               Is the shot alive on screen or not. Can be set to false if it goes off screen or if it collides with like an enemy.
  26.  x AS SINGLE '                  X coordinate of the shot.
  27.  y AS SINGLE '                  Y coordinate of the shot.
  28.  speed AS SINGLE '              The speed of the shot. Could be adjusted according to the shot speed of different cannons etc. if needed.
  29.  spriteheight AS INTEGER '      The height of the shot sprite. A bit overkill but used for calculating when the shot is completely off the screen.
  30.  spritewidth AS INTEGER '       Same but width.
  31.  dir AS _BYTE '                 What direction is the shot travelling in?
  32.  angle AS SINGLE
  33.  stepy AS SINGLE '              These are used for trig stuff to aim etc. etc.
  34.  stepx AS SINGLE
  35.  sprite AS INTEGER '            What sprite is used for the shot
  36.  'maxshots AS SINGLE '          How many of this particular shot can be fired on screen at the same time.
  37.  'dmg AS SINGLE                 Damage value of the shot. Targets HP is reduced by this when hit.
  38.  
  39. REDIM SHARED Shots(0) AS Shot '    Make it a dynamic array. Can be redimmed later to accomodate different amounts of shots.
  40.  
  41.  
  42. 'Shot sprite
  43. '8x8px
  44. '(Part of code is borrowed from somewhere like a tutorial or something...).
  45. ShotSpriteData:
  46. DATA &HFFFC00FC,&HFFFC00FC,&HFF000000,&HFF000000,&HFF000000,&HFF000000,&HFFFC00FC,&HFFFC00FC
  47. DATA &HFFFC00FC,&HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFF000000,&HFFFC00FC
  48. DATA &HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFFF7D8A5,&HFF000000
  49. DATA &HFF000000,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFF000000
  50. DATA &HFF000000,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFF000000
  51. DATA &HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFFF7D8A5,&HFF000000
  52. DATA &HFFFC00FC,&HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFF000000,&HFFFC00FC
  53. DATA &HFFFC00FC,&HFFFC00FC,&HFF000000,&HFF000000,&HFF000000,&HFF000000,&HFFFC00FC,&HFFFC00FC
  54.  
  55. RESTORE ShotSpriteData
  56. _DEST ShotSprite&
  57. FOR y = 0 TO 7: FOR x = 0 TO 7
  58.  READ sprite~&: PSET (x, y), sprite~&
  59. NEXT x: NEXT y
  60. _CLEARCOLOR _RGB32(252, 0, 252), ShotSprite&
  61.  
  62.  
  63. 'Set some properties of the shot
  64. Shots(0).x! = 0
  65. Shots(0).y! = 100
  66. Shots(0).spritewidth% = 8
  67. Shots(0).spriteheight% = 8
  68. Shots(0).dir%% = 0
  69. 'Shots(0).sprite% = shotsprite%
  70.  
  71. SCREEN tvscreen43&
  72. _DEST Temp&
  73.  
  74. DO '                                                      Start of the "game loop".
  75.  Shots(0).x = (Shots(0).x + 1)
  76.  IF Shots(0).x >= (ScreenEndRight + Shots(0).spritewidth) THEN Shots(0).x = (ScreenEndLeft - Shots(0).spritewidth)
  77.  
  78.  StarField
  79.  Target
  80.  _PUTIMAGE , StarScreen&, Temp&
  81.  _PUTIMAGE (Shots(0).x, Shots(0).y), ShotSprite&, Temp&
  82.  _PUTIMAGE , Temp&, _DISPLAY
  83.  _LIMIT 60
  84.  
  85. SUB StarField
  86.  STATIC Star.x(50) AS SINGLE, Star.y(50) AS SINGLE, Star.Speed(50) AS SINGLE, INIT%%
  87.  IF NOT INIT%% THEN
  88.   FOR i%% = 0 TO 50
  89.    Star.x(i%%) = INT(RND * ScreenWidth)
  90.    Star.y(i%%) = INT(RND * ScreenHeight)
  91.    Star.Speed(i%%) = INT(RND * 10) / 10
  92.   NEXT i%%
  93.   INIT%% = -1
  94.  _DEST StarScreen&
  95.  LINE (0, 0)-STEP(ScreenWidth - 1, ScreenHeight - 1), _RGB32(0), BF
  96.  
  97.  FOR i%% = 0 TO 50
  98.   Star.x(i%%) = Star.x(i%%) - Star.Speed(i%%)
  99.   IF Star.x(i%%) < 0 THEN Star.x(i%%) = ScreenWidth
  100.   PSET (Star.x(i%%), Star.y(i%%)), _RGB32(180)
  101.  NEXT i%%
  102.  
  103. SUB Target
  104.  STATIC Target.X, Target.Y, Rebound%%
  105.  _DEST StarScreen&
  106.  IF Rebound%% = 0 THEN Rebound%% = -1: Target.X = ScreenWidth - 30: Target.Y = 20
  107.  Target.Y = Target.Y - Rebound%%
  108.  LINE (Target.X, Target.Y)-STEP(10, 25), _RGB32(255, 0, 0), BF
  109.  IF Target.Y >= ScreenHeight - 45 THEN Rebound%% = 1
  110.  IF Target.Y <= 20 THEN Rebound%% = -1
Granted after becoming radioactive I only have a half-life!

Offline moises1953

  • Newbie
  • Posts: 55
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #13 on: October 31, 2021, 02:58:59 pm »
this is the best i could get, with this metod:
1. Limit memory transfer by substituting CLS for a limited background put. (BlackSprite)
2. Insert autodisplay at the beginning of the loop

Code: QB64: [Select]
  1. 'tvscreen43& = _NEWIMAGE(1920, 1080, 32) 'Optional to test
  2. tvscreen43& = _NEWIMAGE(320, 240, 32)
  3.  
  4. SCREEN tvscreen43& '               Set tvscreen& as the screen where we will display everything in the end. The active screen.
  5. _MOUSEHIDE '                       Hide the mouse cursor.
  6.  
  7.  
  8. 'Making stuff easier to adjust
  9. CONST ScreenEndLeft = 0
  10. CONST ScreenEndRight = 320 '1920
  11. CONST ScreenEndTop = 0
  12. CONST ScreenEndBottom = 240 '1080
  13. CONST ScreenWidth = 320 '1920
  14. CONST ScreenHeight = 240 '1080
  15. CONST ScreenCenterX = (ScreenWidth / 2)
  16. CONST ScreenCenterY = (ScreenHeight / 2)
  17.  
  18. 'THIS HAS SOME LEFT OVERS BUT THEY SHOULD NOT MATTER...
  19. TYPE Shot '                        PlayerShot definition.
  20.   alive AS _BYTE '               Is the shot alive on screen or not. Can be set to false if it goes off screen or if it collides with like an enemy.
  21.   x AS SINGLE '                  X coordinate of the shot.
  22.   y AS SINGLE '                  Y coordinate of the shot.
  23.   speed AS SINGLE '              The speed of the shot. Could be adjusted according to the shot speed of different cannons etc. if needed.
  24.   spriteheight AS INTEGER '      The height of the shot sprite. A bit overkill but used for calculating when the shot is completely off the screen.
  25.   spritewidth AS INTEGER '       Same but width.
  26.   dir AS _BYTE '                 What direction is the shot travelling in?
  27.   angle AS SINGLE
  28.   stepy AS SINGLE '              These are used for trig stuff to aim etc. etc.
  29.   stepx AS SINGLE
  30.   sprite AS LONG '** long pointer            What sprite is used for the shot
  31.   'maxshots AS SINGLE '          How many of this particular shot can be fired on screen at the same time.
  32.   'dmg AS SINGLE                 Damage value of the shot. Targets HP is reduced by this when hit.
  33. REDIM SHARED Shots(0) AS Shot '    Make it a dynamic array. Can be redimmed later to accomodate different amounts of shots.
  34.  
  35.  
  36. 'Shot sprite
  37. '8x8px
  38. '(Part of code is borrowed from somewhere like a tutorial or something...).
  39. ShotSpriteData:
  40. DATA &HFFFC00FC,&HFFFC00FC,&HFF000000,&HFF000000,&HFF000000,&HFF000000,&HFFFC00FC,&HFFFC00FC
  41. DATA &HFFFC00FC,&HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFF000000,&HFFFC00FC
  42. DATA &HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFFF7D8A5,&HFF000000
  43. DATA &HFF000000,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFF000000
  44. DATA &HFF000000,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFF000000
  45. DATA &HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFFF7D8A5,&HFF000000
  46. DATA &HFFFC00FC,&HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFF000000,&HFFFC00FC
  47. DATA &HFFFC00FC,&HFFFC00FC,&HFF000000,&HFF000000,&HFF000000,&HFF000000,&HFFFC00FC,&HFFFC00FC
  48.  
  49.  
  50. DIM SHARED ShotSprite AS LONG, BlackSprite AS LONG '** long pointer
  51. BlackSprite = _NEWIMAGE(3, 8, 32)
  52. _PUTIMAGE (0, 0), 0, BlackSprite
  53.  
  54. RESTORE ShotSpriteData
  55. FOR y = 0 TO 7: FOR x = 0 TO 7
  56.   READ sprite&: PSET (x, y), sprite& '** Full color
  57. NEXT x: NEXT y
  58.  
  59. _SETALPHA 0, _RGB32(252, 0, 252), ShotSprite
  60. ShotSprite = _NEWIMAGE(8, 8, 32)
  61. _PUTIMAGE (0, 0), 0, ShotSprite
  62.  
  63.  
  64.  
  65.  
  66. 'Set some properties of the shot
  67. Shots(0).x! = 0
  68. Shots(0).y! = 100
  69. Shots(0).spritewidth% = 8
  70. Shots(0).spriteheight% = 8
  71. Shots(0).dir%% = 0
  72. Shots(0).sprite = ShotSprite
  73.  
  74. SCREEN tvscreen43&
  75.  
  76.  
  77.  
  78. DO '                                                      Start of the "game loop".
  79.  
  80.   _LIMIT 60! '                                           Limit fps to 60 fps...
  81.  
  82.   'CLS
  83.   xant! = Shots(0).x!
  84.   Shots(0).x! = (xant! + 2) '                     If done with dynamic fps this line would instead be:
  85.   'Shots(0).x! = Shots(0).x! + 2 * (delta## * 60)
  86.  
  87.   'If the shot as gone off the right side screen edge, reset its position to the left side of screen.
  88.   IF Shots(0).x! >= (ScreenEndRight + Shots(0).spritewidth%) THEN Shots(0).x! = (ScreenEndLeft - Shots(0).spritewidth%)
  89.  
  90.   _PUTIMAGE (xant!, Shots(0).y!), BlackSprite '** Put the black sprite on buffer
  91.  
  92.   '_DISPLAY '
  93.  
  94.   _PUTIMAGE (Shots(0).x!, Shots(0).y!), ShotSprite '** Put the sprite on screen
  95.  
  96.   _DISPLAY '                                            Display it hopefully flicker less...
  97.  
  98.  
  99.   'SECTION FOR USING A "FIXED" FPS INSTEAD OF USING _LIMIT (UNCOMMENT _LIMIT AT TOP OF LOOP)
  100.   'Comment out _LIMIT 60 at top of loop
  101.   'Uncomment: LoopStartTime## = TIMER(0.001)
  102.   'Uncomment: delta## = (TIMER(0.001) - LoopStartTime##)
  103.   '
  104.   'Uncomment the code lines below:
  105.   '-------------------------------------------------------------------------------------------
  106.   'IF delta## < 0.0167 THEN '                           'If the time it took to complete the loop is less than 1 / 60...
  107.   '                                                      0.0167 could be replaced with (1/60)
  108.   'DO '                                                 '...enter a mini loop and check the time again and again until it is 1/60 or more.
  109.   'delta## = (TIMER(0.001) - LoopStartTime##)
  110.   '
  111.   'LOOP UNTIL delta## >= (0.0167) '                     'Again its possible to use (1 / 60) instead of 0.0167...
  112.   'END IF
  113.   '-------------------------------------------------------------------------------------------
  114.  
  115.  
  116.   'FOR DYNAMIC FPS (LOOP CAN BE AS FAST AS IT WANT BUT SHOT MOVES THE SAME DISTANCE):
  117.   'Replace: Shots(0).x! = (Shots(0).x! + 2) with: Shots(0).x! = Shots(0).x! + 2 * (delta## * 60)
  118.   '
  119.   'Comment out _LIMIT 60 in the loop
  120.   'Uncomment: LoopStartTime## = TIMER(0.001)
  121.   'Uncomment: delta## = TIMER(0.001) - LoopStartTime##
  122.  
  123.  
  124.  
  125.   'VARIANTS OF _PUTIMAGE LINE:
  126.   '-------------------------------------------------------------------------------------------
  127.   '_PUTIMAGE (INT(Shots(0).x!), INT(Shots(0).y!)), Shots(0).sprite% 'Putting it at integer values of the single type x and y values
  128.   '                                                                  that can potentially have decimals (because it cant be put between pixels...).
  129.  
  130.   'PSET ((Shots(0).x!), Shots(0).y!), &HFFF7D8A5 '                   Its the same if we only put a single pixel on the screen...
  131.  
  132.   '-------------------------------------------------------------------------------------------
  133. _FREEIMAGE ShotSprite
  134. _FREEIMAGE BlackSprite
  135.  

Offline IfThenOrElse

  • Newbie
  • Posts: 8
    • View Profile
Re: Windows 10 timer resolution - jerky movement even with _LIMIT
« Reply #14 on: November 02, 2021, 12:44:36 pm »
@bplus "Timer Tool V3" is a small program that will change the timer resolution in ms windows. I am not sure about the rules for posting links to other places here but just google it and you will find it. (as always when downloading things, be careful with what downloaded files may contain). Anyway, there seems to be an "issue" with windows (depending on how you look upon it) where the windows timer resolution can be adjusted. As far as I understand it, the idea is that when the computer is "idling" or does not have a lot to do the resolution will be set to something less fine by windows itself. When there are a lot to do, like when running a graphics program the resolution will be set to a finer value. This way its possible to save energy since the computer can work less fast when idling. The concept is pretty neat but not so nice when trying to get a stable frequency.
When using the Timer Tool V3 and setting the resolution to .5 ms the problem I have is less pronounced; the "shot" moves a lot smoother.

@moises1953
Thats an interesting approach. Its better for me as well! I tried it in my main project and it worked there too but instead of running at 60fps the whole game runs at about 30fps or less instead so unfortunately its unplayable but still the scrolling is a lot better. It happens when i include _AUTODISPLAY.

@Cobalt
Yeah i know what you mean! Something similar to watching the rims of a car and percieve them going backwards even though they are not. I tested your starfield program and sure, if you keep your eyes on one of the stars the shot seems to go smoother. Still, thats not the issue here... its something else going  on..

« Last Edit: November 02, 2021, 12:56:55 pm by IfThenOrElse »