|
Game Engine that conserves CPU |
Myrdos
Member #1,772
December 2001
|
This is a continuation of the OT discussion from this thread, on how to write a game engine that uses less than 100% of the CPU on fast computers, but automatically uses more CPU time as needed on slower computers. Here's a simple program that implements such a system. Try it out to convince yourself that it works.
Quote: if you're computer is fast enough, and it is sitting in a busy wait loop (pushing cpu usage to 100%) you should yield/rest then... no? That is exactly what this does! If you're redrawing the graphics but there was no logic update since the last redraw, you're "caught up". You have time to kill. So sleep. But if there was a logic update, your game is still chugging away. So yield. Yielding is optional, but it helps ensure smooth multitasking if there are other programs running, or if your program is multi-threaded. __________________________________________________ |
Goalie Ca
Member #2,579
July 2002
|
I honestly believe the best way to do such a game loop is to have a timer that can wake up a blocking (sleeping) main loop thread. All the rest still boils down to polling. But in order to have such a timer you can't use the allegro timer. A library would have to be written or os specific code would have to be used. edit: ------------- |
Kris Asick
Member #1,424
July 2001
|
And this is all presuming you do fixed frame calculations. For almost three years now I've been programming real-time instead of fixed-frame and the concept of frame dropping has sort of eluded me as a result. My real-time timers give 1 ms of time back to the CPU every frame to prevent I/O issues with Windows 98 and recent Allegro versions. This also means that at lower framerates, less time is given back to the CPU, and at higher framerates, more time is given up. Also, with vsyncing enabled, the time spent waiting for a vsync also gives the CPU a break. My recent game, PixelShips Retro, at 120 FPS, measures only 30%~40% CPU usage on my 2 GHz, Windows 98 system. Granted, it's also running at a mere 320x240x8bpp graphics mode. Though on some systems the CPU usage barely registers for some reason, even with vsyncing off... shrugs --- Kris Asick (Gemini) --- Kris Asick (Gemini) |
Michael Jensen
Member #2,870
October 2002
|
My apologies for derailing the other thread... Audric PM'd me a longer explination, I think Goalie Ca is on to a neat idea... Does vsync() actually cause the main thread to sleep? I thought it busy waited also... KA: could you elaborate? It doesn't sound like you're using allegro timers.
|
Audric
Member #907
January 2001
|
vsync() is a busy wait on win98. edit: I rechecked: mingw executable of "exmouse" uses vsync for speed control : I get 100%CPU. |
Albin Engström
Member #8,110
December 2006
|
woah, hold on to your horses! , you mean that using vsync would cause a 100% cpu usage on win98 systems?!?! that's insane :S and i'm confused.. |
Kris Asick
Member #1,424
July 2001
|
Audric: Wasn't sure of that. Thanks. Albin Engström: Based on what Audric said, yes it would, but only if you never gave any time back to the system with rest() or Sleep() commands. Michael Jensen: I was using the Allegro timers at first, then I found a way to use the Windows high performance timers thanks to other forum goers here. As a result, my routines are now able to use either. (But prefers my own since it's more reliable than the Allegro ones and only uses the Allegro ones if the high performance timer is mysteriously unavailable.) The way I do it is to run a timer at 2400 ticks a second, since this rate compares the most easily with the multitude of screen refresh rates out there, and I time my logic to this using floating point values where 1.0f = 1 second. (Thus one tick is 4.166... microseconds.) I also pick 2400 because the Allegro timers handle it better than higher values I've tried. Thus every frame I update and check the timers to see how much time has passed since the last frame, and update my logic by that amount, and since everything is floating point, everything is updated at the proper rate, whether the framerate is 10, 100, or more. In the extremely unlikely event of a zero-frame (not enough time has passed to increment the tick counter) then the game logic is processed with a multiplier of 0.0f, and thus goes nowhere until the next frame. I also do frame interpolation in PixelShips Retro, but that's another topic entirely. (Side Note: The Allegro timers ALSO use the Windows high performance timers when they are present... but because they work on an interrupt basis they don't always give the exact value they should. Directly accessing the Windows high performance timers can thus be more accurate when done right.) --- Kris Asick (Gemini) --- Kris Asick (Gemini) |
Audric
Member #907
January 2001
|
Albin: yeah, it was a surprise to me too. Maybe I disabled vsync in the DirectX settings for the graphics card ? It's possible I did, but I can't remember nor find the parameters right now... |
Albin Engström
Member #8,110
December 2006
|
er.. i think i'm even more confused now.. would'nt the cpu reach 100% even without vsync? in the case that the program used no rest or sleep?? :S |
Goalie Ca
Member #2,579
July 2002
|
I decided to implement some code. This is for linux/mac only at the moment. Windows support should be trivial to add though. Someone could please add it? ATM this uses absolutely 0% of the CPU time. This isn't the best solution out there but its simple for most people. If your code runs slower than BPS this code will slow it down even more as it waits an extra tick for a release. I haven't tested that but you guys shouldn't have a problem. DO post any revisions to allegro.cc I would like to make this an add-on library or something for people or something. I suppose if we went the c++ route we could use boost/mutex for cross platform. If not it'd be best to do a bunch of #ifdef WINDOWS etc. and add a few threading utilities. I believe SDL has threading
edit: for those of you interested this is potential windows code. I believe though that by including windows.h you require a winmain function etc. This should be fixable by just including what's needed. This one hasn't been tested.. edit2: appears its in winbase.h , maybe that helps maybe it doesn't
------------- |
Myrdos
Member #1,772
December 2001
|
Here's the C++ version of a windows/linux friendly mutex, should be easy to convert to plain C. Should be, but I'm just too tired.
DyMutex.cpp:
[EDIT]Looks like you've got it already. __________________________________________________ |
Goalie Ca
Member #2,579
July 2002
|
Quote: Looks like you've got it already. Not really. You put it together in a single class. I also need to put error handling etc. The only question I really have though is about including files. I noticed you don't include any windows header files. The little i do know about windows.h and winapi is that you can't really mix and match it with anything else without issues. I tried to include windows base but i'm not sure if that requires winmain like everything else. Also.. say it does... and a user needs to call winmain.. how does that play with allegro!? edit: ------------- |
Myrdos
Member #1,772
December 2001
|
Quote: The only question I really have though is about including files. I noticed you don't include any windows header files. It's been forever since I've looked at this... the original class is from my networking lib, viewable here. My includes are in another class: 31 #include <ws2tcpip.h> 32 #include <winsock2.h> ...Probably not what you want to use, since you aren't doing networking. And of course this code in my Allegro programs that use the lib: #include "allegro.h" #ifdef DY_WINDOWS_VERSION #include "winalleg.h" #endif And it just seems to work. I've never had any problems with it not blocking. (I use MinGW) However, it's been a long time since I wrote this code, and there might be something I've forgotten... __________________________________________________ |
BAF
Member #2,981
December 2002
|
Quote: edit: for those of you interested this is potential windows code. I believe though that by including windows.h you require a winmain function etc. This should be fixable by just including what's needed. This one hasn't been tested.. I think you only need WinMain if you are creating a Windows (Windows, menus, etc), and even then I'm not sure. I know I have used windows.h and winsock.h with just plain main before. |
KnightWhoSaysNi
Member #7,339
June 2006
|
This guy has an interesting timing tutorial with many methods. I think he shows how to do a timer that doesn't use 100% cpu. I only read it for timeGetTime() though. |
|