Scripting languages allow rapid development of game behaviour without the pitfalls that await the unwary C++ programmer. Using an existing scripting language saves the time and cost of developing a custom language, and typically gives you a far more powerful language than you could create on your own.
Python is an excellent choice for a game scripting language because it is powerful, easily embedded, can seamlessly be extended with C/C++ code, has most of the advanced features that make scripting languages worthwhile, and can also be used for automating production. Additionally, the books, development tools and libraries available for Python provide great opportunities for benefiting from the work of others.
describes our experiences at Humongous Entertainment with integrating
Python into our new game engine. It explains why we chose Python, the
benefits we've seen, the problems we've encountered, and how we solved
Why use a scripting language?
C++ is a powerful language and an enormous improvement over C. However it is not the best choice for all tasks. The emphasis in C++ is run-time performance [Stroustrup94] and no feature will make it into the language if it makes programs run slower. Thus, C++ programmers are burdened with many restrictions and inconveniences.
A few of the restrictions - that C++ programmers are so used to they usually don't notice -- include:
C++ is static, scripting languages are dynamic. Grossly oversimplified this means that C++ runs fast, but scripting languages let you code faster.
should only be used when you need to optimize for run-time performance.
On today's fast computers there are huge blocks of code where performance
is not an issue. If you develop these in C++ when a scripting language
would do then you are optimizing for the wrong thing.
What's wrong with SCUMM?
Humongous has used SCUMM (Script Creation Utility for Maniac Mansion) to create over 50 different games. SCUMM is a powerful adventure game creation language, but it has some limitations. SCUMM was written more than a decade ago and it is missing some of the features found in more modern languages.
continual patching and maintenance, SCUMM will never be as full featured
and robust as the many other languages available.
We explored the idea of creating a new, more modern proprietary language, but wisely discarded the idea. We are in the business of making games, not languages.
After spending millions of dollars over the years maintaining a suite of proprietary tools we, really wanted to go with an existing scripting language rather than creating one. Existing languages let us get started faster, have lower maintenance costs, are generally better than a language we would create, and tend to get better over the years, even if we don't work on them.
Once we decided that we wanted to use an existing scripting language we had to choose one. We needed something clean that would support object oriented programming and could be embedded in our games, without technical or licensing problems.
We considered Lua [Lua01] and Python [Python02], both of which had been used in several games.
Lua is smaller and probably easier to embed in an application, and has some nice language constructs. However, at the time we were choosing a language the documentation was a bit sketchy. This is probably because Lua is a newer language than Python.
Python has more extension modules than Lua, more books written about it, and stackless Python [Tismer01], which was a promising way of creating micro-threads for object AI. We ended up not using the stackless version of Python, but we did start using Python for writing automated build scripts and this gave us momentum. We knew the syntax, we liked it, and so we chose Python.
have been improved since we made our decision - Lua has become stackless
and Python has acquired generators, which allow some similar functionality.
Either language is a safe choice.
Who is using Python in games
Python has been used in a number of games, including
with numerous other sightings that are difficult to verify, including at least one PS2 game.
Python is also used in at least two game engines:
A build script example
As an example of Python code, here is a simple build script that recursively builds all VC++ workspaces. Written in a fairly verbose fashion it still takes just a dozen lines of code:
for entry in nameList:
workspaceName = os.path.join(dirname, entry)
resultFile = os.popen("msdev %s /make all" % workspaceName)
resultLines = resultFile.readlines()
for line in resultLines:
if __name__ == '__main__':
os.path.walk(os.curdir, BuildAllWalker, None)
With a couple of dozen more lines of code, this script [Dawson02] parses the output and e-mails a summary report to everyone on the team. Unlike some scripting languages, the code is quite readable. Using the same language for build scripts and game scripting will save a lot of learning time.
This build script example shows what is probably the most distressing aspect of Python to new users. Flow control is indicated entirely by indenting. There are no begin/end statements and no braces.
It took me about five minutes to adjust to this idea and I have since found that it is very effective. I've been in more than one heated argument about where the braces in C/C++ should go and I'm sure that Python programmers are 10% more productive just because of the time they don't spend arguing about K&R indenting style versus others. When your code blocks are defined by indenting there is no longer any possibility of the indenting not matching the compilers view of the code's structure.
time when indenting for flow control causes problems is when tabs and
spaces are mixed. Since most programmers use three or four space tabs
and the Python compiler internally uses eight space tabs, mixing tabs
and spaces causes confusing syntax errors. If you standardize on either
spaces or tabs and use an IDE that warns you when you are mixing them
then you will have no problems.
Game script example
The following is a sample of some Python code from our first Python/C++ game. You can see from this small sample that the Python code is running the main loop, calling out to modules that may be written in either language:
# Update the input
# Tick the menu code
# Tick the scene code
game boots up in Python, and only calls out to C++ as needed.
How does it work?
Python is based on modules. When one source file wants to use functions defined in another source file it imports that file. For instance, if gameai.py has a function called UpdateAI then another Python source file can go:
The wonderful thing about this from a game programmer's perspective is that if UpdateAI() runs too slowly it can be rewritten in C++. To do this, the functions and types defined in gameai.py are written in C++ and registered with Python with the same module name. The Python code can continue to import and use gameai without any changes.
modules make it easy to prototype your entire game in Python and then
recode as needed in C++.
Writing the glue code to make C++ code visible to Python is tedious if you try to do it by hand. A system for generating glue code is essential.
Swig, Boost, CXX and others [Abrahams01] are systems to help generate code to glue together Python and C++. Another option is Fubi [Bilas01] which is a generic system of making C++ functions and classes available to a scripting language.
Most of these glue code systems work by parsing a C++ header file. Thus they are restricted to what a C++ header can expose, and some of them did not support having Python classes derive from C++ classes. They have been improved substantially since then and are worth taking a look at.
We decided to create a custom solution that generates glue code based on an IDL description of the class or function to be exported. Our code name for this is Yaga, which is a recursive acronym that means Yaga is A Game Architecture.
A typical snippet of Yaga IDL code looks like this:
which then generates the following glue code, and a few hundred lines more:
static int YAGAPYCALL
if (!PyArg_ParseTuple(args, "|llll",
This system makes it very easy to export classes and functions, derive Python classes from C++ classes, map C++ arrays and vectors to Python sequences, and much more.