Fps

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Howdy,
      How does one get a game that runs at 60 fps on a moderate computer, run at the same speed on a fast computer? Does this involve keeping track of the milliseconds it takes the processor to process the game loop? Is the problem of getting the game to play at the same speed on most computers in the book? Could you give the pages covering that topic?

      Thank you!
      n00b
    • Basically this is covered in Chapter 6 - but it is a little buried.

      Basically you split the jobs of rendering and updating the game state, and make sure that the routine that updates your game state does so based on that elapsed time, and not how many times the function was called.
      Mr.Mike
      Author, Programmer, Brewer, Patriot
    • Make sure they're not just split, but also running in different threads. this makes a huge difference, especially on multi-core processors.

      -Rez
    • Hey there hoss,

      If you are going to give that advice, perhaps you can also give us a few secrets in intra-thread synchronization?

      :)

      After all - that done incorrectly that really screw things up!
      Mr.Mike
      Author, Programmer, Brewer, Patriot
    • You're right, Mike. Opening the pandora's box of multi-threaded programming does deserve a bit more of an explanation. I'm not an expert by any means, but I'll give you some of the basics so you at least have enough rope to hang yourself with. ;)

      A thread is a path of execution that, for all intents and purposes, is executed simultaneously with other active threads in the system. Behind the covers it's not truly simultaneous; you have a very complex process manager giving each thread a time slice of the CPU. One thread will run a few instructions, then the next, and so on.

      The biggest problem with running multiple threads is synchronization. You can't guarantee which instructions will be run at what time, which can cause a race condition. A race condition is when the output of a program is unintentionally tied to the execution order.

      Here's a simple example, shamelessly stolen from Wikipedia:

      Let us assume that two threads T1 and T2 each want to increment the value of a global integer by one. Ideally, the following sequence of operations would take place:

      1. Integer i = 0;
      2. T1 reads the value of i from memory into a register : 0
      3. T1 increments the value of i in the register: (register contents) + 1 = 1
      4. T1 stores the value of the register in memory : 1
      5. T2 reads the value of i from memory into a register : 1
      6. T2 increments the value of i in the register: (register contents) + 1 = 2
      7. T2 stores the value of the register in memory : 2
      8. Integer i = 2

      In the case shown above, the final value of i is 2, as expected. However, if the two threads run simultaneously without locking or synchronization, the outcome of the operation could be wrong. The alternative sequence of operations below demonstrates this scenario:

      1. Integer i = 0;
      2. T1 reads the value of i from memory into a register : 0
      3. T2 reads the value of i from memory into a register : 0
      4. T1 increments the value of i in the register: (register contents) + 1 = 1
      5. T2 increments the value of i in the register: (register contents) + 1 = 1
      6. T1 stores the value of the register in memory : 1
      7. T2 stores the value of the register in memory : 1
      8. Integer i = 1

      The final value of i is 1 instead of the expected result of 2. This occurs because the increment operations of the second case are non-atomic. Atomic operations are those that cannot be interrupted while accessing some resource, such as a memory location. In the first case, T1 was not interrupted while accessing the variable i, so its operation was atomic.


      Race conditions are a bitch to deal with because they can have subtle symptoms and it can be hard to pinpoint the real issue. One solution for race conditions is to use critical sections, which are sections of code that you mark as needing to be 100% atomic. In other words, only one thread is allowed inside that critical section at a time.

      Hopefully this will get you started with multi-threaded programming. Like everything else in programming, it's best to start small. Maybe you could create a thread for sound or some other nicely self-contained system to get a feel for it.

      One last note: I've intentionally left out code examples and explanations for setting up threads. I think it's important to look this stuff up because any half-way decent book or website that talks about multi-threaded programming should also show you how to avoid some common pitfalls.

      -Rez
    • Thank you for your replies and info. Mr. Mike, the variables fTime and fElapsedTime used for: calculating frames per second (fps), game updates, and render calls (In chapter six on page 161 and the code on page 164). Do these variables help control how fast the game renders?

      Rez, thanks for the introduction to multithreaded applications. Would threads then be an alternative way to control the fps? What do you think about the ease of writing a multithreaded application in C++? Do you think that other languages (e.g. java) handle multithreaded applications better or worse than C++?
      n00b
    • You want rendering to be as fast as possible. The timing variables are there so you know how much time has elapsed. This is important for many reasons, one being how far to move something each frame during a transformation. If it takes 2 seconds to rotate 180 degrees, it should always take two seconds regardless of the FPS. It'll look smoother with more frames of course, but the time it takes should be the same. If I remember correctly, fTime is the total time elapsed since the start of the game and fTimeElapsed is the time elapsed since the last frame.

      I'm not sure exactly what you mean by controlling FPS with threads, but multi-threading is not a great way to do timing. Although you do have some control over the time slices given to threads, it's ultimately non-deterministic which threads get called and when. Threads are useful for breaking up execution into different paths so that you're not bottlenecking on one thing. Two major places that a bottle neck tends to happen are disk IO and waiting for the monitor to refresh. That's why rendering and disk IO intensive systems (like sound and the resource manager) often get their own threads.

      In Barbie, we had a main rendering/logic thread and a sound thread. We also spawned a thread that took care of loading so that we could show a nice little movie while we loaded in the background, but that thread was killed when you hit the main menu. We took a "load absolutely everything in the beginning" approach because we couldn't afford to dynamically load too much at run-time. We didn't have the CPU budget. In fact, the only thing we did load dynamically were the sound files, which is why the sound system really needed its own thread. (Actually, we might have done the same with cutscene animations; I can't remember.)

      In Rat Race, we split the rendering and logic code into two threads. We also started to implement a more intelligent resource manager because on the PS3, you don't have buckets of vram. Splitting rendering & logic into two threads caused our average FPS to sky-rocket because one no longer had to wait for the other.

      As to your question about which language has a better implementation, I can't really answer that. My multi-threaded programming experience has been exclusive to C++. C++ has no native multi-threading functions; you always use the platform's API. This means that you typically end up writing a few classes that can wrap the API functions of whatever platform you're targeting. A quick google search on Java's Runnable interface seems to imply that it's pretty easy to spawn a new thread. It definitely looks much easier than screwing with the Win32 API (or whatever you're using).

      Bottom line: Threads will not make your life easier. They will in fact do the exact opposite.... but used properly, they will make your game faster.

      -Rez
    • Well said, Rez !
      Mr.Mike
      Author, Programmer, Brewer, Patriot