Archived

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

Using LUA for scripting

This topic is 5357 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

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.. [edited by - Smokes on November 20, 2002 10:56:53 AM]

Share this post


Link to post
Share on other sites
We discovered LUA recently and after looking at several other languages decided to use it.

Pro:

a) simple to include
b) small in size and simple, yet powerful (Python anyone?)
c) can be used to interact with C/C++ easily (look at LUA++, or LUNA helper class)

Con:

a) I have yet to find a way to use LUA for timed scripting (something like movie sequences, e.g.
moveleft( 2 ); wait( 200 ); moveright( 2 ); )

Also i know that a some commercial games used LUA for their scripting, a list is available at lua.org.

Regards,

Endurion


Share this post


Link to post
Share on other sites
Endurion: I have the same problem.. But in version 5 which is still in alpha they have implemented minithreads and a yield/resume feature.. if you call yield() inside the script the parser will return in your host program with a code indicating that is is yielding.. then when you''ve done some work you can resume the script.. guess this is what we are looking for.. but it is still not documented.. Also some dude made patch for LUA 4 with a yield/resume function

Share this post


Link to post
Share on other sites
Endurion, you could probably write a scripted function the likes of:


move (time)
(
if (time = 0) moveleft (2)
else if (time < 200) wait
else if (time = 200) moveright (2)
)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Endurion: for "wait" functionality you can implement simple c function that sleeps the thread, it''s just so simple!!

Share this post


Link to post
Share on other sites
AP: yes if you only want to run one script at a time and you run it in a seperate thread from the gameloop.. And you wouldn''t just wanna Sleep().. you would probably want to wait for some event object :-).. But as I mentioned the functionality is in LUA 5 and in a third party add-on

Share this post


Link to post
Share on other sites
AP: yes, would work, if i would only want one script running in a seperate thread, but alas, i''m thinking of having several scripts running, and this yield/resume stuff sounds just like the thing!

I already downloaded the alpha 5 of LUA, but didn''t look in the code, just the docs, and there''s no yield/resume yet. Let''s hope they make it a part.

Actually i was almost starting to implement something like this myself.

Thanks for all the replies, but actually i wasn''t the one starting the thread

Regards,

Endurion

Share this post


Link to post
Share on other sites
My Lua coroutine system (which I am reeeally proud of) handles this nicely. Event handlers execute simultaneously and can block on arbitrary expressions. For instance:


-- walk 50 pixels, wait 200 frames, then walk 50 pixels again
walk(50)
for i=1, 50 do
yield()
end
walk(50)

-- tell Fred to pick up the sock, wait for him to finish, then cough

callevent(fred, {verb="get", object="sock"})
while ~ fred.action.complete do
yield()
end
cough()


This is all with Lua 5.0 alpha''s coroutine support. 5.0 beta is coming out soon, with certain fundamental changes to coroutines, so if you''re planning something like this it might be a good idea to wait.


Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
Sneftel: yes that is a nice function.. But I kindda need some documentation about.. In the lua header I saw that the lua_resume() function took TWO lua_States as arguments.. why two?!?.. I mean you run your script.. then it yields.. then your program call resumes.. all happening in the same lua_State.. what is the need for the second?

gip: well you can download a script for book on lua.. in postscript format (download ghostscript and gview of you are using windows).. and there was also something in portuguese (lucky you, to me it is just nonsense :-).. you can get both from the lua main site http://www.lua.org

Share this post


Link to post
Share on other sites
quote:
Original post by smokes
Sneftel: yes that is a nice function.. But I kindda need some documentation about.. In the lua header I saw that the lua_resume() function took TWO lua_States as arguments.. why two?!?.. I mean you run your script.. then it yields.. then your program call resumes.. all happening in the same lua_State.. what is the need for the second?


yeah, the refman-alpha isn''t too good.

lua_resume takes two lua states: the parent state, and the thread state. I''ve only ever created threads from the parent thread, so I dunno if this has to be the thread that called newthread. So you do it like this (don''t have the manual in front of me, so the syntax is probably wrong):


lua_State L = lua_open();
lua_State T = lua_newthread(L);
lua_cobegin(T, -1); // assuming the function is at the top of the stack
lua_resume(L, T);


OH NOS! TEH INTRENAL SERVER ERRER!


Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
I took a look at the Lua site yesterday and was kind of overwhelmed by the number of choices in the Lua/C++ binding category... can someone recommend a good one that they''ve used? Have you used others?

Share this post


Link to post
Share on other sites
I personally don''t use any of them; I like binding classes and functions myself. But as far as I can tell, most people use tolua.


Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
After reading this thread, i went out and tried it by myself.

And i have to say i am really amazed. It was horrible easy to expose my classes to lua, manipulate c++ object instances from lua and vice versa. Maybe it's not that powerful than Python, but producing working bindings is by far easier then with python (took me ages, even with boost:ython).

btw, i use tolua. Anyone knows if there's a wrapper to hide the stack handling when extracting LUA variables in C++?

- Stephan



OpenMountains | Open source snowboard simulation - some day.

[edited by - stephanh on November 23, 2002 1:17:52 PM]

Share this post


Link to post
Share on other sites
I don''t know of any, but if you poke around in the lua standard libraries (lualib.h and files that include it) you''ll find a ton of functions (most of which start with luaL) geared specifically towards exposing C/C++ functions to lua. Those can do away with much of the busywork involved in exposing functions.


Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
Sneftel:
can the yield & resume functions only be used with lua threads?.. i mean cant you just run a script in one lua_State.. it yields.. you do some work (executing your game loop eg) your resume the lua_state?

Share this post


Link to post
Share on other sites
Not really sure; I''ve never had occasion to try it. I would assume not... but you could easily get around this by just doing everything in one thread that you create at the beginning.


Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
Not exactly related to the topic..

I''m incorporating Lua into my game. Though I have problems understanding why I would need multiple lua_state... Somebody can elighten me on this?

I have the Game Scripting Mastery book and he says that if you want to run multiple scripts you will need multiple states. Does it mean that if I have multiple entities in my world (monsters mostly and objects) I will need a lua_state for each entity?

Does it mean I have to register all my external functions with each and every lua_state I create?

Thanks guys!
Patrick Lafleur

Share this post


Link to post
Share on other sites
Re-registering isn''t gonna be a problem if you encapsulate that in a single call, is it?

I think the idea is that you can have several threads running Lua scripts at any given time. Or some aspects of your application may need to store their state while other scripts are running, so you keep the lua_states separate.

[ 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
No it is not a problem registering the functions again (as it is a single call in my case). I was just wondering if I was on the right track.

I did not plan to use threads though. I will execute my scripts every x milliseconds (all scripts could use a differente rate if needed) and all the scheduling will be done in my TaskScheduler (scripts being one of the tasks that can be scheduled).

Will that work ok?

[edited by - nosfy on March 19, 2003 8:46:34 AM]

Share this post


Link to post
Share on other sites
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
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