Thread: Script in games

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218

    Script in games

    As most of you probably know already games widely uses scripts to add different kind of things to their game, be it a quest, or a pattern of movement, and so on. Me and Bubba have worked out a system that is designed to be used together with the Zelda-game Bubba has talked alot about. But in order to share our ideas with you people i decided to write this little post to maybe inspire somebody to try something like this on your own .

    The focus on this type of script is for it to run as fast as possible, with as little parsing as possible at runtime. In order to do this you must basicly convert a text-file (or binary file) into Structures of some sort. We also wanted the script to behave as a state-machine. This means that you test for 1 state, and if that state is true, you do something. This can interact nicely with the message-system we have developed (might post something on this later).

    The syntax.
    The syntax is very important when you write a script and can be everything from an assembly-like syntax to a syntax that looks very similar to C++. I chose a syntax that would be easy to parse, but at the same time is somewhat familiar to the people who have programmed in C, C++ and the likes. Basicly everything is a function-call. There is no such thing like this:
    variable = 10
    instead it goes like this in my script system:
    aSetVar(variable, 10)
    Notice the a infront of the actual functionname. This a shortence for 'action', which is well, something will be done here. I chose to have an a infront because it allows for easy parsing and detection of a functioncall. Consider now that some functions may start with an 'u', this denotes user-defined functions. User defined functions are just functions that group up several normal a-calls to 1 u-call. This is for easier development.

    Messages.
    The script and the whole Zelda-engine is about messages (think windows-messages), with a fling of MFC-styles in it. Basicly we have mapped a message-id to a single function inside a class. This script sends these messages to either a Message-pump or its own message-handler, depending on what type of messages it is. The Message-pump then sends the message to its correct destination. The scripts internal message-handler (think Win32 MsgProc) deals with setting variables, and things like that.

    Functions.
    As said above the functions is what makes this script. It is all about functions and if-calls. But problem came up here, we needed a way to externally map each function to a message-id. We also needed to know wether the arguments to a function was a normal plain number or a variable. The solution to this was a definition-file. A definition-file contains the names of the functions together with what type of arguments it expects. This definiton-file is very easy to expand and is basicly what makes this script so versatile.

    Variables.
    Perhaps the single hardest thing to get right. Our system only handles DWORD or unsigned int types, and that is partly because if one wants float, string unsigned int, signed int and so on, it would partially be very hard to implement a system that handles that without using alot of runtime checking. And runtime checking is bad because that takes time, which is better spent on frames or rendering (remember, speed is everything here). Another reason is that we dont want the script to directly access and control what is done. Say we want an object to move through a list of waypoints, we then send the ID of that list of waypoints instead of programming the actual waypoints into the script. What I have found is worth thinking about when it comes to variables and script is this: think carefully, does one really have to have 5 different type of variables or would 1 type suffice?

    Loading.
    Almost all parsing is done at loadtime, the only parsing that gets done at runtime is for the aSetVar function, this is because this function can take both a number, variable and the returnvalue from another function as its second parameter. Therefore a check to see what type the second parameter is has to be done. For everything else It gets converted into a structure that looks like this:
    Code:
    struct Action
    {
    	std::vector<std::vector<Action> > ifConditional;
    	std::vector<Action> ifActions;
    	bool trueCondition;
    	std::vector<std::string> arguments;
    	DWORD msgID;
    	pFuncParam pParams;
    	std::string actionName;
    };
    Where the most relevant pieces are msgID and pParams. You see, in order to cut down time at runtime, I store pointers to all parameters that is associated with 1 functioncall. The maximum number of parameters at the moment are 3, but those can easily be increased.

    Running.
    To run the script we basicly iterate a vector that contains objects of type Action. We check if there is an if-conditional in place, if there is we check that if-conditional. If that is true we run all the ifActions inside that if-conditional. Otherwise we simply pump down to the next action in the main actionvector. So at runtime it is all about iterating, and almost nothing about parsing (I say almost because we have to parse the aSetVar function). We iterate through this vector once every frame, so therefore it is cruicial for the designer of the scripts to write them right.

    Personal experience from making this script.
    First id like to say that this script is in no way complete. I have yet to add support for a parser that parses pure binary files will be added aswell. The intention of this script is to have a fast and stable way to get text-files or the likes to influence the game. Would I have done something different? Sure, first I would not have skipped cruicial things like if-elseif-else but implemented them from the beginning. But I must say that it has been fun to develop this, and seeing how powerful this can be in the right hands. It has also been an enormous satisfaction to see this come to live, even though its only at a console level at the moment.

    What to think of.
    Think of the design, and think of its purpose. Does it have to be as fast as possible? Then you sure must think of a way to get that text-file into pure C-structures. And dont be afraid of making a very simple script the first time. Writing a parser isnt easy but not much brings more joy than seeing how you write something in a textfile and then just run a program and the result shows there.

    This was just a little description of the script-system me and Bubba have worked on, and I decided to post it here to inspire and help people who might think of doing something similar.
    Last edited by Shakti; 09-27-2006 at 12:30 AM.
    STL Util a small headers-only library with various utility functions. Mainly for fun but feedback is welcome.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. In a game Engine...
    By Shamino in forum Game Programming
    Replies: 28
    Last Post: 02-19-2006, 11:30 AM
  2. Passing arguments to script.....
    By suwie in forum C Programming
    Replies: 5
    Last Post: 09-25-2004, 11:10 PM
  3. Game structure, any thoughts?
    By Vorok in forum Game Programming
    Replies: 2
    Last Post: 06-07-2003, 01:47 PM
  4. Video Games Industry. 5 years left.
    By Cheeze-It in forum A Brief History of Cprogramming.com
    Replies: 26
    Last Post: 12-10-2002, 10:52 PM