Solved

What's the difference between a graphics fps and logic fps?

Posted on 2004-08-26
21
686 Views
Last Modified: 2013-12-26
Recently I've developed a simple vertical shooting game using DirectX. The game itself is written in C++. I've set the frame-per-delay at 20ms, which means per second it'll run at 50 frames.

However, I've done a comparison between mine game's graphic fps feel and Diablo 2's graphic fps feel and found out that at 50 fps they felt the same. P.S Diablo 2 is running at 25 fps.

My game is 800x600x16bits, while Diablo 2's should be 800x600x8bits (Correct me if I'm wrong, but please make sure that you're absolutely right, in my experience, I don't think D2 is 16bits)

Note that I'm absolutely sure that my game isn't blitting twice. You might ask, it may be that my game is running at 16bits which contributed to this slow performance. But I've set my graphics blitting at 100fps and it runs perfectly, even on a Celeron 1.7Ghz... though I've yet to try it on a slower machine.

The Question is, can anybody explain to me clearly on why this is happening? I mean, if you notice carefully, D2's graphical movement is somewhat jerky if you are strict abt it but it's acceptable at 25fps - since VCDs run ard 30 fps...

If 25 fps is only slightly jerky, 50 fps should be smoother significantly, but in my game I only see the same jerkiness as I do in Diablo 2.

I would really appreciate some really helpful enlightenment on this matter.
0
Comment
Question by:thrawn80
  • 8
  • 8
  • 2
  • +1
21 Comments
 
LVL 17

Expert Comment

by:davebytes
Comment Utility
First, you should be flipping, not blitting...

Second, Diablo 2 in general is using D3D for acceleration when available, and is running in 16 or 32 bit.  It can also run, I believe, in 8-bit software rendering.

Despite those facts, if you use DX properly, the difference between 8 and 16 bit should be negligible on any decent machine (say 1Ghz as a starting marker).

How are you gauging the framerate of Diablo?  And your game?  Have you tried using FRAPS or other third party tool to see exactly what FPS you and d2 are actually getting?

Trying to determine that two games 'feel' the same by 'feel' is a bit dangerous... If your game doesn't feel smooth, figure out why -- don't just compare to other products on the market... ;)

What do you mean by "VCDs run around 30fps"?  Trying to compare a VCD to a computer game's 'interacticity' is hardly a good matchup... ;)

50fps SHOULD be smoother overall.  But it depends on your input system, your update system, etc.  Are they running time-desynchronized, using millisecs-between-calcs to determine delta-time changes?

How are you doing your frame-per-delay calculation/wait?  Is there a reason you are waiting at all?  Do you need to lock your game to only 50fps for some reason?

-d
0
 

Author Comment

by:thrawn80
Comment Utility
Thanks for your guidance on this matter.

- How are you doing your frame-per-delay calculation/wait? -
my game is running based on a simple algo,

1) while(GetTickCount() - dwStartTime < 20); - that's for 50 fps

2) while(GetTickCount() - dwStartTime < 10); that's for 100 fps

currently I'm using (2). all my other physics objects doesn't rely on time to determine how much they should move becoz there is a dependency on the local computer's hardware performance. (vid+cpu)

therefore, for example, if there is an instruction to move a game object at  x(0), y(-1) for 2000 milliseconds,
the movement will be calculated in (No. of Frames to Move).
So, if my physics engine is running 50 fps, the number of frames to move the object would be 2000/50 = 40.
So therefore, if my game is running on a very slow machine, even if the game is slow, the objects will still reach their destination. By using time, I'll most likely get an object ending up in different places for machines with difference performance.

- Is there a reason you are waiting at all? -
Yes. There is. The reason to wait is simply to lock the game at this particular frame rate for PCs that can handle my game much better. For example, if there is a super fast PC in the future say... 7Ghz cpu (just an example), my game will still run at 100fps and will not be faster due to the faster processor.

- Do you need to lock your game to only 50fps for some reason? -
Yes and No.
I believe I've explained 'YES' in the previous paragraph.
No, that's because my game allows frame skipping.

- How are you gauging the framerate of Diablo? -
I did not gauge the frame rate of Diablo 2. I've gotten the information from a group of supposedly-beta testers for the game. I was looking for runewords in the webpage when I encountered this piece of information. (25 fps)

However I did have another gauge which came from NES emulators. Most emulators for very old consoles runs at 50 fps. And the feel is extremely smooth. Agreed on the point when you said that :
- Trying to determine that two games 'feel' the same by 'feel' is a bit dangerous -
Even having played games for almost 2 decades, I won't dare to champion on feelings.

- First, you should be flipping, not blitting... -
Yes. Flipping of a secondary buffer surface with the primary surface is something that is understood by all DX developers using DirectDraw. Even Direct3D guys do that.

What I meant by blitting is the graphic processing I'm doing to the secondary buffer (back buffer).


- If your game doesn't feel smooth, figure out why -- don't just compare to other products on the market... ;) -
Good point. But how about this,

1) If my game can't run smoothly on 50 fps, increasing fps to 100 doesn't really help isn't it? It can be due to poor graphic processing or optimization or poor code optimization then. Morever, increasing the game fps to 100, directly increased the senstivity of the game. Sensitivity define as in, now I only have 10 ms to process my entire game logic. If during this time, another process is running at the same time and it takes more than 10ms to process, the tendency of my game lagging would be much higher than waiting for 20 ms(which is 50 fps). However, despite this sensitivity, my game did not lag much with other background processes running.

2) But my game runs well on 100 fps, that means the system can handle it at 100 fps. It doesn't make any sense if my game runs poorly on 50 fps but performs so well on 100 fps.

3) All my bitmaps surfaces are stored in Video RAM. It's the fastest and I used BltFast for almost every sprite except sprites that needed to be scaled, only then I'll use Blt. Morever, most of my codes are optimized using direct pointers, which means I don't have to search for a weapon to fire, and that when I have the weapon, I don't hav to search for the Sprite reference and the soundFX reference. It's all being formulated before the game starts.

The 1st and 2nd points are the ones that led me to posting this question.




0
 
LVL 17

Expert Comment

by:davebytes
Comment Utility
I'm assuming dwStartTime is set as the tickcount at the start of each frame, and you are waiting at the end for the 'excess' counter to run out.

Yes, if you are having stuttering even at 50fps, increasing further shouldn't make a difference.  That would lead me to believe that you have a problem in some of your math somewhere causing stuttering.  If you have it at 50, but not at 100, you might be hitting a case where you are just under/over the time boundary each frame.

Remember to track and account for 'roundoff error' in the time calculations.  i.e., you might be running in 50fps mode, and 22ms just passed.  Hold onto the extra '2ms' and add into the next frame delta to ensure you are smoothly stepping each frame and not drifting over time.

In some sense, you'd be better off VSYNCing, and 'unlocking' the framerate completely.  It'll slow down the lower end machine a teensy bit, cap the higher end machines, and everything runs smooth.

The reason for the 50fps number is that PAL video runs at 50fps (wheras NTSC video runs at 60fps).  So you'll see 25/30/50/60 as core numbers everywhere.  Normal movies/film are typically shot at 24fps, though a lot is changing with digital technologies...

If something is off in your math, or you ARE VSYNCING AND TIME-CAPPING at the same time, that'd lead to potential hiccups in lower framerates.  Missing Roundoff-Carryover at lower framerates might do this too.

Lastly, you'd be better off if your physics system worked in milliseconds natively -- I couldn't tell if it does or not.  Your initial sentence seemed like it was determining number of frames to compute, but you are better off just using the raw number of millisecs elapsed since the last physics run, and compute that much delta change.

Any of that help/make sense?

-d
0
 

Author Comment

by:thrawn80
Comment Utility
Thanks again.

You caught my attention to that 2ms extra...
I'll go and anaylze furthur and get back asap.

My physics system worked in ms initially but if you want to work without missing an extra frame, probably I've to use threads. However I don't think threads are that cost-worthy in my case now. The physics system using ms has some strange effects. Ships move different distances for different machine speeds which is typically wrong. Say if I have a ship to move 5000ms (5secs) for Y(1), on the screen, if the fps is 50, I'll get 5000/50 which is 100 pixels.

Therefore, by right if the ship is at POINT(50, 50), the command to move Y(1) for 5000ms should land the ship in POINT(50, 150) accurately.

Some slower machines may cause the ship to stop pre-maturely before its actual destination.
0
 
LVL 17

Expert Comment

by:davebytes
Comment Utility
Ahh.  Well, two things.  First, the system should store its end-objective as an absolute, and ensure that at time t=5000ms, pos=50,150.  That's not a physics system, that's an absolute positioning system with inbetween animation... ;)

Second, you don't need to thread it.  Watching for the drift is easy enough to do in code.  And moving based on ms you can easily shift things into fixed point or floating point math for better precision.  Also, you shouldn't actually try to divide up the movement into per-frame portions that you then apply -- rather, for the current frame take the starting time of the movement and the total time of the movement, divide to get a percentage through the movement, take the start and end locations, multiply by the percentage to get the positional offset, and place there in inbetween frame.  better accuracy, smooth no matter what.

-d
0
 

Author Comment

by:thrawn80
Comment Utility
Ic...

Firstly, I don't encourage the use of percentages during real-time games or high fps... coz it involves division and multiplications...

Secondly, back to the main question...  It could be a calculation fault that caused this problem. But doesn't 1000/10 gives 100?

Hmmm... anyone?
0
 
LVL 4

Expert Comment

by:Fippy_Darkpaw
Comment Utility
""So, if my physics engine is running 50 fps, the number of frames to move the object would be 2000/50 = 40""

I think your physics looks "jerky" because you are using a set number like that. The elapsed time between every frame is going to be different every time. Your update function should get the elapsed time since the last frame, then base all movement on that.

For example you could have an update() function like this, where each object;s movement is based on it's velocity multiplied by the time_elapsed since last frame.

void Update(float time_elapsed)
(
   // distance_traveled = velocity * time_elapsed
  // position = position + distance_traveled
}

This method also keeps object movement the same regardless of CPU speed.
0
 
LVL 17

Expert Comment

by:davebytes
Comment Utility
First, if you are trying to avoid divs and muls to achieve a 'real time' game with high FPS, I've been coding 3D games in C++ for over a decade -- lots of math, only avoided things when they needed.  Core calculations of the offset to move things per frame should be done in high precision -- my solution was to do a percentage offset of movement based on the new frame time... doesn't get more precise than that. ;)

As for your Q, depends on WHAT the "100" (1000/10) is USED for.  If you aren't calculating your overall delta time per frame properly, you could be losing ms here and there, or many ms per frame, pretty easily.

-d
0
 
LVL 3

Expert Comment

by:teratoma
Comment Utility
If there's a "jerky" feel to the game then there's a massive CPU or I/O hog in there somewhere, a bad algorithm.  A simple vertical shooter should not be sluggish on any platform.  The fact that performance increases when you double the allowed framerate is evidence for this.  Fine-tuning won't help here.
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:thrawn80
Comment Utility
Again, thanks for your replies.

ike I said earlier, if it's already a bad algo, increasing the framerate by double doesn't help at all. In fact, they wouldn't be any improvements at all. Based on your expertise and experience, what could I have done to better improve this situation? Any better blitting algos?

Only a consistent algo will respond correctly (ie the smoothness) to framerate changes, ie, 30, 50 or 100fps..

Regarding percentage offset of movement... may I ask, if I have 500 objects in the game. including debris, explosions, projectiles and ships, if I haveto offset every single object's movement using percentage, wouldn't it slow down the game?

void Update(float time_elapsed)
(
   // distance_traveled = velocity * time_elapsed
  // position = position + distance_traveled
}

Agreed on this piece of code. As I'm trying as much as possible to avoid divs and muls... I might try it on this code to see the impact on 500+ objects... Thanks for your contributions :)

My velocity is biased towards the final position rather than the final time it took to reach there. True, davebytes may feel incorrect in that sense since you're a 3D C++ prog for decades... however, that isn't much of a concern when it comes to the pace of the game. Not that I disagree with you, but it would seem that the slight in timing isn't noticable by the gamer.

I'll get more feedback in that aspect.


0
 
LVL 17

Expert Comment

by:davebytes
Comment Utility
500 Divs or muls is nothing.  I'm talking about doing thousands of matrix operations (vertex transforms) per frame -- 6 or 7 years back!  if you had thousands of objects, and were running typically on <1GHz machines, then maybe worth looking at.

I generally try to engineer properly, THEN optimize.  Don't outthink yourself. ;)

You should be able to pre-calculate the per-ms floating point offset to move the object, store all locations in floats (or do it in fixed point if you really need to), and there's no per-frame % calculation -- but you store all deltas in ms, not in 'frames'.

d
0
 

Author Comment

by:thrawn80
Comment Utility
Hi davebytes,

I do respect ur experience in games programming and also in 3d games programming. However,
1) You're not answering the question I've asked in the beginning
2) Your solution seems ok but unclear. You keep mentioning deltas in ms but have you really explained them? Or do you expect me to understand all those terms myself?
3) I'm not outthinking myself. My game is by far, engineered much properly than u can ever think. Least to say, it's simple. Every logic runs in simple and concise codes including storage algorithms. From there only then, I start to optimize. However, optimization isn't the QUESTION!

4) My question is still very simple. My game runs smooth of 50 fps but not satisfactory smooth enuf compared to 50 fps console games. You may say that I should try to use VSYNC, fine. Please elaborate on that. I honestly admit that I'm not too sure whether what I'm doing is VSYNC or not. My monitor is refreshed at 50Hz. (Vertical refresh) That's 50 cycles per second which is supposedly the same as my game speed.

5) My argument is that, if my codes are bad, why does it run well on 100 fps instead? A lousy piece of rendering will be that slow regardless of how much less you want to wait per cycle.
So what else could have caused this dissatisfactory results? - Note : I'm not asking for optimization solutions.

6) Your experience has made me respect you. But answers don't. Simply because they are not the solutions or A solution at all. Perhaps your answers may sound very simple to you, but to a beginner like me, it doesn't. Why don't you look back at the time when you first started games programming, if someone posts that kind of answer to you, will you understand?

7) Moreover, it's strange that you'll think that I'm blitting my sprites to the primary surface. Strange, because FLIPPING chain is a method that is known to all DirectDraw programmers. This actually already made me feel rather uncomfortable.

I'll be honest with you, Flippy_Darkpaw's solution is much more easier to understand. But then again, calculating the amount of pixels the object should have moved based on ms is a killer for vertical shooting games. Imagine if my comp lags for 4000 ms due to some external IO going on, and my game was suspended or lagged for 4000ms. You'll see a ship "teleporting" from one place to another isn't it?

Lastly, I'll say again. Time accuracy isn't my concern. Ship's final POINT pos is my concern. I don't mind ships arriving late (they never arrive early if based on frames).

0
 
LVL 17

Expert Comment

by:davebytes
Comment Utility
Well, I've put more time and thought into this 200pt question than most 500pt questions!  If I gave answers that seemed more 'advanced', that's because I took some of your answers to imply you had deeper understanding of things.

1) You've asked a question which is, at some level, unanswerable.  "Can you tell me why my code hiccups?"  No.  I >can< give you things to look at and think about.

2) If you don't understand the term 'delta', then... well...  You should know the number of milliseconds that have passed since the last frame.  That's what I mean by delta in ms.  If you base everything off that delta, rather than assuming that every frame will be exactly N ms, you should get smoother animation.

3) If you are questioning whether an extra 500 divides per frame is going to be an issue, then you yourself MADE optimization part of the question.  Otherwise, you could have tried to implement at least a few different approaches by now to see if your computation of offsets is at all leading to the perception of hiccups.

4) If your visuals aren't as smooth as 50fps console games, then you need to re-evaluate the method you are using for animation/movement of objects on screen.  Sounds like you aren't compensating for differences in deltas from frame-to-frame, and aren't necessarily accounting for any kind of time drift or other 'missing' time.  As for VSYNC, you either are or aren't.  If you are, you really have no need to 'wait' for the end of a frame, just wait for the flip to complete.  And I guess if you are overseas, you might have a monitor running at 50Hz -- I've never myself had a computer monitor running lower than 60Hz.

5) Without seeing the game, seeing the code, I'm just throwing darts blindly... I've gotten no better feeling for the game you are creating, or whether the approach you are taking is 'sound', than I was in my first response.  Problematic time/delta calculations might just show as more obvious hiccups at 50fps than at 100fps -- you could still have problems in your code, it just isn't as apparent, or rounding/offset/drift isn't as bad.

6) Again, my apologies for inferring from your responses that you were more than a 'beginner'.  Based on your responses, mine seemed in line.

7) I've never thought you were blitting sprites to the primary, and never said that.  However, people DO blit from an offscreen or the backbuffer to the primary/front-buffer, rather than flip, for whatever reason.  Thus my comments in my very first response.

I'll leave you with a final thought: ships should never arrive 'early' OR 'late', they should be where they are supposed to be at any given ms snapshot in time that you want to break the system down at.

-d
0
 
LVL 4

Expert Comment

by:Fippy_Darkpaw
Comment Utility
Personally I think the jerkiness is due to using a set number as the elapsed time. I did a physics movement simulator for Graphics class, and when I used a set number as "time elapsed" in my calculations the movement was not fluid. Probably because, as mentioned above:

- time elapsed between frames is usually not the same
- you "lose" time if you exceed the cap
- if your app is v-synced you get even more lost time, since you to wait for the the next refresh

When you set it to 100FPS the movement was smoother, however on a lower spec machine that would probably make things worse. They would exceed the set time every frame. If you really want to leave your code "as is", just set the Frame Rate to 100FPS for all machines above a certain Mhz CPU, and set it to 50FPS for those lower. Then you don't have to change your code at all.
0
 

Author Comment

by:thrawn80
Comment Utility
ahhh... an interesting perspective...

From your points, I seem to derive "sensitivity". High speed CPU don't face this problem as their processing power will somehow keep things in place... but a Low Speed CPU will yield results much worse than expected...

Hmm... I'll do a trial run using a P3-600mhz if I can find one nowadays...

Thanks for your suggestions!
0
 

Author Comment

by:thrawn80
Comment Utility
Btw, the snippet of the engine loop code is :

(Sample, not actual)
do
{
    gameEngine->onPaint();
    dwStartTime = GetTickCount();
}while(GetTickCount()  - dwStartTime < 10)

I do agree that if gameEngine->onPaint() takes more than 10ms, the while loop will still proceed but in the process, it becomes a jerk coz since n > 10, while GetTickCount() - dwStartTime < 10 where n could have been much higher than 10

This will definitely coz a paint delay or jerk. However, the graph of jerkiness should be even, that means, more objects, more processing time, and therefore more (n)s

supposedly if n becomes > 10, the jerking will begin depending on the delay of the next painting and processing frame.

So if I change the following :
do
{
    gameEngine->onPaint();
    dwStartTime = GetTickCount();
}while(GetTickCount()  - dwStartTime < 20)

Now the game has more "room" for delay coz the minimum waiting time is 20ms (to get 50fps controlled fps). So therefore, the chances of the game jerking is lessened by this increase.

However, at 50 fps, the game still looks OK. Smooth but not that smooth. No jerks but neither is it fluid. The framerate is consistent.

Therefore at this conjecture, any suggestions for handling the overflow of the ms?
Thanks.

0
 
LVL 17

Expert Comment

by:davebytes
Comment Utility
That's exactly what you CAN'T do, as you have zero control over the elapsed time.   I thought that was clear, but let me draw you the quick example.  You want something more like:

do
{
    dwStartTime = GetTickCount();
    gameEngine->onPaint();
}while(GetTickCount()  - dwStartTime < 10)

That is, the TOTAL FRAME TIME is 10ms, not that you 'wait for 10ms' AFTER the frame is done...

That could easily be the root cause of your hiccups.

Now, if you want something slightly different, the following is more of a MS based delta approach:

dwLastTime = GetTickCount();
do
{
    dwNewTime = GetTickCount();
    dwDeltaMS = 0;
    while(1)
    {
       dwDeltaMS = dwNewTime - dwLastTime;
       if (dwDeltaMS<1) Sleep(1);  // this should be whatever sleep function gives you closest to 1ms sleep...
       else break;
    }
    dwLastTime = dwNewTime;
    gameEngine->onPaint(dwDeltaMS);
} while(bNotQuit)

That make some more sense now?

-d
0
 

Author Comment

by:thrawn80
Comment Utility
I was thinking of offsetting the next TOTAL FRAME TIME instead.

But I'll take a shot at your example. But one thing, you used Sleep(). I used Sleep() previously and it's somewhat slow compared to using a GetTickCount() - dwStartTime < 10... any enlightenment?

Thanks.
0
 
LVL 17

Accepted Solution

by:
davebytes earned 200 total points
Comment Utility
You don't really HAVE to do the sleep -- you can spin-wait on dwDeltaMS<1 on 2K/XP without really bad things happening.

You can also try Sleep(0) for the minimum possible timeout.

Sleep is NOT guaranteed to go away for exactly N ms -- that's just the 'minimum' time.  But in general you are telling the system "you can have N ms -- I don't need to come back before then".

But the above two examples both show methods for avoiding the issue you have -- which is that your code wasn't accounting for the actual frame time, just delaying an extra N ms after each frame...

-d
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Artificial Intelligence comes in many forms, and for game developers, Path-Finding is an important ability for making an NPC (Non-Playable Character) maneuver through terrain.  A* is a particularly easy way to approach it.  I’ll start with the algor…
As game developers, we quickly learn that Artificial Intelligence (AI) doesn’t need to be so tough.  To reference Space Ghost: “Moltar, I have a giant brain that is able to reduce any complex machine into a simple yes or no answer. (http://www.youtu…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now