Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

smokes

Using LUA for scripting

This topic is 5725 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

For "timing" I use timers in my engine. I schedule a timer to be triggered in say 2000ms, and I also save the name of the Lua function to call. Each frame, I decrement the timer''s time left by the time since the last frame. Once it reaches 0, I execute the Lua function.

I haven''t yet worked out how to save a Lua table in C++, otherwise I''d also save some Lua paramaters and pass those to the function.

So now I can do this in my code:

Timer:Schedule("Info_SetText", 60000)

I also use ToLua to expose my C++ classes, but I only use one Lua State. That''s all you need, even for multiple Lua scripts.

Share this post


Link to post
Share on other sites
Advertisement
Are you using the object oriented approach when writing your scripts (through the use of tables as objects)?

I know how to call a simple function from lua (procedural function that is). But what if I used the oo approach? How do I call a lua function residing in a table from C++?

To call a normal function you do:

lua_getglobal(state, "myFunction")
...

With the oo approach how do I get the function for a particular "class"? Let's say I have this class definition in lua:

MyClass = {
_parent = GameObjectClass
}

function MyClass:simulate()
log('Doing something actually...')
end

How can I get the MyClass:simulate function? Do I have to call lua_getglobal(state, "MyClass:simulate")? And after that how do I call it on an instance? Do I have to push the instance on the stack as the first parameter of the method (as does the interpreter when calling the method)?

I would be interested to hear anybody who tried something like this.

I'm at work right now and my code is at home. So I can't test it, this is why I asked the question here.

-nosfy
Lead programmer
Creation Objet Inc.

PS: sorry for the long post! : )


[edited by - nosfy on March 20, 2003 11:40:35 AM]

Share this post


Link to post
Share on other sites
I'm using ToLua to generate bindings for my classes, so that I can access them in the Lua scripts. This is the ToLua package file for my camera class.


   
$#include "core/hbScriptTypes.h"
$#include "game/hbBaseCamera.h"
$#include "game/hbSceneBaseEntity.h"

$using namespace Habitat::Core;
$using namespace Habitat::Game;
$using namespace std;

module Habitat
{
module Game
{
class hbBaseCamera:
public hbSceneBaseEntity
{
virtual void Yaw(int yaw);
virtual void Pitch(int pitch);
virtual void StrafeLeft(int step);
virtual void StrafeRight(int step);
virtual void DollyForwards(int step);
virtual void DollyBackwards(int step);

void SetPosition(float x, float y, float z);
void GetPosition(float& x, float& y, float& z);

void SetView(float x, float y, float z);
void GetView(float& x, float& y, float& z);

void SetUpVector(float x, float y, float z);
void GetUpVector(float& x, float& y, float& z);

void SetTarget(float x, float y, float z);

void SetSpeed(float speed);

void SetViewport( int xpos, int ypos,
int width, int height);

void SetNearClip(float clip);
void SetFarClip(float clip);
void SetClip(float nearclip, float farclip);

};
}
}


And then in the script:

  Camera:SetViewport(0, 0, 640, 480)
Camera:SetPosition(0.0, 100.0, 500.0)
Camera:SetView(0.0, 0.0, 0.0)
Camera:SetUpVector(0.0, 1.0, 0.0)
Camera:SetSpeed(100.0)
Camera:SetClip(2.0, 5000.0)


Interesting bug in the forum scripts wiped out two source tags when I edited my post. Hmmmmmm

[edited by - stodge on March 20, 2003 1:35:38 PM]

Share this post


Link to post
Share on other sites
I looked at toLua last week and it seems pretty good at binding existing C++ code to lua. I will probably use toLua for this.

But how can you do it the other way around? How do you call methods on lua objects (objects being tables with method inside) from C++?

Let''s say I have an Entity class in Lua.

  
-- Lua code
EntityClass = {
_parent = GameObjectClass
}
-- Constructor
function EntityClass:new(t)
t._parent = EntityClass -- table t now inherits from EntityClass table
t.visible = 1
t.x = 0
t.y = 0
settag(t, SingleInheritanceTag)
end

-- Methods of EntityClass
function EntityClass:isVisible()
return self.visible
end

function EntityClass:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end

function EntityClass:eventHandler(eventType, eventData)
log(''The EntityClass:eventHandler() method must be overriden.'')
end

-- Let''s test it

entity1 = EntityClass:new({name = ''MyFirstEntity''})
function entity1:eventHandler(eventType, eventData)
log(''This is a specific event handler that will handle events triggered by the game engine in a completed scripted manner.'')
end
entity:move(0, -5)

entity2 = EntityClass:new({name=''MySecondEntity''})
function entity2:eventHandler(eventType, eventData)
log(''This is a specific event handler that will handle events triggered by the game engine in a completed scripted manner.'')
log(''entity2 will react completely differently from entity1 even for the same event.'')
end



The table single inheritance mechanism is well documented on lua''s website (www.lua.org). It''s achieved by creating a new tag and modifying the index fallback. So everytime I call a method on a table inheriting from EntityClass it will go up in the hierarchy until it finds the corresponding method. It works like a charm.

From lua it''s pretty simple to create an EntityClass object and call some methods on it. I would like to be able to do the same from C++. Let''s say all entities are created from lua, maybe by a map script.

Once the map is loaded, the game will run. Some events will occur while the game is running (I hope so otherwise it will be a very boring game). Let''s say from C++ I know the name of the variable referencing the entity (I will get it from lua_getglobal("entity1")). When there is an event that should affect entity1, how will I call the eventHandler method of entity1?

Anybody has already used this "class" mechanism in lua?

-nosfy
Lead programmer
Creation Objet Inc.

Share this post


Link to post
Share on other sites
quote:
Original post by smokes
Isn''t anyone here using LUA for scripting? just discovered it the other day and I think it is really nice for embedding into an engine..


We''re using Lua for the AI API in our realtime strategy game, and I can strongly recommend it. It''s easy to implement and really fast, and I did not discover one bug in 1 1/2 years using Lua (but I must admit that I didn''t exhaust all of Luas capabilities yet .

Regards
Matt

Lead programmer at sechsta sinn
http://www.sechsta-sinn.com

Share this post


Link to post
Share on other sites
I only have one solution so far to my problem (calling a function in a table from C++).

I have to define a procedural function in lua.


  

-- t is the object (table) on which we want to call the method
function eventHandler(t, event)
t:eventHandler(event)
end

function simulate(t, delta)
t:simulate(delta)
end



That''s the best solution so far. I don''t mind having to create such methods, the engine does not have a lot of hooks with the lua objects. The engine must call lua objects to propagate events, another method to execute the AI and that''s about it. The rest is all internal to the engine.

In fact I think it''s quite interesting to proceed like that. I can modify the simulate function to log a few things before I simulate the object. This way I don''t have to modify all the simulate methods in all entities/object specifically. This could be quite handy for debugging.

Anybody has a more elegant solution?

-nosfy
Lead programmer
Creation Objet Inc.

Share this post


Link to post
Share on other sites
On a side not, yesterday I really began to work with toLua. I exported a few classes, for most of them it worked like a charm. It gets more complicated when there are userdata types involved.

Let's say I have a Timer class. And one of it's function accepts a DWORD parameter (delay).

// This is my C++ class
class Timer{

public:

bool isIntervalElapsed(DWORD delay);

protected:
// Some members
}


I created a Timer package for toLua:


// This is my toLua package
class Timer{
bool isIntervalElapsed(DWORD delay);
}


When toLua generates the code it treats the DWORD parameter as a user type.

From lua how do I create a userdata parameter?


-- This is lua code
timer = Timer:new()
timer:isIntervalElapsed(1000)

This does not work at runtime there is an error (I do not recall the exact message).

What am I missing here? Should I simply change the parameter type to 'unsigned long' in the package file?

-nosfy
Lead programmer
Creation Objet Inc.

[edited by - nosfy on March 21, 2003 11:28:56 AM]

Share this post


Link to post
Share on other sites
Matthias6S: Can you give some details on how you implemented the AI scripting using LUA? I''m interested in doing it that way too.

Thanks.

Share this post


Link to post
Share on other sites
quote:
Original post by nosfy
Once the map is loaded, the game will run. Some events will occur while the game is running (I hope so otherwise it will be a very boring game). Let''s say from C++ I know the name of the variable referencing the entity (I will get it from lua_getglobal("entity1")). When there is an event that should affect entity1, how will I call the eventHandler method of entity1?

Well surely there are 101 ways of doing this, depending on whether you want to do it all on the C++ side, all on the Lua side, or something in-between. I mean, surely something simple like lua_dostring(luaVM, entityName + ":eventHandler();") would work?

As for the DWORD conflict, then I would recommend you switch to using ANSI types rather than MS-specific ones in functions that Lua will use. Write minimal wrappers with static_casts if necessary.

[ MSVC Fixes | STL Docs | SDL | Game AI | Sockets | C++ Faq Lite | Boost
Asking Questions | Organising code files | My stuff | Tiny XML | STLPort]

Share this post


Link to post
Share on other sites
quote:
Original post by MichelS
Matthias6S: Can you give some details on how you implemented the AI scripting using LUA? I''m interested in doing it that way too.

Thanks.


MichelS, generally, we distinguish two kind of scripts: mission scripts and AI scripts. There is one mission script per map which is responsible for mission goal checking, timer based events (like calling another script for an ingame event), and you can also place map triggers in the editor which call mission script functions. Every AI player has an own AI script. The API offers methods to create, destroy and modify a single unit, to manage groups, to handle resources, to evaluate influence maps, etc. This offers both generic and very special mission and AI design possibilities. AI scripts can range from simple (build any base building required, create as much units as possible, wander around the map and attack any enemy you find) to very complex ones (create scouts to locate the enemy, evaluate enemy firepower and defense by sending reconnaissance planes, create enough units to defend the base, send scouts to locate more resources, create attack forces that exceed the enemy firepower, if attacked, build defensive buildings where needed, etc. etc.). The units offer a hardcoded lowlevel behaviour depending on their current mode (aggressive/defensive, guard, patrol, berserk, ...), and the script is polled every 100 frames or so (we''re going to balance this out later). The idea behind the API is to be able to modify anything you want without the need to recompile the game. The full API offers methods to create new dialogs, play videos, change background music, or even quit the game, just to mention some examples. One disadvantage is that the mission designers need to be quite familiar with the Lua programming language, and our (well documented) API, but this doesn''t really matter, as most of the programmers in our amateur team are the designers as well

Regards
Matt

Lead programmer at sechsta sinn
http://www.sechsta-sinn.com

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!