scripting in irrlicht

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
Phunk
Posts: 78
Joined: Sun Dec 14, 2003 8:18 pm
Location: The Netherlands

scripting in irrlicht

Post by Phunk »

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
AndyCR
Posts: 110
Joined: Tue Nov 08, 2005 2:51 pm
Location: Colorado, USA
Contact:

Post by AndyCR »

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 */
};
zenaku
Posts: 212
Joined: Tue Jun 07, 2005 11:23 pm

Post by zenaku »

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/
stodge
Posts: 216
Joined: Fri Dec 05, 2003 5:57 pm

Post by stodge »

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.
zenaku
Posts: 212
Joined: Tue Jun 07, 2005 11:23 pm

Post by zenaku »

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.
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.


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/
stodge
Posts: 216
Joined: Fri Dec 05, 2003 5:57 pm

Post by stodge »

Good point - I was basing my comment on the fact that ticking of objects would be handled in C++.
evo
Posts: 96
Joined: Mon Jun 27, 2005 6:46 pm
Location: The Netherlands

Post by evo »

@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
Phunk
Posts: 78
Joined: Sun Dec 14, 2003 8:18 pm
Location: The Netherlands

Post by Phunk »

thanks you guys! This topic has been very helpful for me. After seeing the wrapper that evo made, I think ill settle for Squirrel. It seems small and has the licence i like :-)

Greets, Robin
Post Reply