Skip to main content
gamedev.net
🔒 Locked

Scripting with Lua

Started by rasher_b2 8 replies 3.7k views
Original Post
rasher_b2
rasher_b2
I'm just learning how to use Lua to script a small game I'm working on. The game is written in C++ and I'm using Luabind. I've been thinking about how to actually implement scripting in my game.

Most of my game's logic in hardcoded in C++ but take, for example, a trigger. When the player hits a trigger something should happen, and what happens can be different for each instance of a trigger. Therefore, I thought it would be nice to have something like an onHit(params) function in a Lua script that is called to execute some logic for a trigger.

The problem is that each instance of a trigger needs a separate onHit function. So I thought maybe I could create a table that maps trigger ids to their onHit function. Now each trigger can have a separate function.

What's your view on this? I see in the Luabind docs, another solution might be extending my C++ trigger class in Lua.

Another thing is: if I were to create a game object with all its logic implemented in Lua...how is this generally done? Could each object, in C++, have a tick function that calls some Lua function? Or is this generally not how that problem is approached.

Thanks!
theOcelot
theOcelot
Quote:
Original post by rasher_b2
The problem is that each instance of a trigger needs a separate onHit function. So I thought maybe I could create a table that maps trigger ids to their onHit function. Now each trigger can have a separate function.


Makes sense to me. Another thing you could do is a table that maps the trigger itself, whether its a table or userdata, to its onHit function.
OnHitFunctions[MyTrigger](MyTrigger, params)
rasher_b2
rasher_b2
Quote:
Original post by theOcelot
Makes sense to me. Another thing you could do is a table that maps the trigger itself, whether its a table or userdata, to its onHit function.
OnHitFunctions[MyTrigger](MyTrigger, params)


Thanks for the reply. That makes sense too. Actually, the more I think about it, the more it seems I should move my game logic to Lua and have the C++ part of my game provide services such as rendering and physics.
Ariste
Ariste
Quote:
Original post by rasher_b2
Quote:
Original post by theOcelot
Makes sense to me. Another thing you could do is a table that maps the trigger itself, whether its a table or userdata, to its onHit function.
OnHitFunctions[MyTrigger](MyTrigger, params)


Thanks for the reply. That makes sense too. Actually, the more I think about it, the more it seems I should move my game logic to Lua and have the C++ part of my game provide services such as rendering and physics.


Agreed. I think, in general, it's a good idea to move as much as possible into script and leave only performance-critical sections in native code. C++ is great at what it's great at, but writing in scripting languages is so much easier :)
Ashaman73
Ashaman73
Quote:

Another thing is: if I were to create a game object with all its logic implemented in Lua...how is this generally done? Could each object, in C++, have a tick function that calls some Lua function? Or is this generally not how that problem is approached.

Well, this is not an issue with including a script language into your game. Using trigger, ticks , updates etc. could be all solved completly in c++ or in lua. The question is, where to make the cut :-)

I don't know your game (c++) structure sofar, but it seems that you already have some kind of gamelogic in c++, something like this:
class Entity{  void update() {}  void onHit() {  ... do some stuff..}  void onOtherTrigger() { ... do other stuff..}}


My way to handle this in my game is to map each C++ entity to an lua object. In lua this could look like
object_pool = {}registerNewObject = function( _cplusplus_reference)  object_pool[reference] = {}  _lua_object.ref = _cplusplus_referenceendgetObject = function( _cplusplus_reference)  return object_pool[_cplusplus_reference]endgetReference = function( _object)  return _object.refend


Whenever you create a c++ entity, call the registerNewObject function. Next you should use your c++ entity to interface the lua functions:
class Entity{  void update() { callLuaObjectFunc(this,"update");}  void onHit() { callLuaObjectFunc(this, "on_hit");}  void onCollision() { callLuaObjectFunc(this,"collision"}}


The callLuaObjectFunc will call something like this in your lua scripts:
callFunc = function( _cplusplus_ref, _function_name)  local obj = getObject( _cplusplus_ref)  -- check if method is present  if obj[_function_name]~=nil then    -- call method    obj[_function_name](obj)  endend


Eventually you can add individual functions for each object to handle object dependent behaviour by simply assigning functions to each lua object:
react_to_hit = function( _obj)  .. react to hitendlook_for_enemy = function( _obj)  .. scan surrounding for enemiesendinitMonster = function(_cplusplus_ref)  local obj = getObject( _cplusplus_ref)  obj.on_hit = react_to_hit  obj.update = look_for_enemyend
rasher_b2
rasher_b2
Quote:
Original post by Ashaman73
Well, this is not an issue with including a script language into your game. Using trigger, ticks , updates etc. could be all solved completly in c++ or in lua. The question is, where to make the cut :-)


Yep, could be done in either but just need to decide where to separate things. I did have an Entity with tick, etc. functions in C++. However, after some thinking and prototyping, I have decided to split things a bit lower down so entities only exist on the Lua side of things. This means I just handle things like rendering, physics, etc. on the C++ side.

What I'm doing now is creating a Lua state when my game starts. I keep this state around until the game exits. Lua can use the C++ API to create game states (a game state is something like the menu, game world, pause menu). As the game loop runs, it calls a tick function in Lua that runs the active state's logic. Input events are also propagated to the Lua code.

I'm not sure how much sense that made. I've left out many details but it's been working well for me so far. I'll elaborate if anyone wants to continue the discussion.
Ariste
Ariste
Quote:
Original post by rasher_b2
Quote:
Original post by Ashaman73
Well, this is not an issue with including a script language into your game. Using trigger, ticks , updates etc. could be all solved completly in c++ or in lua. The question is, where to make the cut :-)


Yep, could be done in either but just need to decide where to separate things. I did have an Entity with tick, etc. functions in C++. However, after some thinking and prototyping, I have decided to split things a bit lower down so entities only exist on the Lua side of things. This means I just handle things like rendering, physics, etc. on the C++ side.

What I'm doing now is creating a Lua state when my game starts. I keep this state around until the game exits. Lua can use the C++ API to create game states (a game state is something like the menu, game world, pause menu). As the game loop runs, it calls a tick function in Lua that runs the active state's logic. Input events are also propagated to the Lua code.

I'm not sure how much sense that made. I've left out many details but it's been working well for me so far. I'll elaborate if anyone wants to continue the discussion.

I do something similar. Basically, the engine exposes as much functionality as possible and allows Lua to control it from the outside.
AverageJoeSSU
AverageJoeSSU
Quote:
Original post by Ashaman73
Quote:

Another thing is: if I were to create a game object with all its logic implemented in Lua...how is this generally done? Could each object, in C++, have a tick function that calls some Lua function? Or is this generally not how that problem is approached.

Well, this is not an issue with including a script language into your game. Using trigger, ticks , updates etc. could be all solved completly in c++ or in lua. The question is, where to make the cut :-)

I don't know your game (c++) structure sofar, but it seems that you already have some kind of gamelogic in c++, something like this:
*** Source Snippet Removed ***

My way to handle this in my game is to map each C++ entity to an lua object. In lua this could look like
*** Source Snippet Removed ***

Whenever you create a c++ entity, call the registerNewObject function. Next you should use your c++ entity to interface the lua functions:
*** Source Snippet Removed ***

The callLuaObjectFunc will call something like this in your lua scripts:
*** Source Snippet Removed ***

Eventually you can add individual functions for each object to handle object dependent behaviour by simply assigning functions to each lua object:
*** Source Snippet Removed ***


I basically do this, except i take it a step further and only do graphical and physics things at the C++ object, and all other stuff (game logic) at the lua level. I use an event system to pass event data from c++ to lua. I highlight it in my blog.

What im working on now is constructing a level in lua.




------------------------------ redwoodpixel.com
rasher_b2
rasher_b2
Quote:
Original post by theOcelot
Sounds cool to me. So Lua functions request graphical and physical objects from the C++ engine?


Yup. Lua requests something from the C++ side and is given back a handle. It can then use this handle with functions to manipulate whatever it requested. Sort of like what OpenGL does with textures, they type of API.

Quote:
Original post by AverageJoeSSU
What im working on now is constructing a level in lua.


I'm also working on something like that. I'm using Lua code as my data format. Basically, a level file is just Lua code that calls whatever functions it needs to create the level. The file also has level specific data and functions. So, for example, in the level file an entity might look like:

entity{ class = "Player", args = { pos = vector2(10, 10) --[[ some more args here ]]} }


Where entity is a function that takes a table parameter and spawns an entity in the game's world.

[Edited by - rasher_b2 on June 10, 2010 7:13:29 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.