Archive for the ‘Lua’ Category

Event Data from C++ to Lua using Luna(r).

Thursday, April 8th, 2010

It has been a while since I have updated, but I have a couple of posts I will make within the next week. The first post is on the enhancements I have made to our Event System.

The basic implementation of this event system is from lua programming gems (very nice book). It consists of a lua object (otherwise known as a table) that contains a couple of tables that stores Events, Pending Subscribers and Pending Unsubscribers, as well as a couple of functions for updating subscribers and firing events. You can get the full source for the Event System here (toward the bottom, 21 I believe). This Event system has a C++ implementation that simply pushes a string onto the stack and calls the lua function like so.

The Fire Event function looks something like:

 function EventManager:FireEvent( eventName, ... )
   self.Events[ eventName ] = self.Events[ eventName ] or {}
   for subscriber,_ in pairs( self.Events[ eventName ] ) do
     subscriber[ eventName ]( subscriber, ... )
   end
 end

and in C++ looks like:

void FireEvent( lua_State* L, std::string eventName )
{
  //Call the lua FireEvent on this event manager object.
  lua_pushlightuserdata( L, this ); //STACK: em
  lua_gettable( L, LUA_REGISTRYINDEX ); //STACK: self
  lua_pushstring( L, "FireEvent" ); //STACK: "FireEvent", self
  lua_gettable( L, -2 ); //STACK: FireFunc, self
  lua_pushvalue( L, -2 ); //STACK: self, FireFunc, self
  lua_pushstring( L, eventName.c_str() ); //STACK: self, eventName, FireFunc, self
  lua_pcall( L, 2, 0, 0 ); //STACK: self
}

As you may see, there is some lost functionality in this process. Although the lua fire event function takes additional arguments (note the “…” ), the C++ function does not account for this. This allows event data to be passed around at the lua level, but not from C++ to lua. This is the primary use of an Event! when you have keyboard and mouse input you would like to fire an input event that contains the bytecodes of the input used!

This is okay, with a little effort and C++ template magic we can fill in the little gap. we need to be able to pass in any type of data and include it in the arguments to lua like anything else.
In order to do this, we need 2 things.

First we need to change the C++ FireEvent function to a template function, allowing us to only write it once, and still be able to take many types of event data.

Secondly, we need to expose our EventData classes to lua, and be able to push each EventData type onto the lua stack. This can get very complicated, and as i said before, there are many ways to expose data to lua, this is just one of them.

I used luna (actually lunar but I copy and pasted some of it into my luna class). Luna is somewhat of a pain if you want to expose multiple things into your lua environment from C++, but I find that it is mostly copy and paste and chaging names once you got it down.

Here now, is the new code:

C++ FireEvent and Push Function for a collision event

    template <typename T1>
    inline void fireEvent(std::string eventName, T1 a1)
    {
         EventLog << "FireEvent:: " << eventName << "\n";
        //Call the lua FireEvent on this event manager object.
        lua_pushlightuserdata( L, this );            //STACK:    em
        lua_gettable( L, LUA_REGISTRYINDEX );        //STACK:    self
        lua_pushstring( L, "FireEvent" );            //STACK:    "FireEvent", self
        lua_gettable( L, -2 );                        //STACK:    FireFunc, self
        lua_pushvalue( L, -2 );                        //STACK:    self, FireFunc, self
        lua_pushstring( L, eventName.c_str() );        //STACK:    self, eventName, FireFunc, self
        PushArg(a1);
        lua_pcall( L, 3, 0, 0 );
    }
 
    void PushArg(CollisionEvent* EV);
    void PushArg(PickEvent* PE);
    void PushArg(InputEvent * IE);
 
    //here is what the PushArg for a Collision event looks like and how the new fire event is    
    //used.
    void EventManager::PushArg(CollisionEvent* EV)
    {
        Luna<CollisionEvent>::push(L, EV, true);
    }
 
    //Here is the Event System in action, using a Collision Event to pass collision data to lua.    
 
    CollisionEvent* CE = new CollisionEvent();
    void* id1 = pair.actors[0]->userData;
    void* id2 = pair.actors[1]->userData;
    std::cout << "collision:" << (*(int*)id1) << "::"<< (*(int*)id2) << std::endl;
    CE->Obj1_ID = (*(int*)id1); //GameObject ID set at actor creation
    CE->Obj2_ID = (*(int*)id2);
    Events->fireEvent<CollisionEvent*>("Collision" , CE );
 
   //and lastly, the luna(r) implementation of a collision event 
 
#ifndef COLLISIONEVENT_H
#define COLLISIONEVENT_H
 
#include "luna.h"
#include <iostream>
 
using namespace std;
 
class CollisionEvent
{
  public:
    CollisionEvent();
    CollisionEvent(lua_State *L);
    ~CollisionEvent();
 
    static const char className[];
    static Luna<CollisionEvent>::RegType methods[];
    //static const Luna<Foo>::RegType Register[];
    int getObj1ID(lua_State *L);
    int getObj2ID(lua_State *L);
  //private:
    int Obj1_ID;
    int    Obj2_ID;
};
typedef struct { CollisionEvent *pT; } CollisionEventdataType;
 
#endif

Phew, quite a bit. Here is how that very collision event code example is handled by a subscriber in lua.

    function Obj:Collision( CEvent )
            t = CEvent:getObj2ID()
            d = CEvent:getObj1ID()
            print( t .. "," .. d .. ":and my ID:" .. self.ID )
    end

Not too bad huh?!

In conclusion, you can see that template functions and classes can go a long way in making it easy to provide many kinds of event types for an Event System. In Particular, you see how the update function in this event system lends itself to such an implementation in C++. I hope you found this post useful! Next will be on quaternions!

DB
PS. thanks to dmail, ddn, and m_switch on the gamedev forums for the help in coming up with this.

Saving and Loading Lua Tables to a file.

Monday, January 25th, 2010

So, you have integrated Lua into your game engine, you are able to write scripts that define game objects and program some game logic. But what happens when you want to stop your engine? Can you reproduce a game state 20 minutes in? Well, this is where saving/loading lua tables comes in handy. If your Lua environment is anything like mine, tables store everything. And being able to save tables to a file and then re-load them completely intact can achieve this result.

You have 1 and a half options. why the half? Because I soon found out that 1 option provided half the result (really nothing since it mangled tables). Those options? Lua Pickle and Table.save . These little Lua scripts provide the functionality described above.

Lua Pickle is the half, not coming with the file writing functionality but it was easy to put in. The problem with Lua Pickle was that if you saved and loaded and saved again, certain values would come back mangled when loaded, which doesn’t do us any good! The script is 10 years old though so it’s alright, it made a good run. Lastly, it does not store functions, which is not surprising if you do not think of them as first class variables. If your tables are very simple and do not have sub tables and complex self references, this is a decent option.

Table.save is what I use, however there is a catch. The test that runs it causes it to fail. They claim that using a tmpfile() in io is fast for huge tables you want to save, but the stdio tmpfile function was deprecated on the msdn site, so i had to avoid that “extra feature”. the cool thing about table save is it also can save functions, which, as long as you use some sort of encapsulation (meaning the functions only refer to variables that exist in the table) then you are good to go!

So that’s all for now, comments are welcome!

Update: Editor and Lua Lighting…

Monday, January 25th, 2010

I moved the lighting objects to lua, and more so removed some of the legacy lua code (no more sandbox). I’m running lua the way its intended to be run with the engine, initializing lua objects and relying on events for all of their updating.

I started converting my editor to wpf, which actually is not all that bad.

Lua’s Module Identity Crisis

Friday, November 13th, 2009

I just managed to get running the Lua Module system I described toward the end of my presentation. link.

To sum up the reason for this post, i point you to the google search results of “Lua modules” where you will see that the second page in the list is titled “lua’s module function critiqued”.  If you have gone down this route before you know what I am talking about. It is NOT clear cut and dry how to implement modules in lua in the lua book and in a lot of the tutorials online.

The process is not like an import or #include, since “require” searches in the package.loaded table for anything that you have defined in module()… and anything defined WITH module() CANNOT call ANY globals (like print or another require) once this module function is called. (if you go to that critique web page you will see how to overcome this)

Confused? Well it seems like Lua and the Lua team have opportunity to improve the system and straighten things out. Just know that when you call module, the environment is wiped nearly entirely, meaning that those nifty functions like print and such will no longer be with you.

Why don’t I fix it? Because i can see why they do it the way they do, to make each module lightweight and somewhat private… but… there has to be a better way. I really think this is important ALSO because this is the essence of sharing code, and if you cant get the system of sharing code right… how will anyone be able to use it (espcially with the MIT license just begging for free sharing of code).

Update: Moving Forward, Whats Next?

Friday, November 13th, 2009

So the whole point of me doing more Lua stuff right now is so I can go back to working on my lighting model. I want to be able to add cameras, lights and objects to anywhere in my scene by the click of a button, even change normal maps. This makes debugging an OpenGL lighting model easier, since the debugging tools aren’t as plentiful as DirectX.

However, I have also been trying to build up enough stuff to put out a demo to test how the engine is holding up with all of these structural changes. So, I am going to come up with a very very simple demo using the new lua structure.

So Be on the lookout for some future posts on Deferred Shading. If anyone has any requests about how this post should be tailored, I’m all ears. I was thinking about doing a 3 part post. 1st on ABSOLUTE beginner intro 2nd on architecture, and 3rd on implementation.

Game Logic, Game Object Updates, Events

Monday, November 9th, 2009

This Post is an answer to the question recently posted in a comment about updating game objects.

There are 2 encarnations of a single “game object”.

1) The Object class in the C++ engine (which i pointed out in the video), containing things like collision mesh, mesh, texture, etc.

2) The lua table that describes the properties of the game object to make it a gun or a tank or a shield or sword OR more importantly, a button or a minimap, or a bullet. (the advantage of making it generic, more on this later).

Now, I briefly talk about the event system that I have in place in lua in my presentation. This event system allows me to fire events when certain things happen, and have lua game objects (lua tables) call a specific function when a particular event is fired.

This event system is interwoven into the c++ side of the engine so i can fire events from C++ and respond to them in lua. (the gameloop shows the event->update() function which just calls the event system’s lua function that calls all the functions of any listeners where their event had fired that frame)

SO, in a “game” context there are several cases in which something needs to be updated. When an object collides with another object, something needs to happen (a collision event fires for the two objects). when a button gets clicked on a click event fires.

In terms of moving somewhere, an object may be told to move to point x. and when the object gets to point x an event is fired.

On the C++ engine side, the “graphics/physics” object is being updated every frame, where as the game logic is more so updated in response to events.

ALL of our game logic should be able to exist within these events. And things like timers and other tools will be made in C++ to fire events in lua if needed.

here is a link to the source code from lua programming gems (a pretty cool book btw).

So to conclude, you can see that there are multiple kinds of “updates” and event listener functions that are called to make the update process efficient and fast, but hopefully robust =)

Cameras in Lua

Wednesday, October 28th, 2009

Now that the architecture for the engine has been laid out, it is now time to migrate all of our engine’s objects into lua in one way or another, and provide these to the game. I’m starting with things that we originally did in C++.  For example, here are some files of different kinds of Camera implementations. These Core things will exist across multiple games.

Modules

Camera is the base object, while free camera (respond to w,a,s,d and move around)  and preview camera (will sit at the origin and look down the z-axis.)

Right now these implementations are empty, however they will call engine api functions for making a certain camera active for rendering and for moving them around.

Cheers,

J

Lua Part 2. In Video Format.

Monday, October 26th, 2009

Hello Everyone,

I have been on vacation, but before I left I gave a video presentation on the engine’s architecture.

Check it out!

I’ll be posting more errata from this presentation, but here are some corrections.

you cannot (to my knowledge) use DirectX shaders with OpenGL.

I also said that you shouldn’t use pointers with lua for referring to game objects, This is actually a pretty good idea, however it should be done with care, since you are bypassing the enginemanager and going directly to the objects.

Irrlicht and Ogre do implement different physics engines, not sure which.

I also forgot to point out Decoda which is a debugger for the lua environment, it does cost a bit of money but all of you know how valuable a debugger can be. If you use visual studio and have the lua source embedded directly into  your project, as long as you have the .pdb files it will work (so cool!), otherwise you need to point it to the dll I believe (still cool).


Lua Part 1.

Tuesday, July 28th, 2009

Hello Everyone!
In this post I would like to talk about how I am using Lua within my engine so far. I’m sure most everyone who reads this knows of Lua and is likely to have either encountered it or uses it currently. It’s popularity has increased widely over the years due to its ease of integration and use, all while being extremely lightweight (only adding a few kilobytes to a project). I am going to present here a possible way of using Lua as a tool to provide your engine with persistence (which if you are like me you have poured blood and sweat into). This will allow you to keep your engine independent of your game, and give you the ability to easily write multiple games/levels/menus for the same engine. Note: there are dozens of ways to do this to fit your needs, I encourage you to think about how this could be catered differently to suit you.

Right now the engine itself compiles as a DLL, with Lua embedded in it. The Engine has an overlying class that holds everything, and this is the class that is exposed in the DLL, as well as being exposed in Lua. We use Luna to expose our C++ objects in Lua. This allows nice encapsulation of internal mechanisms, while providing ONE place for it to be exposed. Now because we have ONE object that is exposed in Lua, we only have one object which is registered with Luna. The example on Lua’s website on how to use Luna for exposing C++ Objects is pretty straightforward, however I wouldn’t recommend using “their” way (where Lua creates the C++ objects). I have recently picked up Lua Programming Gems, and the chapters there have discussed the performance hit one can take by having too much Lua to C++ data transfer (This may change however, when Lua Part 2 describes game programming of Lua). So instead we Register the class with Luna, which creates a metatable, and then manually expose the Engine Object in lua. For those of you who don’t know what a metatable is, it is a list of rules you can give to a type. For example, you can give an “add” rule to a metatable for your C++ object, and when you try and add two of your C++ objects, Lua will refer to the metatable and find your “add” rule, thus using it to add. This is how Luna exposes member functions for your object. In a Lua script when you call a member function, Lua looks it up in your object’s metatable, which contains a C function pointer. So now that the functions for the Engine class are registered with Lua, we need to expose the Engine object in Lua. To do this, I pushed the Engine Object as userdata, and then set its metatable as the one that Luna created when I registered the Engine Class. So now I have a C++ created object in Lua, that we can add functions to. You may call this our engines Lua API.

Our API consists of a set of functions that work with the Lua stack, which is the main gateway between Lua and C++, and then another set of functions which initialize, render, update, and shutdown the engine. We then have two other projects, an editor, which is done in C# Winforms and hopefully WPF soon, that references Lua Interface (found on luaforge.net) along with a CLI wrapper of the engine, and secondly a program which instantiates our engine alone, with no content loaded. Right now Lua plays a similar role in both the projects, feeding the content through to the engine and calling the engines LoadAsset Function. Our game objects are represented by lua tables. With Lua Interface constructing a table is incredibly simple. With minimal googling you can be an expert on Lua Interface. The developers for it did a really good job with that project. So in C# you have a fancy UI for manipulating a Lua table, and when all the necessary properties are defined (ie mesh, texture), the LoadAsset function is called, which is a Lua API function provided by the main engine class. It parses the Lua table and then calls the Engine’s resource manager to create the object. When it’s all said and done and you would like to save your work, Lua Pickle is a great serialization tool for saving your Lua tables. Lua Pickle will recreate your Lua tables AS a runnable Lua script, basically recreating your tables in text format. When you then load your assets back, you simply need to run the files created and then call load asset for each object.

That does it… I will be making a Lua Part 2 post on game programming to complement this post.