I want to be able to add scripting to the project I am working on. But I really have no idea how I should design the interface. Is there anyone who has a good understanding of scripting in games, an wants to share his knowledge?
This is what I want to be able to do:
use triggers to start a script. I guess triggers are just a handle to start something. They could be set of by getting near a object, but also for example by time, another script or networking code.
The script should be object bound and loaded when the object is. This is nessecary because the objects are loaded from a server, so I cannot hardcode the scripts in the executable.
several scripts should be able to run simultaneous.
It does not matter to me if the script is in c, phyton, lua etc. The problem lies for me within how I should handle the code, so that multiple scripts can run at the same time, but still have a clear interface.
I have thought about small threads, but it would seem to me, that this would give a lot of synchronisation problems, so maybe some sort of finite state machine. But how would this best be implemented?
I have not posted this in the help, because it is not a direct irrlicht problem. But I hope someone can help.
Greets, Robin
scripting in irrlicht
Perhaps I can be of a little help. I have been working on a project which includes a Python frontend for Irrlicht for over a year now. What I do for scripts running simultaneously is this: I provide two built-in methods: registerframefunction and registerframemethod, the only difference being one is for global functions and the other for class methods. I will post the source code here. It's a tad messy, and nowhere near the quality I would like. Hope it helps. NOTE: The way it is designed is to call the methods registered every frame, so you will need to call ExecuteFrameFunctions() in your main loop. (It is VERY minimalistic, but it has served me well). Use the code however you want. (NOTE: You MIGHT have to call Py_DecRef on each object at exit, but I think Python does that automatically. If it dosen't all it would do is cause a memory leak, and if you want you can iterate through the objects that were IncRef'ed and DecRef them at shutdown.)
Code: Select all
vector<PyObject*> vpoFrameFunctions;
vector<PyObject*> vpoFrameSelfs;
vector<std::string> vsFrameMethods;
void ExecuteFrameFunctions()
{
// Call all frame functions
for(vector<PyObject*>::iterator i = vpoFrameFunctions.begin(); i != vpoFrameFunctions.end(); i++)
PyObject_CallFunction(*i, NULL);
vector<std::string>::iterator vsiIterator = vsFrameMethods.begin();
// Call all frame methods
for(vector<PyObject*>::iterator i = vpoFrameSelfs.begin(); i != vpoFrameSelfs.end(); i++)
{
PyObject_CallMethod(*i, (char*)(*vsiIterator).c_str(), NULL);
vsiIterator++;
}
}
static PyObject* RFUtility_RegisterFrameFunction(PyObject *poSelf, PyObject *poObject)
{
if(!PyFunction_Check(poObject))
{
PyErr_BadArgument();
return NULL;
}
vpoFrameFunctions.push_back(poObject);
Py_IncRef(vpoFrameFunctions[vpoFrameFunctions.size() - 1]);
return Py_BuildValue("i", 1);
}
static PyObject* RFUtility_RegisterFrameMethod(PyObject *poSelf, PyObject *poArgs)
{
PyObject* poInstance, *posMethod;
if (!PyArg_ParseTuple(poArgs, "Os", &poInstance, &posMethod))
return NULL;
vpoFrameSelfs.push_back(poInstance);
Py_IncRef(vpoFrameSelfs[vpoFrameSelfs.size() - 1]);
vsFrameMethods.push_back(std::string(PyString_AsString(Py_BuildValue("s", posMethod))));
return Py_BuildValue("i", 1);
}
//! Contains all methods in the rfutility module
static PyMethodDef pmdRFUtilityMethods[] = {
{"registerframefunction", RFUtility_RegisterFrameFunction, METH_O, "Register a function to be called every frame."},
{"registerframemethod", RFUtility_RegisterFrameMethod, METH_VARARGS, "Register a method to be called every frame."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
New RF2 website at: http://realityfactory2.sourceforge.net/
I think the basic logic would be:
Code: Select all
class IGameObject
{
public:
virtual void RunScript() = 0;
};
class CPlayerObject : public IGameObject
{
public:
CPlayerObject() {}
~CPlayerObject() {}
void RunScript()
{
...
}
};
int main(int argc, char **argv)
{
...
std::vector<IGameObject> ObjectList;
...
while(GameRunning())
{
drv->beginScene();
scm->DrawAll();
drv->EndScene();
int NumObjects = ObjectList.size();
for(int i = 0;i<NumObjects;i++)
{
ObjectList[i].RunScript();
}
}
return 0;
}
-------------------------------------
IrrLua - a Lua binding for Irrlicht
http://irrlua.sourceforge.net/
IrrLua - a Lua binding for Irrlicht
http://irrlua.sourceforge.net/
Wouldnt' one of those script events be a game 'tick' event, i.e. something you'd want to call every frame? In that case you might as well run the scripts every frame.stodge wrote:Calling out into Python every frame for multiple objects is probably slow. I would recommend only calling out to script when you need to - say when something happens, such as the user clicks a button or two objects collide.
I dunno you are probably right. For performance reasons you'll probably want to write a bunch of game events in C++ and call scripts for the events.
OnPlayerMove()
OnCollision()
OnPlayerShoot()
etc...
-------------------------------------
IrrLua - a Lua binding for Irrlicht
http://irrlua.sourceforge.net/
IrrLua - a Lua binding for Irrlicht
http://irrlua.sourceforge.net/
@Phunk
You might take a look at my Squirrel wrapper+demo: http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=15684
That should give you an idea how to set up an interface.
I have not used any events or triggers at the moment. Guess events are dependant on user-actions, like the user reaching a certain location.
These are not standardized actions, so I guess everybody would have to code these for themselves.
In my demo I am calling one script per frame loop to avoid too much cpu use by scripts. Also it gives a more 'random' feel to the scripted actions.
Groeten
Evo
You might take a look at my Squirrel wrapper+demo: http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=15684
That should give you an idea how to set up an interface.
I have not used any events or triggers at the moment. Guess events are dependant on user-actions, like the user reaching a certain location.
These are not standardized actions, so I guess everybody would have to code these for themselves.
In my demo I am calling one script per frame loop to avoid too much cpu use by scripts. Also it gives a more 'random' feel to the scripted actions.
Groeten
Evo