Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - IfThenOrElse

Pages: [1]
1
Well.. the timers did not make sense, doing this is enough to wait for a while. The thing seem to be to find a balance where the "game loop" manage to do its thing and then "render" the image as fast as possible. A lot to learn...:

Code: QB64: [Select]
  1.     starttime_gltest# = TIMER(0.001)
  2.  
  3.     DO
  4.         delta_gltest# = (TIMER(0.001) - starttime_gltest#)
  5.     LOOP UNTIL delta_gltest# >= (1 / 70)
  6.     CLS
  7.     _PUTIMAGE (INT(Shots(0).x!), Shots(0).y!), Shots(0).sprite%
  8.     PRINT (delta_gltest# * 1000)
  9.     _DISPLAY


Even this seem to work in the _GL sub:

Code: QB64: [Select]
  1.     _DELAY (1 / 60)
  2.     CLS
  3.     _PUTIMAGE (INT(Shots(0).x!), Shots(0).y!), Shots(0).sprite%
  4.     PRINT (delta_gltest# * 1000)
  5.     _DISPLAY
  6.  

2
I have been experimenting a bit and found that if I measure the time in a _GL sub (normally for open GL rendering) it seem to work the way I want it to. It's a hack-ish way of doing it and i dont know why it works, if the timer get the time from the GPU instead just because its inside the _GL sub or if the measured time just happened to be at the right place... someone might know..

I found this because I was going to try to learn how to render with open GL instead of just using putimage like Ive done so far. I have noticed that programs that use open GL seem very smooth. The one where they simulate the pandemic in particular: https://www.qb64.org/forum/index.php?topic=2827.0
The green dots simulating people moves super smooth in the open GL version that can be found some posts down the page. If you change the size of them to larger ones its really noticable.

Anyway, below is the new code I made. Since i am new to this I dont really understand why it works better, it may just be better placement of the timers and have completely nothing to do with the _GL sub per see. By the way, the 320x240 res screen is just from me experimenting as well. If I manage to make a game I will try to adjust it so i have like a native low resolution for the game and then scale it to whatever the player has as desktop. But thats for later.

Do anyone else see a difference in movement?

Code: QB64: [Select]
  1. tvscreen43& = _NEWIMAGE(320, 240, 32)
  2.  
  3. SCREEN tvscreen43&
  4.  
  5.  
  6.  
  7. CONST ScreenEndLeft = 0
  8. CONST ScreenEndRight = 320 '1920
  9. CONST ScreenEndTop = 0
  10. CONST ScreenEndBottom = 240 '1080
  11. CONST ScreenWidth = 320 '1920
  12. CONST ScreenHeight = 240 '1080
  13. CONST ScreenCenterX = (ScreenWidth / 2)
  14. CONST ScreenCenterY = (ScreenHeight / 2)
  15.  
  16.  
  17. TYPE Shot
  18.     alive AS _BYTE
  19.     x AS SINGLE
  20.     y AS SINGLE
  21.     speed AS SINGLE
  22.     spriteheight AS INTEGER
  23.     spritewidth AS INTEGER
  24.     dir AS _BYTE
  25.     angle AS SINGLE
  26.     stepy AS SINGLE
  27.     stepx AS SINGLE
  28.     sprite AS INTEGER
  29.  
  30. REDIM SHARED Shots(0) AS Shot
  31.  
  32. 'Shot sprite
  33. '8x8px
  34. '(Part of code is borrowed from somewhere like a tutorial or something...).
  35. ShotSpriteData:
  36. DATA &HFFFC00FC,&HFFFC00FC,&HFF000000,&HFF000000,&HFF000000,&HFF000000,&HFFFC00FC,&HFFFC00FC
  37. DATA &HFFFC00FC,&HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFF000000,&HFFFC00FC
  38. DATA &HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFFF7D8A5,&HFF000000
  39. DATA &HFF000000,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFF000000
  40. DATA &HFF000000,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFF000000
  41. DATA &HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFFFFEFF,&HFFFFFEFF,&HFFF7D8A5,&HFFF7D8A5,&HFF000000
  42. DATA &HFFFC00FC,&HFF000000,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFFF7D8A5,&HFF000000,&HFFFC00FC
  43. DATA &HFFFC00FC,&HFFFC00FC,&HFF000000,&HFF000000,&HFF000000,&HFF000000,&HFFFC00FC,&HFFFC00FC
  44.  
  45. RESTORE ShotSpriteData
  46. FOR y = 0 TO 7: FOR x = 0 TO 7
  47.         READ sprite#: PSET (x, y), sprite#
  48. NEXT x: NEXT y
  49. DIM SHARED shotsprite AS INTEGER
  50. _SETALPHA 0, _RGB32(252, 0, 252), shotsprite%
  51. shotsprite% = _NEWIMAGE(8, 8, 32)
  52. _PUTIMAGE (0, 0), 0, shotsprite%
  53.  
  54.  
  55. 'Set some properties of the shot
  56. Shots(0).x! = 0
  57. Shots(0).y! = 100
  58. Shots(0).spritewidth% = 8
  59. Shots(0).spriteheight% = 8
  60. Shots(0).dir%% = 0
  61. Shots(0).sprite% = shotsprite%
  62.  
  63. SCREEN tvscreen43&
  64.  
  65.  
  66. DIM SHARED AllowGL AS _BYTE
  67. DIM SHARED endtime_gltest AS DOUBLE
  68. DIM SHARED starttime_gltest AS DOUBLE
  69. DIM SHARED delta_gltest AS DOUBLE
  70.  
  71. AllowGL%% = -1
  72.  
  73.     _LIMIT 60
  74.  
  75.     Shots(0).x! = (Shots(0).x! + 2)
  76.  
  77.     IF Shots(0).x! >= (ScreenEndRight + Shots(0).spritewidth%) THEN Shots(0).x! = (ScreenEndLeft - Shots(0).spritewidth%)
  78.  
  79.  
  80. _FREEIMAGE shotsprite%
  81.  
  82.  
  83. SUB _GL ()
  84.     IF AllowGL%% = 0 THEN EXIT SUB
  85.  
  86.     endtime_gltest# = TIMER(0.001)
  87.     starttime_gltest# = TIMER(0.001)
  88.  
  89.     delta_gltest# = (endtime_gltest# - starttime_gltest#)
  90.  
  91.     IF delta_gltest# <= (1 / 60) THEN
  92.  
  93.         DO
  94.             delta_gltest# = (TIMER(0.001) - starttime_gltest#)
  95.         LOOP UNTIL delta_gltest# >= (1 / 60)
  96.         CLS
  97.         _PUTIMAGE (INT(Shots(0).x!), Shots(0).y!), Shots(0).sprite%
  98.         PRINT (delta_gltest# * 1000)
  99.         _DISPLAY
  100.  
  101.     END IF
  102.  
  103.     '   _GLEND
  104.     '    _GLFLUSH
  105.  
  106.  

3
@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..


4
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



5
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%


6
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...)


7
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

8
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









Pages: [1]