| |
|
|
||||
![]() |
||||||
| |
|
|||||
|
GDC 2002: Game Scripting in Python 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. This session
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
them. 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. Thus, C++
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. Despite
continual patching and maintenance, SCUMM will never be as full featured
and robust as the many other languages available. 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. Both languages
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.
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: import os def BuildAllWalker(unused,
dirname, nameList): if __name__ == '__main__': 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. The one
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. try: except: Thus, our
game boots up in Python, and only calls out to C++ as needed. import gameai 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. Thus, Python
modules make it easy to prototype your entire game in Python and then
recode as needed in C++. 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: module yagagraphics which then generates the following glue code, and a few hundred lines more: static int YAGAPYCALL
Rect_init( return
0; 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.
|
||||||||||||||
|
|