Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
69 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Contents
 Organizing Projects
 Creating Libraries
 Runtime Log Files
 Protecting
 Image Data

 Introduction
 to Scripting

 The String Table

 Printable version
 Discuss this article
 in the forums



The Series
 Beginning Windows
 Programming

 Using Resources
 in Win32 Programs

 Tracking Your
 Window/Using GDI

 Introduction
 to DirectX

 Palettes and Pixels
 in DirectDraw

 Bitmapped Graphics
 in DirectDraw

 Developing the
 Game Structure

 Basic Tile Engines
 Adding Characters
 Tips and Tricks

Introduction to Scripting

I've talked about scripting engines so much in this series and yet never got around to explaining how exactly it works. Plus I've gotten a lot of E-mails from people wanting to know this stuff, so I thought I'd give you a bit of an overview here. Obviously I can't come anywhere close to completely covering this since this is only a small part of a single article, but hopefully it will give you an idea for a framework you can build on.

To implement a scripting engine in your game, you'll need to do three things. First, you have to design the language. Second, you have to write a "compiler" that turns text scripts into some sort of code, so that users can't look at your scripts and know how to change them to do what they want. Third, you have to write the interpreter that loads and executes script files.

The first part isn't too difficult since you've already seen at least one programming language -- probably several -- so you have a good idea as to what you need in a scripting language. You need variables, decision statements, loops, the ability to read mathematical expressions, and functions. There are two ways to go as far as functions are concerned. You can build functions like MoveNPC into the scripting engine itself, or you can allow the scripting language to directly call functions which are in your game code. The first approach is easier, but not as flexible since you're adding functions to a scripting language that really only apply to one game. The latter approach is much better, because it allows you to use a general scripting engine in a variety of different programs. In addition to those, there are probably some general functions you want to add directly to the scripting engine that can be used from any program. Image loaders are a good example of that.

Once you've decided on what your language needs, and what the syntax is going to be, you're ready to write the compiler, which is easily the most difficult part of doing this. (The interpreter is actually quite straightforward.) What I do is to break all my script code down into fixed-length instructions, much like you would see in an assembly language. If statements and loops are replaced by branch instructions. Mathematical equations are broken down into single operations. For example, the equation x = (a + b) * (c + d) / (e - f) is broken into this:

add t0, a, b
add t1, c, d
mul t0, t0, t1
sub t1, e, f
div x, t0, t1

Those simple instructions are then turned into bytecode. That seems simple at first, since all you basically need to do is pick a number that corresponds to the opcode (add, for example, is an opcode), and replace the word by the number, right? But there are other concerns. In the bytecode, how do you tell whether the arguments are variables or constants? How do you represent floating-point numbers? And just how do you translate a mathematical formula into fixed-length instructions in the first place? Things like this are all questions that need to be addressed before you can have a working compiler, and they all take a bit more time to explain than I have in this article.

The final part of the scripting engine, the interpreter, is relatively easy to write. After all, your compiler has already done the hard work of breaking down complex instructions into small, simple components. The interpreter's job is to open a script file, find out how many lines it contains, and then create some storage space for the script, either with an array or a linked list, and load the script into memory. Once that's done, each line in the script consists of an opcode number and a series of arguments. An easy way to execute the line is to use the opcode number as an index into a function table. You then have one function for executing each opcode. The interpreter just needs to be set up to use that function table to call the appropriate function, and then you can go ahead and build the rest of the interpreter, the part that actually acts on the commands, one little piece at a time. Since most of those functions will be things like assignments, arithmetic, and branches, it's really no problem. Things like moving NPCs are of course not trivial, but those type of actions are part of your game program, not the scripting engine. The scripting engine is only responsible for calling them.

For allowing your scripts to call functions already in your game program, you could give your scripting engine a function called AddFunction(), or something similar, which simply takes a function pointer and adds it to its opcode list. You'd also have to make a small data file with these assignments for the interpreter to read, so it knows how to translate those functions, but that's not a big deal either. I know this overview was very general and doesn't give you any code towards actually getting something like this on its feet, but hopefully it gives you some ideas.





Next : The String Table