Lua and C++: separation of duties
Asked Answered
P

3

12

Please help to classify ways of organizing C++/Lua game code and to separate their duties. What are the most convenient ways, which one do you use?

For example, Lua can be used for initializing C++ objects only or at every game loop iteration. It can be used for game logic only or for graphics, too. Some game engines provide full control to all subsytems from scripts! I really do not like this approach (no separation at all).

Is it a good idea to implement all game objects (npc, locations) as Lua tables without C++ objects? Or it is better to mirror them (Lua tables to control C++ objects)? Or something else?

Thank you.

Edit. My classification: Lua and C++: separation of duties.

Topic's continuation: Lua, game state and game loop

Predestinate answered 20/4, 2010 at 11:1 Comment(0)
C
4

My approach has been to limit what is exposed to Lua as much as possible. I have never found a need for a "main" or other such function which is called every time the scene is rendered (or more). Some Lua engines (like LOVE) do this however. I prefer to define objects with optional callback functions for common events that you may want the object to respond to such as a collision, mouse click, entering or leaving the game world, etc..

The end result is very declarative, almost a config file for objects. I have a function for creating classes or types of objects and another for creating objects based on these types. The objects then have a collection of methods which can be called when responding to various events. All of these Lua methods map to C/C++ methods which in turn modify the object's private properties. Here is an example of a bucket object which can capture ball objects:

define {
    name='ball';
    texture=png('images/orb.png');
    model='active';
    shape='circle';
    radius=16;
    mass=1.0; 
    elastic=.7;
    friction=.4; 
}

define {
    name='bucket';
    model='active';
    mass=1;
    shape='rect';
    width=60;
    height=52;
    texture=png('images/bucket.png');
    elastic=.5;
    friction=.4; 
    oncontact = function(self, data)
        if data.subject:type() == 'ball' then
            local a = data.subject:angleTo(self:getxy())
            if a < 130 and a > 50 then
                --update score etc..
            end
        end
    end;
}

I would not take this as the "one true way" to implement your scripting API. One of the beauties of Lua is that it supports many different styles of API. This is just what I have found works well for the games that I make - 2D physics based games.

Croix answered 21/4, 2010 at 15:47 Comment(2)
Thanks, I like your answer very much. So, you use Lua mostly as config file and callback function repository. And every game object is implemented as C++ object and Lua object. Is that correct? How do you synchronize their states? How do you save game - generate a new Lua config file?Predestinate
The Lua objects are really just interfaces which map to objects in c via a single lightuserdata field which resolves what "self" is. As far as saving I generally only save the level a player is at but I could implement a function which recreates the entire game state entirely in Lua by simply getting the state of each object and then writing out a script to set them all- perhaps not very optimized and I would probably look at serialization in this case.Croix
P
2

I propose this classification:

  1. Extreme variant: Lua scripts control everything (game logic, graphics, AI etc.). Even more: script works as a host-program, owns game loop. Some engines do such thing. Ba-ad thing: no separation of duties at all and no script safety.

  2. Lua scripts maintain game state and process game logic. Probably scripts are called at each game loop iteration.

  3. Lua scripts are rarely used for initializations, configurations, callbacks. A host program provides (binds) a very minimalistic interface for the scripts. So scripts are built from such well-designed and provided blocks.

Predestinate answered 21/4, 2010 at 18:50 Comment(0)
I
1

Start small. Allow access to game entities so that you can perform map/level-specific scripting. Behaviour that is consistent across maps/levels probably doesn't need scripting.

Also, only give access to the public interface of your objects.

Invercargill answered 21/4, 2010 at 15:7 Comment(2)
Thank you for the first answer. Say, is it a good idea to implement all game objects (npc, locations) as Lua tables without C++ objects? Or it is better to mirror them? Or something else?Predestinate
I would implement the game objects in C++, but instantiate them with Lua. During the instatiation you can set properties to what you would like them to be for the specific situation. You can also set callbacks to your Lua-scripts, for example: if door47 is opened then call Lua-function xyz. I recommend that you use Lua for the "story" of the game, C++ for the mechanics.Invercargill

© 2022 - 2024 — McMap. All rights reserved.