Jump to content

  • Log In with Google      Sign In   
  • Create Account

Lua integration into a game


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 acidleaf   Members   -  Reputation: 158

Like
0Likes
Like

Posted 14 September 2012 - 12:15 AM

I'm programming a game in C++, and I've decided to integrate Lua into it to separate several parts of the game. Currently my ideas of implementing it is to create a ScriptManager singleton class to handle all scripts in the game. This singleton will maintain a single Lua state which will be shared across every game object that are exposed to Lua. Then any calls to scripts will refer to this ScriptManager class and call something like ScriptManager::DoScript("script.lua");

How do you guys manage scripts in your game?

Sponsor:

#2 Zouflain   Members   -  Reputation: 532

Like
2Likes
Like

Posted 14 September 2012 - 12:23 AM

You're going to catch some flak for using a singleton, even if the use is justified. Thread safety should be a concern of yours, if you are using multiple threads. Otherwise, all I have to say is it sounds fine, but be aware that you generally only have to luaL_dofile(---) once, and then use C++ functions that interface directly with your virtual machine (so instead of ScriptManager::DoScript("filename.lua") I would suggest ScriptManager::some_function(some_args), where some_function pushes the Lua function name and arguments onto the VM's stack then calls said function. Remember, when you're executing a .lua, it defaults to the global namespace, and you dont generally want to access your scripts that way, except to initialize them.

But, others might know better. This is just how I use lua, and I dont run into trouble with it.

#3 acidleaf   Members   -  Reputation: 158

Like
0Likes
Like

Posted 14 September 2012 - 12:39 AM

So assuming I use the singleton implementation, I will have to set up a loop to call luaL_dofile for each of the scripts I will use in my game, and from there when I want to call a function in Lua, I will use the ScriptManager and manipulate the stack to call the Lua function?

#4 kd7tck   Members   -  Reputation: 715

Like
2Likes
Like

Posted 14 September 2012 - 01:02 AM

If I were in your shoes I would make a scripts folder, then load every script in the folder during runtime and put through luaL_dofile. This way the end user could add any number of extensions or addons as they wish. Create a special C++/Lua api, where you register certain C functions inside lua. These functions when called will act as hooks to common game tasks/functions. These scripts will allow any number of modifications to the game runtime. Once all scripts have been run execute the game with all changes in effect. The scripts should be made optional and not required to run a basic game. For example an optional script could add another level, or new kinds of weapons.

#5 Zouflain   Members   -  Reputation: 532

Like
2Likes
Like

Posted 14 September 2012 - 01:14 AM

I don't even go that far. I only run luaL_dofile on a .lua which calls a hooked C++ function that itself calls luaL_dofile on the argument passed. Thus, I never have to recompile the project when I add a new script, or when a script wants to import another script file (loading every file in the scripts folder adds extra hoops for seperating one mod from another). In other words, the engine only looks for init.lua, and init.lua is just a series of "DoScript("file.lua")". By doing this, a mod manager can easily append or delete the varius DoScript("file.lua") lines and your mod is loaded painlessly.

Otherwise, I handle things exactly as you and kd7tck said.

#6 acidleaf   Members   -  Reputation: 158

Like
0Likes
Like

Posted 14 September 2012 - 01:28 AM

Thanks guys for the kind replies and suggestions. Another question, say I want to use Lua to configure my game GUIs. Do I expose the various GUI elements' member functions such as setPosition(x, y) to Lua, and then in the GUI's init method I run the Lua function that handles the positioning of these GUI controls? Or would it be a better approach to make the GUI's class (for example the MainMenu class) exposed to Lua and do everything in Lua instead?

#7 acidleaf   Members   -  Reputation: 158

Like
0Likes
Like

Posted 14 September 2012 - 01:32 AM

(Is there an edit post option here?)

Just to be clear, currently all of my game states are implemented as different classes (MainMenu, Options, etc.), and each of them has an init() method which is called when they are switched into the game.

#8 kd7tck   Members   -  Reputation: 715

Like
0Likes
Like

Posted 14 September 2012 - 01:47 AM

I don't even go that far. I only run luaL_dofile on a .lua which calls a hooked C++ function that itself calls luaL_dofile on the argument passed. Thus, I never have to recompile the project when I add a new script, or when a script wants to import another script file (loading every file in the scripts folder adds extra hoops for seperating one mod from another). In other words, the engine only looks for init.lua, and init.lua is just a series of "DoScript("file.lua")". By doing this, a mod manager can easily append or delete the varius DoScript("file.lua") lines and your mod is loaded painlessly.

Otherwise, I handle things exactly as you and kd7tck said.


Why would I recompile after adding a script?

Simply program main() to search for all files in the scripts folder and load each one in. No need to pass every file name in through a lua file. This makes things easier for end users; if all an end user has to do is drop in a file then that is ideal.

#9 kd7tck   Members   -  Reputation: 715

Like
0Likes
Like

Posted 14 September 2012 - 01:55 AM

Thanks guys for the kind replies and suggestions. Another question, say I want to use Lua to configure my game GUIs. Do I expose the various GUI elements' member functions such as setPosition(x, y) to Lua, and then in the GUI's init method I run the Lua function that handles the positioning of these GUI controls? Or would it be a better approach to make the GUI's class (for example the MainMenu class) exposed to Lua and do everything in Lua instead?


That will depend on how much control you want to give to the end user. Do not do everything in lua, the game loop needs to be in C++ not lua. You could have a hook that generates a custom state dynamically and places it onto a global state machine.

#10 gdunbar   Crossbones+   -  Reputation: 931

Like
0Likes
Like

Posted 14 September 2012 - 05:52 AM

A somewhat different perspective here. I use lua in my RPG, for scripting things like quests, conversations, etc. Every time I run a lua script, I actually create a whole new lua instance (by calling luaL_newstate(), luaL_openlibs(), luaL_loadstring(), and lua_pcall()). I implemented things this way at first because it was easy, with the intention that if performance was an issue, I could always go back and optimize.

To my pleasant surprise, the performance has been excellent, and no need to chance anything. I should note that I call scripts relatively rarely (a script won't be called every time through the game loop), and my scripts tend to be quite small and self-contained.

Hope that helps,
Geoff

#11 JTippetts   Moderators   -  Reputation: 8498

Like
1Likes
Like

Posted 14 September 2012 - 06:59 AM

I have yet a different perspective. I use Lua for everything except for the really performance critical stuff such as rendering, pathfinding and so forth. Even my main loop is in Lua. The C++ portion of Goblinson Crusoe exists only as a set of classes which can be instantiated from Lua to perform their tasks.

#12 nox_pp   Members   -  Reputation: 490

Like
0Likes
Like

Posted 14 September 2012 - 07:15 AM

Do I expose the various GUI elements' member functions such as setPosition(x, y) to Lua, and then in the GUI's init method I run the Lua function that handles the positioning of these GUI controls? Or would it be a better approach to make the GUI's class (for example the MainMenu class) exposed to Lua and do everything in Lua instead?


Your first approach requires that you tightly couple your GUI element to Lua, so that it can't be used without modification if you decide to move away from Lua in the future. Your second approach is better, but comes with its own set of problems. How much of the interface should you expose to Lua? By exposing the interface, how many other userdatums must be exposed in order to be passed as arguments?

I personally look at my scripts completely differently than my engine code, exposing specifically tailored and simplified interfaces to Lua, rather than the lower level ones.

Between Scylla and Charybdis: First Look <-- The game I'm working on

 

Object-Oriented Programming Sucks <-- The kind of thing I say


#13 Zouflain   Members   -  Reputation: 532

Like
0Likes
Like

Posted 14 September 2012 - 10:25 AM

Why would I recompile after adding a script?

That was actually in response to acidleaf, who made it sound like he was hardcoding all of the script file refferences. Rather than do that, I merely hardcode init.lua, which has the ability to expand the library of lua functions however I or a modder sees fit.

Simply program main() to search for all files in the scripts folder and load each one in.

The problem I see there is with modding. If every file is read indescriminately, you cannot then have a moda.lua and a modb.lua in the scripts folder unless you want the user to always use both mods he has installed there. By using a file to describe each file seperately, you can neatly store all of the lua files for a specific mod in a scripts/modname/ folder, with only the scripts/modname_init.lua called in the scripts/init.lua file. Disabling a mod, then, is as simple as removing the modname_init.lua refference in init.lua.

I suppose you could run every modname_init.lua using your blanket method, but enabling and disabling mods would still require you to remove and replace the init file for no net benefit over the alternative. As an end user, I hate having to move files around (and dont trust programs moving them for me), and so I tend to design code that leaves files in place. Deleting and replacing one line is easy to write a mod manager for and involves less file moving. I don't suppose either design is objectively "better" but I always side with less moving files.

Edited by Zouflain, 14 September 2012 - 10:30 AM.


#14 Key_46   Members   -  Reputation: 422

Like
0Likes
Like

Posted 15 September 2012 - 06:05 AM

Currently I'm using a single state shared across multiple Lua scripts. On the C++ side, the 'mod' definition will register all the .lua files necessary for the game objects, these files contains a factory to create an object (table) inside the lua state, so I don't need a class Enemy or Ally on the C++ side, I just need an Entity providing a minimum interface and which invokes the Enemy or Ally factories from Lua.

The Lua objects communicate using message passing, the interaction is coordinated on the C++ side, using uid's. And since the queues are also in Lua I have freedom to send from int's to complex data structures, if necessary.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS