Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / Confused with Screen FPS, vsync, and timer based movement

Author
Message
CSL
16
Years of Service
User Offline
Joined: 22nd Mar 2009
Location: USA
Posted: 1st Feb 2014 21:24
I wrote a program that among other features, simulates automatic sprite motion. I developed a function named call_sprite that includes parameters such as sprite number, ascii code, color, x-coord, y-coord, x-velocity and y-velocity (Anyone familiar with the TI-99/4A 8-bit computer from the 80's will recognize this instruction).

To give you some background, the x and y velocity parameters take a value between 1-127 (or -1 to -127) and tells the system to set the sprite in motion at that speed. A negative value sets motion in the opposite direction. A value of 1 or -1 is the slowest speed. To simulate "auto motion" I wrote a special "sync" function that wedges some additional BASIC code to update the sprite location and determine when to move to the next location based on the x y velocities. A timer() is used to determine when to move the sprite based on the velocity value. I use this "special" sync function in the main program loop to control the sprite "auto" motion.

For velocity 1 (slowest) the sprite is supposed to move every 200 milliseconds. For velocity 127 (fastest) the sprite is supposed to move every 1 milliseconds. I used an array to translate the 127 velocities to the corresponding timer values. My program is working as intended, but...

Here's the source of my confusion:

As I created programs to use the new functions, I started to notice from the beginning that sprite motion was not as smooth as I wanted, although the program is running at over 900 FPS (measured using Fraps) even with approximately 112 sprites set in motion at full speed and doing some other processing. I did some investigation and the symptoms pointed to a term new to me called tearing, which is supposed to be solved by setting vertical sync or vsync.

So I searched the forums to find out how to turn on vsync, went ahead and added the vsync flag to my display settings, and voila, smooth motion! However,FPS dropped to 60, although a consistent 60 throughout. But here's the wrinkle; the sprite motion slowed down considerably even at the fastest velocities. Originally, without vsync, a sprite at velocity 127 took roughly .5 seconds to go from one edge of the screen to the other (256 pixels distance), now it takes roughly 4 seconds. So I don't understand why sprites slowed down if I'm using an internal clock timer to determine when the sprite should move.

Then the other wrinkle. My FPS using Fraps is consistently 60 frames, while DBPro's Screen FPS is between 14-15 with vsync on and 21-22 without vsync.

So could someone explain what is going on here? What am I missing here and how do I adjust sprite speeds to be consistent regardless of vsync, if that's possible?

I attached a screenshot showing Fraps FPS (in yellow) and screen FPS, running my program with the vsync flag on. The letter and number images are actually sprites flying around at different speeds.

Thanks in advance for your help!

CSL

Attachments

Login to view attachments
ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 2nd Feb 2014 03:32
Not sure about Fraps and why it shows a different FPS rate than DBPro, but other than that it's relatively easily explained: VSync limits your FPS to 60, kind of as "sync rate 60" would do, but in a way that prevents the tearing effect. The only thing you really need to know is that your main loop will cycle only 60 times per second when vsync is activated. Hence your sprites will move much slower, since even at the fastest speed they will be moved no more than 60 times a second (i.e. every 16 or so miliseconds). I assume the slower sprites move at the same speed as they did before and only the fast ones are affected by the changes?

One way to solve the problem is to change your movement approach: Instead of moving by a fixed distance, varying the time between two movements, you could move all the sprites each frame and vary the distance instead (which would work well if your coordinates are stored as floats). If your coordinates are stored as integer however, this would mean your slowest sprites would still move at 60 units per second (pixels I guess). So you could work on a mixture between both methods, and store in your "speed array" not only the time difference between two movement operations, but also the distance the sprite has to be moved each time. In that case you could make sure all slow sprites (up to one movement every ~16ms) stay the way they were before (i.e. distance stays at 1), and faster sprites get an increased distance value in order to keep the time step higher than 16ms (So when you originally had a movement every 4ms, you'd just set it to 16ms and increase the distance to 4, because moving a sprite 4 pixels every 16ms results in the same speed as moving it 1 pixel every 4ms).

I hope this wasn't too confusing. It's 3:30 AM here and surprisingly enough I'm kind of tired.

zeroSlave
15
Years of Service
User Offline
Joined: 13th Jun 2009
Location: Springfield
Posted: 2nd Feb 2014 03:55
I could be wrong, as I haven't tested, but I think that vertical sync limits the sync rate to that of the monitor's screen refresh, and attempts to sync the app with the actual monitor. If the app updates the screen when the monitor is halfway done with a screen refresh, it will cause the top and bottom portions (or, wherever the monitor was refreshed at vertically) of the screen to show different times of the app.

If a sprite was at x position 500 in one frame, and at x position 5 in the next, and the screen tear lies at a y position inside the image you will see a tear.

http://en.wikipedia.org/wiki/Screen_tearing

Everybody is a genius. But if you judge a fish by its ability to climb a tree, it will live its whole life believing that it is stupid.
CSL
16
Years of Service
User Offline
Joined: 22nd Mar 2009
Location: USA
Posted: 2nd Feb 2014 05:58
Quote: " I assume the slower sprites move at the same speed as they did before and only the fast ones are affected by the changes?"

Yes! all sprites that are supposed to move every 16 milliseconds or less (the faster sprites) are taking exactly the same time from one edge of the screen to the other regardless, very interesting. The slower sprites are working fine.

Quote: "If your coordinates are stored as integer however, this would mean your slowest sprites would still move at 60 units per second (pixels I guess). So you could work on a mixture between both methods, and store in your "speed array" not only the time difference between two movement operations, but also the distance the sprite has to be moved each time. In that case you could make sure all slow sprites (up to one movement every ~16ms) stay the way they were before (i.e. distance stays at 1), and faster sprites get an increased distance value in order to keep the time step higher than 16ms "

My program stores the coordinates using integers, so I can't see how this adjustment will work without making the sprite movement look jerky. Increasing the rate of movement means skipping pixels to give it the illusion of moving faster, or is there another way of doing this? ... hmm... It is getting late where I am now, so I'll give it some more thought tomorrow, but thank you, your answer really makes sense and gives me a lot of hope ...

CSL
ShellfishGames
12
Years of Service
User Offline
Joined: 6th Feb 2013
Location:
Posted: 2nd Feb 2014 12:44 Edited at: 2nd Feb 2014 13:00
Quote: "Increasing the rate of movement means skipping pixels to give it the illusion of moving faster, or is there another way of doing this?"


I'm pretty sure this is the only working solution, since you can't really do anything about the 60 FPS limit. Also note that your current implementation would not work well on slower computers. If the program runs with only 200 FPS by itself due to the PC needing more time to render the scene, your fast sprites (moving more often than every 5ms) would be slowed down.
However, skipping pixels to "give the illusion of moving faster" really isn't a big deal. Just think of movies - they've only got 24 FPS, but if a car moves from the left side of the screen to the right, you still perceive it as moving, although it skips 80 pixels each frame (assuming a full HD resolution).
And while the human eye can spot the difference between 24FPS and 60FPS (both appearing as motion, but the latter a little more fluent), I believe we can't see any difference between 60FPS and 120FPS or even 1000FPS. So what it comes down to is that nobody would even be able to tell the difference between a game running at 1000FPS, and a game running at 60FPS but using the method mentioned above.


Edit: I wrote a small example code.



It renders four rows of moving boxes. The first row moves at the maximum FPS rate, the second one is updated every 16ms (hence it moves at about 60FPS), the third row at 24FPS and the fourth one at 10FPS. If you just compile the code the way it is, you'll possibly see a small difference between the first two rows - however, this effect vanishes once you turn on VSync (line 6, change last parameter from 0 to 1), and the rows will behave identical and look even better than before since the tearing is gone. There's just no way for you to notice that those boxes skip pixels at this FPS rate.
Row #3 looks kind of choppy in comparison, but if you added a bit of motion blur to the box it would probably look like proper movement as well - but that doesn't really matter at this point.

CSL
16
Years of Service
User Offline
Joined: 22nd Mar 2009
Location: USA
Posted: 2nd Feb 2014 19:34 Edited at: 2nd Feb 2014 21:27
Certainly very informative and enlightening! I got some tweaking to do, but this certainly helps. Most appreciated, sir *edit* or madam!.

CSL
CSL
16
Years of Service
User Offline
Joined: 22nd Mar 2009
Location: USA
Posted: 9th Feb 2014 04:00
I implemented some changes and seems to be working. I attached a zipped file with two versions of a simple test game I wrote. One version has vsync turned on, and the other has it turned off. I adjusted sprite speed based on the value of screen FPS. On my computer both programs run at more or less the same speed, but with vsync on, sprites move smoothly. My PC is fast so I'm not sure if the changes translate well for other systems, faster or slower.

CSL

Attachments

Login to view attachments

Login to post a reply

Server time is: 2025-05-15 20:36:17
Your offset time is: 2025-05-15 20:36:17