How do I build games with scripted actors?

Ricardo Buring
  • How do I build games with scripted actors? Ricardo Buring

    The idea

    I have an idea for a game. A few games, actually, that can built on top of the same general design.

    There is a game world that the player and the other actors exist in. The player can get information from the world about his surroundings. The player can also interact with the world, picking up an object for example. Now, I would like the same thing to be possible for other, scripted actors. They are the player's competition. Instead of navigating the world and performing actions based on human input, a script should decide what they do.

    An example

    I want to do this using a 2d world eventually, so I might as well give the example I want to build:

    There is a 2d world with objects of various sizes and shapes. Every actor has their own field of view. They get information from the world about the objects in their field of view. For the player, this information is displayed on the screen of the user. The player navigates the world by user input.

    Scripted actors navigate the world in a scripted way. They walk in a general direction, they follow a wall or things like that. Their scripts should be able to get the information about the objects in their field of view and act on it. If an other actor is detected in their field of view, they should walk in that direction for example.

    All of this should happen in pretty much real-time.

    The information gotten from the world (showed to the player, and given to the scripted actors) in this case would be something like a collection of "what", "where", and "in what orientation".

    The question

    My question is: how I can program this effectively and efficiently?

    I am thinking to build this with C and Lua. C++ is also an option. I would store the game state and display the graphics using C. The part that I don't know how to handle is the interaction between C and Lua. Not programming-wise, but design-wise. The interaction between the world and the scripted actors.

    Should C provide the Lua actors with information, and then have the Lua actors call C functions that change their direction, move a step forward, etc? Will this work in real-time?

    I realize that this question is broad, but I think it's not unreasonable. There are obviously ways to do this and I would like to know some.

  • I would recommend to use C++ and polymorphism (one of basic principles of OOP).

    You can create a general Character class. It contains character's location, position in the world, inventory and other data, also virtual functions for updating and rendering character. Than you can subclass it with NPCharacter and PlayerCharacter.

    Method PlayerCharacter::update() listens to user input events and updates Character's state accordingly.

    Method NPCCharacter::update() implements some AI logics and controls NPC in any way you want.

    You can create LuaCharacter also. LuaCharacter::update() simply calls Lua script that does the same thing as NPCCharacter, but from the script. Some games really call Lua script every frame. If you are concerned about performance, it is better to minimize Lua calls, you can use Lua to implement callbacks and listeners to user input or other events only (no need to call these scripts every frame).

    foreach (characters as character)
       // we do not know what type of character it is - Player, AI, LuaScripted etc.
       // they all are updated in the same manner
       character.update(); 
    

    The same can be done using composition and component-based approach, too. Just add different components to your game objects. For example, AICharacterCleverComponent, AICharacterDumbComponent, LuaScriptedAIComponent, PlayerInputControlComponent etc.

  • I'd recommend not writing long scripts for actors, and instead just having each script be an instant 'reaction' script - ie. it runs and terminates quickly and decides a state for the actor to be in. So, I'd implement a few event handling functions in script, to be called as a result of significant in-game events, and an update script which is called once a frame or something. Pass in a small amount of context about the event in question, and the script should be able to call back into C++ functions to query the environment, set new objectives, etc. For the most part the important changes to behaviour and state should occur on the C++ side: the scripts should be limited to querying the current environment and quickly making a decision, passing that back to the engine.

    So for example, you don't continually call a script which then calls a C++ function to say "take a step forward", you call one saying "move me to X,Y" and then the normal C++ update loop will do that without reference to script for the next few seconds. When you arrive, you might call a script (eg. 'on_arrival') where the NPC can choose its next goal.

    I don't recommend trying to run actors via long-running scripts with lots of loops, conditionals, and storing state within the script, because this quickly becomes a concurrent system, and concurrent systems are REALLY HARD. If you use native threads to handle each character, you're going to hit multithreading bugs very, very quickly, unless you fully understand the implications of such a design (which sadly can't be explained in a single StackExchange post). If you decide to use some sort of user threads (eg. Stackless Python tasklets, Lua coroutines, etc) then you still need to understand the implications of cooperative multitasking - eg. being able to yield up control to other actors (ie. why while (1) { do_nothing(); } is not going to work for a sentry), and also to appreciate that even if your game is 'thread safe' the logic is not necessarily 'coroutine-safe' - a variable in one coroutine can easily become invalidated by another.

    eg:

    function duel():
        self.aim_at_foe()
        self.shoot_foe_dead()
        self.celebrate_victory()
    
    a = new Sheriff()
    b = new Outlaw()
    
    run_both_at_same_time(a.duel(), b.duel())
    

    What happens when the loser (whoever it is) tries to execute 'self.celebrate_victory()' and your system discovers that 'self' now refers to a dead actor? Or if it's reference counted, what if it allows a dead actor to celebrate his victory?

    Of course, some people are used to this sort of problem and know what they're doing; anybody in that category can ignore much of the above. :)

Tags
game-design c++ c lua
Related questions and answers
  • ; //this method is unique to the class player void generate_mesh(); } Now in the game engine I want to have a general object list where I can check for example for collision, move objects, and so on, but I want also that the game engine will take the user commands to control the player... Is this a good Idea? class GameEngine{ private: std::vector<GlObject*> objects; //an array... the polygons to the rendering engine I designed my objects like this: class GlObject{ private: idEnum ObjId; //other identifiers public: void move_obj(); //the movements are the same

  • language, in my case Lua. On the other hand I want to use a component based design for my entities, and here starts my questions: 1) Should I define my componentes in C++? If I do this in C++ won't I...) Where should I place the messaging system for my game engine? Lua? C++? I'm tempted to just have C++ object to behave as servers, offering services to lua business logic. Things like physics system... instantiate them. All this, is what I can think of now. I know my editor can still be using game objects even if it is external, but the game am I into is for iphone using cocos2d and the editor

  • question about it is, is this a worthwhile approach at all? If it's a bad design I want to know now before I invest too much more time making all the screens I'm going to need. How do you build up... sort of designs other people used to overcome them, or would use. For a little background, I started working on it in my free time last summer. I was initially making the game in C#, but about 3 months... areas of concern I have and wanted to get some opinions on the proper way others have solved them or would solve them. 1. Cyclical Dependencies When I was doing the game in C#, I didn't really have

  • GameSubsystems) can implement registerComponent(Component*). pro. Components and GameSubystems know nothing about each other. con. In C++ it would look like ugly and slow typeid-switch... a decision which Components to register (and how to organize them). For example, GameSubsystemRender can register Renderable Components. pro. Components know nothing about how they are used. Low coupling. A. We can add new GameSubsystem. For example, let's add GameSubsystemTitles that registers all ComponentTitle and guarantees that every title is unique and provides interface to quering objects

  • component associated with it). No problem until this point. For this function I want to use a scientifically tested, accurate N-body simulation algorithm (like this). It's my field so I already know how to do that. The challenge is how to make the game activate the function efficiently. This is what I've thought of so far: The algorithm can calculate a lot of time steps in a short time, so I could... double-buffering. The question is: who should be responsible for activating the spacecraft's algorithm? Should I do that directly in the game loop, or perhaps create a "timer object" that keeps track

  • with different types of objects in the same scene. I was also thinking about making a MeshNode class and then make a Mesh object that contains them, but then I have some conflict on where to store some data... know if my speculations are ok, as I don't have much experience with 3d animations yet. I want to make a well decision as any option I choose would require a lot of work to get it to render and I don't want to find out in the end that I have to rewrite everything again, as a lot of other objects will be working with these data. Sorry if it's a too subjective matter, but I need some insight. I'm

  • trying to have a 3d field of view routine for a 2d roguelike. The roguelike does have a 3d space, and I want to determine what the player can see, even if what the player can see can't logically be displayed. Let me worry about how to handle that problem. I would be grateful for some advice in how to approach this problem. Perhaps this is utterly crazy, and I should just make a 2d roguelike... Update...I've been thinking about adding 3d support in my roguelike. It would still be top-down like other roguelikes, yet it would have layers, such that things like platforms, tunnels, and bridges, etc

  • I want to make a simple game where I have some characters fighting on a plane (level). I find the trickiest part as figuring out who should do what here. I want my terrain to have friction (so you could play on ice). I also want fairly customizable characters. At first I was thinking of a mediator pattern where the game gathers information about the current player state and modifies them based on that, but I do not think this offers enough flexibility. I was thinking more along the lines of each player / character does have some logic. The Input from the game gives it the command

  • Sorry for the ackward title, but i don't know what to call it exactly. I'm looking for code or libraries that allow easy creation of commonly used user input devices, and code/libs that make gaming controls easy to set up (i'm using SFML and Box2D at the moment) I don't want to re-invent things like buttons, arrows being placed wherever the mouse is located, and more game specific items... input to press buttons or drag objects in games has "Focuses" (like a textbox being able to gain focus and be typed in) Is compatable with SFML/Box2D and code for common game mechanics/controls

Data information