Hey. I'm not exactly new to irrlicht, and I wasn't sure if this was a "beginner" question or not... but, I'm making a program in C++ where my classes regularly all access the same IrrlichtDevice. So far I've done this by passing the pointer to each class, but I'm not sure if this is the best method. Is there an easier/cleaner way, perhaps with some kind of pointer that can be accessed from all my classes?
Also, I have a "Game Manager" class with a bunch of other classes under it. (Like a list of gameobjects to be updated each tick) Is there a way to make it so that the lower objects can communicate with their parent? (Like, say, a game object issuing a command to the game manager)
Any help would be greatly appreciated.
How would I make "IrrlichtDevice" universal?
Re: How would I make "IrrlichtDevice" universal?
1) you are talking about a global variable : typically frowned upon by the programming gurus.
you could also use a singleton object, which is a fancy global variable. search for it on google.
Code: Select all
#include "irrlicht.h"
// declared outside of any class or function scope
irrlichtDevice* gDevice = 0;
class myClass
{
public
void doSomething()
{
if (gDevice) gDevice->someFunction();
}
};
void main
{
myClass game;
gDevice = createirrlichtdevice();
while (game.doSomething())
{
do more stuff
}
}
Last edited by Seven on Fri May 16, 2014 10:31 pm, edited 1 time in total.
Re: How would I make "IrrlichtDevice" universal?
object to object communication is pretty easy. you need :
1) objects with some way to look them up
2) message structure
3) message Manager
for example :
and each object has a function called receivemessage() that 'knows' what to do with each message.
here is an example object sending a message
this is a 'fire' object. when the physx simulation detects collision between this and another object, the physx world will send
this object a MESSAGE_TRIGGER_ENTER message. this object then sends a message to the other object
saying that it has been FIREDAMAGED
and one receiving a message
this is a character obejct. it receives a firedamage message and displays a hurtful text ont he screen
1) objects with some way to look them up
2) message structure
3) message Manager
for example :
Code: Select all
// a simple message class
class CSObjectMessage
{
public:
ADD_VARIABLE_SETGET(CS_MESSAGE_TYPE,Type); // message type
ADD_VARIABLE_SETGET(CS_MESSAGE_TYPE,Type2); // message type
ADD_VARIABLE_SETGET(int,Source); // who initiated this message
ADD_VARIABLE_SETGET(int,Dest); // who is the message going to
ADD_VARIABLE_SETGET(float,RTime); // what time was the message sent
ADD_VARIABLE_SETGET(float,DTime); // what time to deliver the message
ADD_VARIABLE_SETGET(stringc,Data); // the message
CSObjectMessage(); // class constructor
virtual ~CSObjectMessage(); // class destructor
// dual creation allows for better error handling
virtual bool create(CS_MESSAGE_TYPE type, CS_MESSAGE_TYPE type2, int source,int dest, float rtime, float dtime, stringc data);
};
class MessageList
{
public:
core::list<CSObjectMessage*> m_List; // list of messages
core::list<CSObjectMessage*>::Iterator m_Iterator; // message list iterator
MessageList();
~MessageList();
void initialize();
bool cleanup();
bool create();
bool add(CSObjectMessage* data);
void logInfo();
};
// callback function for the messages
typedef void (*MESSAGECALLBACKFUNC)(CSObjectMessage* message);
// simple message manager class
// messages are time based and are stored until the appropriate time.
// a good example of using messages is for a missile to send itself a timed message
// to explode in 10 seconds when it is fired. the message hangs around and gets delivered
// when the time is right. if the missle already exploded then the message will get
// dropped (since the reciever is not a valid object anymore), otherwise the missile will
// receive the message to explode and will react accordingly.
class CSMessageManager
{
public:
ADD_VARIABLE_SETGET(MessageList,List); // the list of Message pointers
ADD_VARIABLE_SETGET(CSObjectManager*, ObjectManager); // list of created objects
ADD_VARIABLE_SETGET(CSApplication*, Application); // the app
ADD_VARIABLE_SETGET(CSLevel*, Level); // the level
CSMessageManager(); // class constructor
virtual ~CSMessageManager(); // class destructor
virtual void initialize(); // set all variables to a known value
// dual creation allows for better error handling
virtual bool create(CSObjectManager* m, CSApplication* app, CSLevel* level);
virtual bool cleanup(); // cleanup whatever memory mess we made
virtual void frame(float elaspedtime); // do what this class does each frame
// create and add a message to the list
virtual void addMessage(CS_MESSAGE_TYPE type, CS_MESSAGE_TYPE type2, int source,int dest, float rtime, float dtime, stringc data);
// send the message
virtual void dispatchMessage(CSObjectMessage* message);
// clear out existing messages
virtual void clear();
// use a callback if you like.
MESSAGECALLBACKFUNC MessageCallBack;
ADD_VARIABLE_SETGET(int,MessageCallBackId);
void setMessageCallBack(MESSAGECALLBACKFUNC NewCallBack, int id);
};
Code: Select all
// send the message
void CSMessageManager::dispatchMessage(CSObjectMessage* message)
{
// if we have a callback, send it there too
if (MessageCallBack)
if (message->getDest() == getMessageCallBackId())
MessageCallBack(message);
// if this is meant for the app level strcuture, send it there
if (message->getDest() == ID_APP_MESSAGE)
{
getApplication()->receiveMessage(message);
}
else
// if this is meant for the level strcuture, send it there
if (message->getDest() == ID_LEVEL_MESSAGE)
{
getLevel()->receiveMessage(message);
}
else
{
// it must be for an object, so get a pointer to the object
CSObject* obj = getObjectManager()->getObjectPointer(message->getDest());
if (obj)
{
// if the object exists, send the message
obj->receiveMessage(message);
}
}
}
Code: Select all
bool CSObject::receiveMessage(CSObjectMessage* m)
{
if (m_Children)
{
CSObject* obj = m_Children->getNextObject(true);
while (obj)
{
obj->receiveMessage(m);
obj = m_Children->getNextObject(false);
}
}
// we didnt want the message
return false;
}
here is an example object sending a message
this is a 'fire' object. when the physx simulation detects collision between this and another object, the physx world will send
this object a MESSAGE_TRIGGER_ENTER message. this object then sends a message to the other object
saying that it has been FIREDAMAGED
Code: Select all
virtual bool receiveMessage(CSObjectMessage* m)
{
switch (m->getType())
{
case MESSAGE_TRIGGER_ENTER:
{
getLevel()->getObjectFactory()->getMessageManager()->addMessage(CS_MESSAGE_TYPE::DAMAGE_FIRE, CS_MESSAGE_TYPE::MESSAGE_TRIGGER_ENTER, getId(), m->getSource(), 0, 0, "10");
} break;
case MESSAGE_TRIGGER_CONTACT:
{
} break;
case MESSAGE_TRIGGER_EXIT:
{
getLevel()->getObjectFactory()->getMessageManager()->addMessage(CS_MESSAGE_TYPE::DAMAGE_FIRE, CS_MESSAGE_TYPE::MESSAGE_TRIGGER_ENTER, getId(), m->getSource(), 0, 0, "0");
} break;
}
return false;
}
this is a character obejct. it receives a firedamage message and displays a hurtful text ont he screen
Code: Select all
virtual bool receiveMessage(CSObjectMessage* m)
{
switch (m->getType())
{
case CS_MESSAGE_TYPE::DAMAGE_FIRE:
{
int damage = stringcToInt(m->getData());
createTextAnim(getLevel(), getPrimarySceneNode(), stringw( stringc("OUCH!! FIRE DAMAGE -") + stringc(damage)),SColor(255, 240, 0, 0), 3000, dimension2d<f32>(160, 30));
} break;
etc...etc......etc......
Re: How would I make "IrrlichtDevice" universal?
You can do something like putting it into a namespace. For example:
And after creating the Device you must call:
SYSTEM::irrDevice = yourIrrlichtDevice;
And when you want to use, include System.h and use function SYSTEM::getIrrDevice();
Code: Select all
//System.h:
#ifndef SYSTEM_H
#define SYSTEM_H
//forward declaration
namespace irr{
class IrrlichtDevice;
}
namespace SYSTEM {
extern irr::IrrlichtDevice* irrDevice;
inline irr::IrrlichtDevice* getIrrDevice() { return irrDevice; }
}
#endif
Code: Select all
//System.cpp
#include "Sytem.h"
namespace SYSTEM {
irr::IrrlichtDevice* irrDevice = NULL;
}
SYSTEM::irrDevice = yourIrrlichtDevice;
And when you want to use, include System.h and use function SYSTEM::getIrrDevice();
Re-creating Irrlicht with Vulkan: http://irrlicht.sourceforge.net/forum/v ... =6&t=52404
Re: How would I make "IrrlichtDevice" universal?
I like just passing around the pointer. That way anyone reading your code can immediately see which of your classes needs an IrrlichtDevice. Also consider if all those classes really need access to the full device - often they might only need IVideoDriver and ISceneManager for example. Or only IGUIEnvioronment etc. In those cases it's sufficient to pass on those pointers.
Samy way with gamemanager - every game-object you have a pointer to the gamemanager.
(also I have to admit I didn't do it that way in older projects - there I had usually 1 global for the application class which is still fine for smaller applications I guess).
Samy way with gamemanager - every game-object you have a pointer to the gamemanager.
(also I have to admit I didn't do it that way in older projects - there I had usually 1 global for the application class which is still fine for smaller applications I guess).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Re: How would I make "IrrlichtDevice" universal?
I also prefer passing the pointer around. One reason is that I use multiple scenemanagers in my apps. Most of the time that I borrow code off of the forums, the scenenodes assume that the user will be using the getSmgr() functions for irrlicht main structures and I have to rewrite them to accept a smgr pointer so that I can pass mine in. not a big deal, but I try not to assume what the end user will be doing in his app. Sometimes i have a null device that i use for file access and dont pass in the main device, as another example.
also, and someone can correct me since I am not an expert, passing a pointer around is not a big deal in today's compilers as far as speed and whatnot.
also, and someone can correct me since I am not an expert, passing a pointer around is not a big deal in today's compilers as far as speed and whatnot.