Python has this really neat feature called generators. I've found them to be incredibly useful in my code, especially for games. You see, it turns out they're great for handling animations, scripted sequences, and a whole bunch of stuff.

I'm going to talk primarily about generators in Python here, but generators exist in many other languages such as C# and Javascript, and I believe Unity3D also makes use of them for animations and such.

Coroutines

If you're not familiar with the concept of a coroutine, excuse me while I blow your mind somewhat. When one calls a regular function, otherwise known as a subroutine, something like this happens:

          function_a () {                       function_b (x,y,z) {
     [ ]      ...                      .---->       ...
    state     function_b (x,y,z)   ----'            foo = 5
     held     ...                    call          ...
          }                                     }
  1. The state of calling routine is recorded and execution jumps into the called subroutine with any arguments it was called with.
          function_a () {                       function_b (x,y,z) {
     [ ]      ...                            |      ...              [ ]
              function_b (x,y,z)       exec. |      foo = 5         state
              ...                            v      ...             held
          }                                     }
  1. Execution continues until the subroutine returns. During the subroutine's execution it may have its own state, using local variable for example
          function_a () {                       function_b (x,y,z) { \ /
     [ ]      ...                    return         ...             -   -
    resume    function_b (x,y,z)   <---.            foo = 5          / \ 
     state    ...                      '----        ...             state
          }                                     }                   lost
  1. The called subroutine's state, i.e. its arguments and local variables, are discarded and execution jumps back to the point where the subroutine was called from, possibly with a return value if it returned something. The state of the calling routine is restored.

Coroutines are different. Program execution can jump between coroutines without their state being discarded. An example might go something like this:

          coroutine_a () {                      coroutine_b (x,y,z) {
     [ ]      ...                      .---->       ...               
    state     coroutine_b (x,y,z)  ----'            coroutine_a ()
     held     ...                     call          ...
              coroutine_b (x,y,z)                   ...
          }                                     }
  1. The state of calling routine is recorded and execution jumps into the called coroutine with any arguments it was called with, same as before.
          coroutine_a () {                      coroutine_b (x,y,z) {
     [ ]      ...                      exec. |      ...                 [ ]
              coroutine_b (x,y,z)            v      coroutine_a ()     state
              ...                                   ...                 held
              coroutine_b (x,y,z)                   ...
          }                                     }
  1. Execution of the coroutine continues. The routine has its own state.
          coroutine_a () {                      coroutine_b (x,y,z) {
     [ ]      ...                      call         ...                 [ ]
              coroutine_b (x,y,z)   <---------      coroutine_a ()     state still
              ...                                   ...                  held
              coroutine_b (x,y,z)                   ...
          }                                     }
  1. The coroutine hands execution back to the calling routine, however its state is NOT discarded - it is preserved in the same way the calling routine's state was.
          coroutine_a () {                      coroutine_b (x,y,z) {
     [ ]      ...                     call          ...                 [ ]
    state     coroutine_b (x,y,z)       .---->      coroutine_a ()     resume
     held     ...                       |           ...                state 
              coroutine_b (x,y,z)  -----'           ...
          }                                     }

          coroutine_a () {                      coroutine_b (x,y,z) {
     [ ]      ...                                   ...                 [ ]
              coroutine_b (x,y,z)                   coroutine_a ()     
              ...                     exec. |       ...                
              coroutine_b (x,y,z)           v       ...
          }                                     }
  1. The calling routine once again invokes the subroutine. The subroutine recovers its state, and continues execution from the point it got to last.

Execution can quite happily ping-pong indefinitely between two coroutines in a way which may be quite alien if you're used to thinking in terms of subroutines and their call stacks. Curious, no?

Python Generators

Python generators allow you to do something a bit like this. A generator behaves like a regular Python function, but preserves its state when it passes execution back to the calling function using a special yield statement.

A trivial example of a Python generator might be something like this:

>>> def integers():
...     i = 0
...     while True:
...         yield i
...         i += 1
...

We define the generator the same as we would define a regular function. The key difference is the inclusion of the yield statement which indicates to the compiler that this is a generator function. integers can now be called to create a new generator. Each time we iterate the generator with its next method, it executes up the the next yield statement and passes the value of i back to us.

>>> g = integers()
>>> g.next()
0
>>> g.next()
1
>>> g.next()
2

The state of the generator, and therefore the value of i, is preserved between calls.

The ping-ponging described in the previous section could be accomplished in Python with something like this:

>>> def myfunc():              >>> def mygen():
...     g = mygen()            ...     while True:
...     while True:            ...         print "now"
...         print "how"        ...          yield
...         g.next()           ...          print "cow"
...         print "brown"      ...          yield
...         g.next()           ... 
... 

When myfunc is invoked, the function and generator will happily pass execution to and from each other forever - no stack overflows involved:

>>> myfunc()
how
now
brown
cow
how
now
brown
cow
.
.
.

Now of course, there's nothing particularly special about how this generator object behaves. One could easily create a Python object which, when iterated over, behaved the same way; returning "now" and "cow" alternately. What would the implementation of such an object look like, then? Well, how about this:

>>> class NowCow(object):
... 
...     def __init__(self):
...         self.cow = False
...         
...     def next(self):
...         if self.cow:
...             self.cow = False
...             return "Cow"
...         else:
...             self.cow = True
...             return "Now"
... 

What we've created here is a state machine. The object preserves the cow/now state between calls to next, by using a boolean, and this state is checked on each call to determine how the object should behave. This is fine, and for many problems this is a great solution. Where generators come into their own is for defining a linear sequence of states in a concise and natural way. This leads me to how you can use them to great advantage in games.

Generators for Scripted Sequences

Let's say that you're putting the finishing touches on your next masterpiece of a game. It's time to add in the main menu screen, and you want it to be a magnificent sight to behold. You'd like the main menu buttons to fly in one by one and come in to land in the centre of the screen. But you also have your game loop to consider; your main loop invokes your do_menu function 60 times per second. On each call, the function has to update the positions of your button sprites and return so that the program can perform its rendering and other duties and complete the frame.

            1                2                   3    
      +-----------+    +-----------+       +-----------+ 
[  ] ---->        |    |   [  ]    |       |   [  ]    |
      |           |    |       <----- [  ] |   [  ]    |
      |           |    |           |       |   /|\     |
      +-----------+    +-----------+       +----|------+
         screen                                [  ]

The code to achieve this is going to have do something different each frame, depending on what state the animated sequence is in. A state machine for this, in pseudo-code, might look something like this:

state = 1

function do_menu {

    if state == 1 {
        move button 1's position
        if button 1 is in place
            state = 2
    }
    else if state == 2 {
        move button 2's position
        if button 2 is in place
            state = 3
    }
    else if state == 3 {
        move button 3's position
        if button 3 is in place
            state = 4
    }
    ...
}

The more complicated this scripted sequence gets, the more states we are going to have to declare. As I'm sure you can imagine, this can very quickly get ugly and difficult to maintain.

Instead, let's consider how this could be achieved using a generator instead:

generator menu {

    while button 1 not in place
        move button 1
        yield

    while button 2 not in place
        move button 2
        yield

    while button 3 not in place
        move button 3
        yield
}

This generator can be iterated every frame, in the same way that our do_menu function could be called. But the expressiveness of the generator syntax lets us declare the linear sequence of events in a more procedural way. The flow of events in the animation reads more naturally from top to bottom, the same way as any other program flow would be declared, without having to define lots of individually handled states. Each time we yield, we allow the game loop to render another frame.

I find this expressiveness pretty neat for games. In fact Fiona has created an entire 2D library for Python called Myrmidon which uses a generator for each game object. This allows the entire lifecycle of each sprite to be laid out in this procedural way. It takes inspiration from an old game-making tool we used to use called Fenix/DIV. Here's an example of a Myrmidon game object that fades in, pauses, follows the player for a while, then fades out:

class Ghost(MyrmidonProcess):

    def execute(self):

        # appear
        for i in range(60):
            self.alpha = i/60.0
            yield

        # pause
        for i in range(30):
            yield

        # follow the player
        for i in range(500):
            self.rotation = MyrmidonGame.angle_between(
                    (self.x,self.y), (player.x,player.y))
            self.move_forward(2.0)
            yield

        # disappear
        for i in range(60):
            self.alpha = 1.0-i/60.0
            yield

Generators can be nested, too. That is, you can have a generator yield while it is iterating another generator. This makes them really useful for games which rely heavily on scripted story-based content, such as RPGs or adventure games. Rather than relying on a separate scripting language such as Lua or some kind of home-grown scripting DSL, we can take advantage of Python's expressiveness and write scripts in the language itself! Consider this scripted sequence written as a generator:

def love_scene():

    for i in fade_in(): yield

    for i in character_walk_to(alice,(12,16)): yield

    for i in character_say(alice, "Hey there Bob"): yield

    for i in character_turn(bob, west): yield

    for i in character_say(bob, "Oh hi Alice"): yield

    for i in character_walk_to(bob,(12,17)): yield

    for i in character_say(alice, "I love you Bob!"): yield

    for i in character_say(bob, "I love you too, Alice!"): yield

    for i in fade_out(): yield

The commands fade_in, character_walk_to, character_say and so on are themselves generators which each perform an action over a number of game cycles. By looping over them and yielding on each iteration, we can have the main script wait until the command has finished. There is in fact a PEP suggesting a yield from syntax for Python which would eliminate some of the boilerplate here, but at the time of writing it hasn't quite made it into the language yet.

Performance Considerations

Naturally there is some overhead associated with using a generator over a regular function. Based on some quick benchmarks, it would seem that iterating a generator executes more or less as quickly as a calling the equivalent function. There is overhead involved in constructing the generator, though; you're looking at around 5x the time it takes to construct a do-nothing class instance. That said, if you've already chosen to use Python to write games then it might be fair to assume that performance isn't your highest priority anyway. Particularly if you're prototyping, you'll probably be aiming to make things as easy as possible for yourself - in which case, go for the generators!

Conclusion

Generators are an interesting tool which allow linear sequences of events to be declared in a natural, procedural way. In many cases they eliminate the need for complex state machines, and are especially useful for games. Next time you're stringing together a state machine just to make your main menu look nicer, or inventing a scripting language just to add cutscenes to your game, consider using this powerful language feature instead.