Skip to main content
gamedev.net
🔒 Locked

Component-Based Architecture and Lua

Started by JonBonazza 2 replies 2.9k views
Original Post
JonBonazza
JonBonazza
Hello,

First, I should note that I am new here, so it's nice to meet everyone.

I am working on a 2D game engine for the Android OS and I am using LuaJava as a JNI wrapper for the Lua library.

The way I have my engine planned out is that it will use a traditional component-based architecture, where each component will essentially be a script. The game objects will each have a collection (represented by a linked list) of components and, when the game object is updated, it will go through and call the update method of each of its components, thus calling the update method of the script laded for each component.

My problem is that I cannot, for the life of me, figure out how to all for dynamic script names. That is, since the name of each script file is not known ahead of time, how can I make the process of loading and compiling a script name independent?
Co-founder/Lead Programmer
Bonafide Software, L.L.C.
Fairmont, WV 26554 US
ddn3
ddn3
The strategy I would use would be within each of those script modules ( identified by a unique Lua file ), returns back a factory object which can generate an instance of the scripted object belonging to that class.

So to start off you would scan a folder called "Scripts/" and for each found Lua file you would compile it using the require method. Require will compile and execute the given Lua file. If the Lua file returns a value you can store that away. Like so..

local gFactroyMap={}

--if the files are not know before hand you can just scan the entire Scripts/ folder and compile and register all valid scripts
local scriptA = require("Scripts /ScriptA")

--assign the script factory instance to the factory map which is indexed using the enumerated name of the script, which should be unique
gFactroyMap[scriptA.getName()]=scriptA;

so in that code snippet, you compile and execute a file called ScriptA which then returns back a factory object, which have several methods, one of which is getName, which returns back the enumerated full name used by other systems to create it. This is just an example, you can organize how the factory objects are used more appropriately for your project.

In this case an external script would request an instance from ScriptA using something like this ..

function getInstance(objectName)
if (gFactroyMap[objectName]==nil) then
return nil;
end
return gFactroyMap[objectName].createInstance();
end

local instA = getInstance("AdvanceAI_For_Spaceships");
local insBt = getInstance("Special_Powers_SpeedBoost");

local mySpaceShip = { mComponents={instA,instB} }

etc..

That's a simple way and should be flexible enough for your purposes..

Good Luck!

-ddn
JonBonazza
JonBonazza
Thanks for the reply.

I should have mentioned, however, that both Component, and GameObject are C++ classes Within the GameObject class, there is a list<> data member that contains a linked list of all of the registered components (Component class). There is also an update method for the GameObject class that goes through and calls the update method for each Component instance. the update method for the Component class is what executes the script.

So I need someway of interfacing with Lua script files (from C++) without knowing the name of the script file I want to compile ahead of time.
Co-founder/Lead Programmer
Bonafide Software, L.L.C.
Fairmont, WV 26554 US
ddn3
ddn3
I think you can still use basically the same scheme. It depends on how tight the binding you want to create with C++ / Lua. Personally I don't like tight bounded objects between the 2 since it hides inefficiency.. I use a simple Lua API call-able from the C++ side and it uses handles for everything. With Luabind you can bind the the objects might more tightly using the ptrs to the objects themselves all hidden by Luabinds template magic..

In a pure Lua API scheme u would provide some function to dispatch an update method to a given object stored somewhere in Lua using a handle, previously obtained by the getInstance function in the above sample. Something like..

C++

Lua State dispatch function call

onUpdateInstance(instantHandle);

inside Lua it calls the anaglous function



function onUpdateInstance(instantHandle)

if (doesHandleExist(instantHandle)== false) then
return;
end

local instance = getInstanceByHandle(instantHandle);

--call on update on the given instance now, assumed it has its own context internally
instance:onUpdate();

end



That's a very simple Lua API for updating anonymous instances using just their handles.. The handles are created upon the instation of an instance from the script object gotten from require. The instances could live within a global table or as part of a composite Lua / C++ object associated with your entity.

To avoid needless back and forth between C++/Lua i would pass a set of handles to the update function and it can update all the associated entities components in one call vs N calls..

Good Luck!

-ddn

Topic Locked

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

Sign in to reply to this topic.