Archive for the ‘pyglet’ Tag
Recently I started reading about livecoding. I was aware of it in the context of music performance, but in regard to games it might be more accurate to call it code reloading or simply interactive programming, but of course ‘livecoding’ is more catchy. Regardless of what you call it, it’s a lot of fun, and if you like programming as an iterative process as I do, it’s just fantastic.
A few years ago there were a few articles about livecoding and Python, which you can track down through this post by Richard Tew. He’s the author of the livecoding module which I’ve started to use with pyglet.
The basic idea is that you can modify a game’s code as the game is running; this isn’t any different than what you can do with many game development frameworks and some mud servers (mush softcode allows this, for example, and I believe LPMud has this as well), but the livecoding module lets you do it simply with your text editor of choice. Some IF language development environments like the Inform 7 IDE and TAD 3’s Workbench have a similar function with their skein and replay features, but livecoding is much more immediate and in the flow of the game itself.
The livecoding module achieves this by managing which files are to be tracked for changes, and then executing a file’s contents over again when you change it. As the programmer you need to structure your program so that you’re cognizant of what is in the global scope, as executing that code again will clash with the previous version (for example, you don’t want to re-execute a file that instantiates the pyglet window, unless you delete that window from the global scope). You also want to manage how instances of a class know about changes to their class; the module won’t automatically update old instances, but you can reassign the class to the instance to get the new changes (this at least is what I’m doing currently — I’m still learning how this works).
Here’s a simple example — get the livecoding module and put it in a new directory. Then create a code directory within that new directory. In my code directory I put two files, an initialization.py and a classes.py. Here’s initialization:
import pyglet window = pyglet.window.Window(width=640, height=480, visible=True, caption='livecoding')
Remember that the important thing is to separate things in the global scope from the things you’ll change, to avoid clashes with the running game when you change things. Now in classes.py I put this:
import pyglet class Hero(pyglet.sprite.Sprite): def __init__(self): pattern = pyglet.image.SolidColorImagePattern(color=(255, 255, 255, 255)) solid = pattern.create_image(200, 100) image = solid.get_texture() super(Hero, self).__init__(solid) def set_pos(self): self.x = 400 self.y = 200
In the main directory you’ll have a script to run the game, which I just called run.py.
import pyglet from livecoding import reloader cr = reloader.CodeReloader() cr.AddDirectory("server", "code") import server hero = server.Hero() @server.window.event def on_draw(): hero.__class__ = server.Hero hero.set_pos() server.window.clear() hero.draw() if __name__ == '__main__': pyglet.app.run()
The reloader keeps track of changes to any file in the code directory (of course, you can call the code directory anything you want). This replaces the normal Python import statement for those files. It’s similar in a way to pyglet’s method of managing data files.
You see that the game creates the hero object, and in this hackish example I reset the class of the hero on every frame. That’s to account for the possibility of changes to the Hero class (in classes.py). What you do then is execute run.py, and while the pyglet window is sitting there, change the set_pos method of Hero in classes.py. Then mouse over the pyglet window or alt-tab to it, and see the changes!
In a less trivial example you could move the class reset to an update function called on a pyglet timer. That then opens up, fairly transparently, making changes to the game process and data as you’re playing the game.
The only sticking point so far is managing the structure of the program to avoid any weird errors in the global scope. Also from reading some of those other posts I linked above it seems like I might run into more problems with things like animation as I go forward — but we’ll see what happens!