Tuesday, June 16, 2009

"What has God wrought?

Okay...so it isn't as dramatic as Morse sending out his first message over wire, but I've completed the messaging for my engine using Boost Signals2. All is working well.

That's it, that's the post...short and sweet. Okay, okay...here's a sample of the messaging setup using Boost::Signals2...


class ObjController
{
public:
ObjController() { printf("ObjController::ctor called.\n"); }
~ObjController() { printf("ObjController::dtor called.\n"); }


boost::signals2::connection RegisterHitMsg(const signalSend_type::slot_type &subscriber)
{
return m_SendHitMsg.connect(
subscriber);
}

boost::signals2::connection RegisterRenderMsg(const signalSend_type::slot_type &subscriber)
{
return m_SendRenderMsg.connect(subscriber);
}

boost::signals2::connection RegisterTestMsg(const signalSend_type::slot_type &subscriber)
{
return m_SendTestMsg.connect(subscriber);
}

void CheckCollision(short nID)
{
m_SendHitMsg(nID);
}

void RenderObjs(short nID)
{
m_SendRenderMsg(nID);
}

void TestMsg(short nID)
{
m_SendTestMsg(nID);
}

private:
signalSend_type m_SendHitMsg;
signalSend_type m_SendRenderMsg;
signalSend_type m_SendTestMsg;
};

class ObjA
{
public:
ObjA(ObjController& objCntrl, short nID) : m_objCntrl(objCntrl), m_nID(nID)
{
printf("ObjA::ctor called.\n");

m_connection = m_objCntrl.RegisterHitMsg(boost::bind(&ObjA::HandleCollision, this, _1));
m_connection2 = m_objCntrl.RegisterRenderMsg(boost::bind(&ObjA::RenderObjects, this, _1));
m_connection3= m_objCntrl.RegisterTestMsg(boost::bind(&ObjA::Test, this, _1));
}

~ObjA()
{
printf("ObjA::dtor called.\n");

m_connection.disconnect();
m_connection2.disconnect();
m_connection3.disconnect();
}

private:
void HandleCollision(short nID)
{
if(m_nID == nID || kBROADCAST == nID)
printf("ObjA::HandleCollision called - id: %d\n", m_nID);
}

void RenderObjects(short nID)
{
if(m_nID == nID || kBROADCAST == nID)
printf("ObjA::RenderObjects called - id: %d\n", m_nID);
}

void Test(short nID)
{
if(m_nID == nID || nID == kBROADCAST)
printf("ObjA::Test - id: %d\n", m_nID);
}

boost::signals2::connection m_connection;
boost::signals2::connection m_connection2;
boost::signals2::connection m_connection3;

ObjController& m_objCntrl;
short m_nID;
};

typedef boost::shared_ptr spOBJA;

int _tmain(int argc, _TCHAR* argv[])
{
ObjController theObjController;

spOBJA pTheObj1(new ObjA(theObjController, kOBJ1_ID));
spOBJA pTheObj2(new ObjA(theObjController, kOBJ2_ID));

theObjController.CheckCollision(kBROADCAST);

// delete pointer to test that following test msg isn't called since object is gone == slot gone

pTheObj2.reset();

theObjController.RenderObjs(kBROADCAST);
theObjController.TestMsg(kOBJ2_ID); // will be ignored

return 0;

}

I set it up so that I can only signal a specific object if I like, utilizing a specific ID or BROADCAST to all. Yes, I know I can disable slots and turn off individual updates, but since the game will have a relativily small number (20 at most) of objects in a level at a time, I went for the quick and dirty.

The ID approach works but, a better approach would be to have a base message class, and derive messages off of it. Then have the objects when they receive a base message, send back for the actual derived message, but this will work, and I didn't want the over head (although it wouldn't be much more overhead).

The Boost libraries used are signals2, bind, and shared_ptrs. In the engine I add an aggregate to keep a list (vector) of bools on the returns on collision detects, for the game control object to notify the Lua scripts. I don't want any game specific actions in the engine. I also moved the connections into a vector and iterate through them to disconnect on the object reset.

This is just a sample, the code has some typedefs that are in a header file. So, this will not compile or run, but if you would like the complete working source shoot me an email and will send it off.

Well, back to designing the scripting engine component and tying that in.

- .. .-.. .-.. / -. . -..- - / - .. -- . (so you like games? figure out what that Morse code says. :) )

No comments: