YAAG

Sign in to follow this  
  • entries
    7
  • comments
    2
  • views
    8213

The Game Loop

Sign in to follow this  
lede

1259 views

The original game was played over the modem and was a turned based game. Since BBS are fairly scarce these days I have made this a stand alone game. Also since blocking input was very common in older games I've changed the game engine to not block input and be more interactive like today's games.

Another difference is the 286 and 386 computers only could run one thread unless you had a multi processor board which in the 80's was very rare. Since this is being made in C++ in a modern compiler I will work on adding multi threading support to the game. Right now because the frame rate is very low (12 FPS) that gives me a ton of time to calculate and draw changes to the ASCII graphics engine.

Last time we discussed the Entity system that I created and we only talked about high level design of the code. This is all fine on a high level but the bugger is in the details of the code. Like last time though I will keep with the painful UML diagrams so we can have a good discussion about the code and how the objects communicate between systems.

EngineUML.png

The first thing I would like to explain is the text in green "IEntity" is referring to the previous UML diagram I posted yesterday. If you need it again please let me know and I'll re-post the image. Now then as you can see the UML diagram is getting complex quickly. There are a lot of interface classes that help abstract items in the core engine. This designs allows for me to have the freedom to create similar type objects without having to ever touch the core engine. In the past month since the core engine had been completed I have rarely touched the code because of this design.

Now then lets start with one of the fundamental parts of the engine. To me the term engine means it loops infinitely or until the user or computer needs it to stop. This is where threading comes into play because now we can have the GameEngine, PhysicsEngine, and SoundEngine run on their own threads. I tried to break the components down into section that either would have a lot of calculations or would take time to load. So the core function in the IEngine class is RunEngine. This is like when you start your car or pull the ripcord on a lawn mower. Once the engine starts running it goes until it is time to quit. The reason for the return value int is so that we can use that to report back to the OS how the program exited.[code=auto:108]//... Init code has been clipped for brevity.// The game loopdouble time;do{ time = clock(); // Get when this frame time started Update(); // Run the update system // Check default controller for the [ESC] key if(Controller()->ChkInput(VK_ESCAPE)) { _isRunning = false; // Set the run state to false, Game over man! continue; } int sleepTime = static_cast(time + MS_PER_FRAME - clock()); if(sleepTime > 0) { /... Cliped more code from this section for this discussion // Burn some time since we got done with out work early today! std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); }}while(IsRunning());// Shutdown the engine code as we exitreturn iRetVal;
So this is the engine loop or game loop which ever you prefer to call it. Most of these loops I have seen use a while and in this one I used a do. This was because I wanted the engine to run at least one frame since it was fairly safe to do even if everything was not properly setup. I'm also not a big fan of the while(1) loop idea because it leaves room for an infinite loop bug. I prefer the bool variable based loop control so that my code can properly handle shutting down the main loop. There really is no advantage to either way and is a personal preference of mine. You could re-write the loop using a while(1) and just add a break instead of the continue statement to shutdown the game engine.

The nice thing in the engine if you want to disable the [ESC] key from shutting down the engine and you want to take over this control in the game logic then you can do that by setting the controller to a NullController instance. Originally in my game before I had the game logic built to exit the game I used the [ESC] key to shutdown the game. But once I had the exit define and it was able to gracefully shutdown the game I removed the KeyboardController from the game engine and put the NullController there instead. If you are doing the same then let me warn you first make sure your game logic will shut down perfectly before turning this functionality off.

The next important thing is the timing of each frame. I know there are a lot of complicated calculations out there and I believe from my Game Patterns book he recommended using a simple approach to the frame rate. In this example I just calculate how long each frame should take which is MS_PER_FRAME = 1000 / 12. Now when the engine has extra time left over it will put the thread to sleep so your computer can do something else. Other designs try and suck every tick out of your processor and leave your computer in a defunct state until the game exits. I prefer to let you use your computer and play my game at the same time.

Now the hidden part of the code is in the Update method. This method gets called each frame and will process updates for every Entity and Updater item in the list. If we have time left over then we can draw the updates to the screen which has introduced an update lag and draw error. I haven't solved this issue yet but I have an idea that if in one frame you ran the update but ran out of time to draw it to the screen the next frame should draw and not update. This would solve the issue where the game could freeze and the next time a frame gets drawn you jump across the screen. Also since I'm using an ASCII graphics engine and don't render the full screen every time it would help prevent artifacts from drawing on the game field.

That is all I have time for today but stay tuned for the bug fix and the update method.
Sign in to follow this  


0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now