Live Coding Games in Python

Erik on Aug 2nd 2006

Reddit recently lead me to Logan Koester’s blog post about live coding with Python, and I found it fascinating. Live Coding is the practice of editing code for a running program in an environment that loads in the changes as they are made. Apparently people do this as a performance art, writing programs on the fly to play music. There is even a Wikipedia article on live coding.

I tried out the examples on Logan’s page, generated some weird drum loops, and had some fun with it all. The experience was a reminder that I want to learn how to make music. But it also opened my eyes to what seems like a new approach to programming.

After 30 seconds of looking I have failed to find a good reference on this, but I have read that a major factor in programmer productivity is the turnaround time between editing code and testing the results. If you are working on big project with a slow build process making changes takes a long time. Because changing too many things at once is a bad idea, you have to spend a lot of time waiting to test your code. If you are working on a small project in a scripting language, then it’s just save and run with little waiting to see the results of your edits.

What if we take this a step further? Are there productivity gains to be found through live coding, where you see the results of your changes when you save the code? I’ve decided it’s a neat idea, and I want to explore it. Since most of my programming focuses on game development, I tried out live coding with PyGame. What can I say? Recompiling your game’s codebase every frame strikes me as a wonderful way to trade cpu cycles for increased programmer productivity.

The first step is building the controlling script that does the live coding magic. I started with Logan’s example, but I wanted to do a couple of things differently. The first is I wanted to see a message and a backtrace for both syntax and runtime errors. The second is that I wanted the host and the client to be largely independent. Here is my controller.

controller.py:

import traceback
import StringIO

from time import sleep

done = False
imported = False
loadBroken = False
runBroken = False

def genTraceback(ErrString):
    """ Takes an error message as an arguemnt.
        Generates a traceback of the most recent
        exception, and prints it with the error
        message.  Sleeps for 2 seconds before
        returning.
    """
    fp = StringIO.StringIO()
    traceback.print_exc(file=fp)
    message = fp.getvalue()

    print ErrString,"\n", message
    print "\nFix livegame.py to continue.\n"

    sleep(2) 

# loop until we sucessfully import livegame.py
while not imported:
    try:
        import livegame
    except:
        if not loadBroken:
            genTraceback("Failed to import livegame.py.")
            # set a flag so that the traceback is only printed
            # once
            loadBroken = True
    else:
        imported = True

# loop until livegame.play() returns True
while not done:

    # attempt to reload the code
    try:
        reload (livegame)
    except:
        # if the reload fails, print the traceback once.
        if not loadBroken:
            genTraceback("livegame.py is broken.")
            loadBroken = True

    else:
        loadBroken = False

        # if the reload is succesful, try to run livegame.play()
        try:
            done = livegame.play()
        except:
            if not runBroken:
                genTraceback("play() in livegame.py is broken.")
                runBroken = True

        else:
            runBroken = False

Sorry for the \" silliness in the above code. It seems to be a wordpress bug. Anyway, what the above code does is load livegame.py and then reload it in a loop, calling livegame’s play function every time. Thanks to the traceback and StringIO modules, it outputs both syntax and runtime error tracebacks to the console seamlessly.

Here is a very basic livegame.py:

fps = 10
width = 640
height = 480

# check to see if the pygame module is in the namespace
try:
    pygame
except NameError:
    # pygame doesn't exsist, so import it.
    # this only happens once.
    import pygame
    from pygame.locals import *

    # initialize the pygame display
    pygame.init()
    pygame.display.set_mode((width,height),0,32)
    display = pygame.display.get_surface()

    # initialize the pygame clock
    clk = pygame.time.Clock()

def play():
    """ Main game logic, called once per frame."""

    # fill the display with black.  Clears the screen.
    pygame.draw.rect(display, (0,0,0,255),(0,0,width,height))

    # draw a shape.
    pygame.draw.ellipse(display, (0,40,200,255),(200,200,100,50))

    # update the display.
    pygame.display.flip()

    # check for events, and return true if we get an exit signal.
    events = pygame.event.get()
    for event in events:
        if event.type == QUIT or (event.type == KEYDOWN
                                    and event.key == K_ESCAPE):
            return True

    # try to maintain a set frame rate.
    clk.tick(fps)

    # No exit signal was recived, so return false.
    return False

The first time this code is run, it initializes PyGame and creates a window. Every time play is called, it clears the window, draws a blue ellipse, checks for events, and then sleeps long enough to try to maintain a set framerate. If you press the escape key livegame signals the controller script, and the controller exits. To see where things get interesting, change this line:


pygame.draw.ellipse(display, (0,0,255,255),(200,200,100,50))

to something like this:


pygame.draw.rect(display, (255,0,0,255),(200,200,200,100))

Save the change with the PyGame window open beside your text editor, and watch the small blue ellipse instantly turn into a larger red rectangle. A basic example, I admit. But it hints at very deep potential.

The next step is taking this live environment, and building a full game using it. I intend to give it a try, hopefully soon. It will take some cleverness to keep things both dynamic and running fast enough. I might have to set up some sort of caching system so that expensive operations, such as loading an image or level from disk, don’t happen every frame. I could perhaps bind a key so that the expensive stuff is only done on request, but I think the experiment will be most interesting if I keep that sort of thing to a minimum.

There are obvious improvements to the above code that could be made, but I wanted to keep things as simple as possible. Though I do want to add more features before I make an attempt at building something significant using the live environment. I hope to modify the controller so that it takes the name of its client as a command line argument. I would like it if the controller gave some sort of audible notification if the client code caused an exception and produced a new traceback. I will see if I can use Ipython’s handy syntax highlighting for the controller’s tracebacks. It would also be neat to modify the client code to use the python if name == '__main__' trick. Then the client could optionally run as an independent program without the controller. This would also allow changing settings such as the target frames per second based on the environment the code is running in.

If I haven’t stated it enough already this post: this approach opens up lots of interesting possibilities. The only downside is that some day I’m going to start writing flash games that run directly in the browser. When I do that, I’m really going to miss all this dynamic language magic that I’m learning to use with Python.

Edit: I’ve posted an update, Live Coding, Continued

Filed in Games, Programing | 9 responses so far

9 Responses to “Live Coding Games in Python”

  1. Logan Koester Aug 3rd 2006 at 06:53 am 1

    Wow, what a great idea. I really like where this is going. Wouldn’t it be interesting to add network support, and have a dungeon master creating the environment in realtime while players are online? Just a thought.

    As you said, performance will be a real issue for anything that complex. Do you have any ideas about caching? What about threading?

    I’m pretty new to python myself.

  2. Erik Aug 3rd 2006 at 09:50 am 2

    I’m sure that this could be made to work in a network environment. The controller might have to take care maintaining the connections, but it could be done. Live coding an RPG is a neat idea. I imagine that there are MUDs out there that allow you to do some of this sort of thing.

    In terms of caching, my thought was to define an initialization function, that defines starting states for objects, and performs actions like loading images. I would call the init function with the PyGame initialization, so that it only happens once. Then I would have the ‘r’ key trigger the init function. So if you made some changes in the init, they wouldn’t take effect until you hit ‘r’.

    I’m not really sure about threading and live coding. One thing I do want to try is having a python shell running in a thread alongside the game, so that you can modify the live game’s state by typing commands into the shell.

  3. Logan Koester Aug 3rd 2006 at 11:53 am 3

    I’m not entirely sure I understand your caching solution. Could you maybe provide some more detail, or better yet an example implementation?

    If I’m lucky I’ll have the time to play around with this a bit over the weekend, see if we can’t get a few of these features implemented, eh?

    Cheers

  4. jas mhz Aug 3rd 2006 at 02:36 pm 4

    This is the ultimate force – live coding networked enviroments – oh I think the network needs a new iteration number or protocol now – wow.
    Multicoloured Code like a vital source flowed and spewed from an ever increasing number of finger-tips. An evermore inelluctable knowledge onrush entertwined in the collective intuition emerges somethink new, unexpectedl; a paradigm shift, number 11 on the dial.
    Many thanks for your beautiful idea – I love it.

  5. Steve Taylor Aug 3rd 2006 at 03:50 pm 5

    I don’t want to get into language-war territory, so please forgive – but Smalltalk might interest you if you want to play with ‘live coding’.

    It’s (from some people) common practice to code inside the debugger, creating classes and methods as they are called, halting, changing and re-running live objects,defining variables on the fly, etc. I don’t think it’s the height of good design to do so, but it can make debugging and exploratory coding quite a hoot.

  6. Erik Aug 3rd 2006 at 04:42 pm 6

    @Logan: I’m working on a bit of code that displays an image without loading it every frame, and does some simple animation. I’ll do a follow up blog entry once I get it to the point that I’m happy with it.

    @Steve: Yes, Smalltalk does interest me a lot. It and Lisp pioneered dynamic language features long ago. But it’s fun to push the limits and see what Python can do. Plus there are reasons why I find Python useful for game development, even if it isn’t the ideal language for live coding.

    I know that Smalltalk and Lisp could do this sort of thing years ago, but I find it odd that I’ve never heard of people developing in an environment where their code is automatically run and tested as they save it. Perhaps I’ve just never read the correct stuff.

  7. Logan Koester Aug 3rd 2006 at 07:41 pm 7

    Looking forward to it, Erik

  8. Nicola Larosa Sep 2nd 2006 at 10:02 am 8

    > The only downside is that some day I’m going to start writing flash games
    > that run directly in the browser. When I do that, I’m really going to miss all this
    > dynamic language magic that I’m learning to use with Python.

    Not necessarily. Work is going on to have Python in Firefox, besides Javascript:

    Breaking the grip JS has on the DOM
    http://wiki.mozilla.org/Breaking_the_grip_JS_has_on_the_DOM

    “We want to change the grip JS [Javascript] has on the DOM and on XUL. [...] The initial work on this, including a Python implementation is largely complete.”

    This goes nicely hand in hand with the work Brett Cannon is recently doing on a new restricted environment for Python:

    [Python-Dev] doc for new restricted execution design for Python
    http://mail.python.org/pipermail/python-dev/2006-June/066344.html

  9. Stan Shepherd Sep 10th 2006 at 10:20 pm 9

    Hi Erik, I am not a functional programmer, but I like the approach. I first saw it here http://www.paulgraham.com/avg.html

    And more technically here:http://lib.store.yahoo.net/lib/paulgraham/bbnexcerpts.txt

    I thought then that it would be a great way to develop games. Have you progressed this much? Any show-stooping issues?

    Stan

Comments RSS

Leave a Reply

Powered by WP Hashcash