Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

If you take any turn based RPG game there will be large periods of time when nothing is happening because the game is looping over 'wait_for_player_input'. Naturally it seems sensible to use this time to update things.

However, this immediately seems to suggest that it would need to be threaded. Is this sort of design possible in a single thread?

loop:  
if not check_something_pressed:  
    update_a_very_small_amount  
else  
  keep going

But if we says 'a_very_small_amount' is only updating a single object each loop, it's going to be very slow at updating.

How would you go about this, preferably in a single thread?

EDIT: I've tagged this language-agnostic as that seems the sensible thing, though anything more specific to Python would be great. ;-)

Second edit: This game is not planning on having any animated components; that is, I'm currently running it as a wait-for-player-input then update everything and draw. So rather than X FPS it depends on the user's speed.

share|improve this question

4 Answers 4

up vote 7 down vote accepted
+100

Yes, its possible to do in a single thread. Generally speaking though, you'll want to be updating the objects every frame and not just when there are spare cycles. Your animations and movement will be disconnected from the frame rate and look rather choppy if you don't. If you're talking more about AI updates or something else that does not need to be real-time, I would put a timer on it. You should know what your target frame rate is and the idle time will be whatever is remaining after everything else has been completed.

Let's say you're targeting 60 FPS for your game. That leaves you with 16.667 ms to perform all of the work you need to do each frame. At the beginning of the game, get the current time using the highest resolution timer available, add 16.667 ms to it and store it somewhere. I think the function in python is time() though it has been a while since I worked in the language. After your processing is complete, enter a loop that checks the current time against the time you've recorded. If the current time is less than the frame end time, update_a_very_small_amount. I wouldn't worry much about the processing going past the end of the frame since your small update should be quick to process. It would only be a slight delay to the start of the next frame and you appear to have enough idle time to handle it.

After the frame has finished processing, add 16.667 ms to the time that was stored for the end of the last frame to find out where the end of the next frame should be. If you use the current time + 16.667 ms and the processing goes over, the end of the next frame will be pushed out by however much time the last frame ran over.

Re: Second Edit

To clarify, I use the term frame-rate here to indicate one iteration through the main loop. If it's based off of the user's input speed, I imagine that your goal is to simply make the game feel responsive. Otherwise you could just check for input and update everything each time through the loop even if it takes 10 seconds to do so. To make it feel responsive though, you'll probably want to check for input around 20 times per second which gives an effective frame rate of 20 FPS, even if you're not actually drawing these frames. This would give you 50 ms to update things before you need to check for input again.

share|improve this answer

For Python specifically you can try and use Coroutines to do calculations over multiple update calls.

... coroutines are program components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations...

PEP-0342 details coroutine implementation in Python.

You can create your own scheduler and tasks which can simulate multithreading on a single thread. This is the same way that Javascript frameworks allow for multithreaded like processing even though Javascript is run on a single process.

share|improve this answer

Yes this is possible. Your game will have some kind of main game loop. Something like this:

while(gameRunning)
{
  checkUserInput()
  updateGame()
  renderGame()
}

In updateGame you can iterate over your game objects and update them "a little". If you are doing any heavy calculation in this method the game will simply hang. So you need a way to split up these calculations to run over several iterations of the game loop.

How to split them up, depends on the kind of game you are building. Suppose you are have a path finder routine which uses A* to calculate a path through a labyrinth. You would need to stop the algorithm after a certain amount of time or after a fixed amount of iterations, keep the calculated path so far and return control back to the game loop. The path finding will continue next time updateGame is called. You can even move the character along the partial path while it is still being calculated.

Most times you don't need to worry about the updateGame call taking too long.

"Premature optimization is the root of all evil!"
If you do hit a performance bottleneck in your update routine, that's the time to investigate and optimize. Since you cannot know in advance what parts of your game will take the most time to compute and might waste time optimizing the wrong stuff.

share|improve this answer

The way I understand your question is that basically you're asking about cooperative multitasking.

Basic infrastructure would be a list of function pointers, all called in a round-robin manner (unless a more sophisticated prioritization is required), and all these functions would do "a little bit of work", small enough not to cause the game to become sluggish. I've done this in DOS before threads were hot, and also on mobile devices that didn't support threading.

A better question, in my opinion, is what to do while waiting for the player to move. What kinds of things would be so processor-intensive that they can't be performed on the fly anyway, while, at the same time, being so optional that if the player just hammers some move key fast enough, the game doesn't have time to process these. Thus, stuff like calculating A* for a couple thousand AIs is out.

Better solution, in my opinion, is to simply yield/sleep, and let the computer's power management do its job. Laptop users will like you better for it.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.