Gamasutra: The Art & Business of Making Gamesspacer
GDC 2002: Game Scripting in Python
View All     RSS
October 1, 2014
arrowPress Releases
October 1, 2014
PR Newswire
View All





If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 
GDC 2002: Game Scripting in Python

August 21, 2002 Article Start Page 1 of 3 Next
 

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.

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:

  • · Manual memory management: a huge amount of C++ programmer time is spent making sure that delete gets called at the appropriate time.
  • Link phase: C++ modules are linked together so that function addresses don't need to be resolved at run-time. This improves run-time performance, but slows down the edit/test cycle.
  • Lack of introspection: C++ code has no way of knowing what members are in a class. This makes writing code to load and save objects an enormous task that in some scripting languages is a single call to a built-in function.

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.

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.

Despite continual patching and maintenance, SCUMM will never be as full featured and robust as the many other languages available.

Why Python?


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.

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.

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:

  • Game Blender - http://www.blender.nl/gameBlenderDoc/python.html
  • PyGame - http://www.pygame.org/

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):
   for entry in nameList:
      if entry.endswith(".dsw"):
         workspaceName = os.path.join(dirname, entry)
         resultFile = os.popen("msdev %s /make all" % workspaceName)
         resultLines = resultFile.readlines()
         for line in resultLines:
            print line

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.

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.

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:

   try:
      # Update the input
      g_InputManager.DispatchInput()

      # Tick the menu code
      g_MenuManager.Tick()

      # Tick the scene code
      g_SceneManager.Tick()
      g_SceneManager.SetScene()

   except:
      import traceback
      traceback.print_exc(None,sys.stderr)
      g_Clock.Stop()
   #-endtry

Thus, our 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:

import gameai
gameai.UpdateAI()

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++.

Glue code


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:

module yagagraphics
{
   struct Rect
   {
      int32_t x;
      int32_t y;
      int32_t width;
      int32_t height;
   };

which then generates the following glue code, and a few hundred lines more:

static int YAGAPYCALL Rect_init(
            YagaPyStruct<Rect>* self,
            PyObject* args,
            PyObject* kwds)
{
      if (!PyArg_ParseTuple(args, "|llll",
                  &self->structData.x,
                  &self->structData.y,
                  &self->structData.width,
                  &self->structData.height))
      {
            return -1;
      }

      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.


Article Start Page 1 of 3 Next

Related Jobs

Infinity Ward / Activision
Infinity Ward / Activision — Woodland Hills, California, United States
[10.01.14]

Senior AI Engineer - Infinity Ward
Infinity Ward / Activision
Infinity Ward / Activision — Woodland Hills, California, United States
[10.01.14]

Gameplay Animation Engineer - Infinity Ward
Infinity Ward / Activision
Infinity Ward / Activision — Woodland Hills, California, United States
[10.01.14]

Lead Tools Engineer - Infinity Ward
Infinity Ward / Activision
Infinity Ward / Activision — woodland hills, California, United States
[10.01.14]

Build Engineer - Infinity Ward






Comments


Richard Ellicott
profile image
I to am biased towards python, hell i think i may consider it for this stuff, certainly more than any other trendy language like ruby or lua

however i am not sure these argument will really convince game devs, many of the advantages cited (easier to code, i mean things like braces are decided by C gods and the ide). I think when it comes down to it, you're using two languages rather than one. I think in reality, just getting stuff done, we tend to choose C.

so my pro python argument would be that i can run functions using the exec function, and also that i can add properties to objects dynamically to make a real world reflection from the object code to the inventory. HOWEVER, i have replicated these features now in C, so i use dictionary lists and instead of exec i just do a bit more code.

The result is that I am more secure, i remember hacking the eve client all to well :)


none
 
Comment: