关闭

【cocos2d-x IOS游戏开发-捕鱼达人5】C++中函数代理与信号插槽机制

标签: cocos2d-x捕鱼达人callback扩展c++
2499人阅读 评论(2) 收藏 举报
分类:

尊重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/17141275


上节回顾

【cocos2d-x IOS游戏开发-捕鱼达人4】基本游戏框架


1、函数代理与C++实现

什么是函数代理(function delegate)
函数代理是一种对象,它能模拟函数的使用方式。并且它可以使调用者不用关心回调函数的类型

回调函数类型
       全局函数
       静态成员函数
       成员函数

C++中的函数代理
C++中没有原生的函数代理类型,必须要自己实现。

实现方式
模板
使用方式
delegate<void(int,int,CCObject*)> m_delegate;
m_delegate(0,0,NULL);


2、信号插槽机制

signal/slot
       在qt、boost等库中有相关实现。
开源的库
        FastDelegate
        sigslot

我们的方案
将delegate封装,使其可以支持多个delegate监听


来看具体的实现:

#ifndef __SINGAL_SLOT_H__
#define __SINGAL_SLOT_H__

#include <vector>
namespace fishingjoy
{
	namespace base
	{
		//===============delegate==================
		//使用模版封装代理
		template<typename T>
		struct Delegate{};


		//void param.
		template<>
		struct Delegate<void(void)>
		{
			typedef Delegate<void(void)> SELF_CLASS;
			typedef void (SELF_CLASS::*CALL_BACK_FN)();
			typedef void (*GENERIC_CALL_BACK_FN)();
			SELF_CLASS* m_pThis;
			union{
				CALL_BACK_FN m_pMemberCallback;
				GENERIC_CALL_BACK_FN m_pGenericCallback;
			};
			

			Delegate()
				:m_pThis(NULL)
				,m_pMemberCallback(NULL)
			{

			}
			
			//使用方式base::Delegate<void(void)> testd(this,&CGameLogic::shutdown);然后会在operator()函数中执行testd
			template<typename X>
			Delegate(X* pThis,void(X::*pCallback)())
			{
				this->m_pThis = (SELF_CLASS*)pThis;
				this->m_pMemberCallback = (CALL_BACK_FN)pCallback;
			}

			Delegate(void (*Callback)())
			{
				m_pThis = NULL;
				m_pGenericCallback = Callback;
			}

		public:
			void operator()()
			{
				if(m_pThis!=NULL&& this->m_pMemberCallback!=NULL)
				{
					(m_pThis->*m_pMemberCallback)();
				}
				else if(m_pThis==NULL){
					if(m_pGenericCallback!=NULL)
						m_pGenericCallback();
				}
			}
		};


		//=================signal===========================
		template<typename T>
		struct Signal{};

		template<>
		struct Signal<void(void)>
		{
			std::vector<Delegate<void(void)> > m_Slots;

			void operator()()
			{
				size_t t = m_Slots.size();
				for(size_t i = 0; i < t; ++i){
					Delegate<void(void)>& d = m_Slots[i];
					d();
				}
			}

			void operator +=(const Delegate<void(void)>& d)
			{
				m_Slots.push_back(d);
			}
		};
	}
}
#endif

使用方式:

#ifndef _GAME_LOGIC_H_
#define _GAME_LOGIC_H_
#include "cocos2d.h"
USING_NS_CC;

#include "../include/IGameScene.h"
#include "../include/SignalSlot.h"
namespace fishingjoy
{
	namespace logic
	{
		class CGameLogic:public cocos2d::CCObject
		{
			scene::IGameScene* m_pGameScene;
		public:
			//override base class.
			void update(float dt)
			{
				if(m_pGameScene)
					m_pGameScene->update(dt);
			}

		public:
			bool init(CCScene* pScene)
			{
				//会去执行CGameLogic::shutdown函数,结束导演的执行
				base::Delegate<void(void)> testd(this,&CGameLogic::shutdown);
				testd();

				base::Signal<void(void)> s;
				s+=testd;
				s();

				if(pScene==NULL)
					return false;
				m_pGameScene = scene::createScene();
				if(m_pGameScene==NULL)
					return false;

				m_pGameScene->attachTo(pScene);
				return true;
			}
			void shutdown()
			{
				//to do..

				//exit.
				CCDirector::sharedDirector()->end();
			}
		};
	}
}
#endif

在去执行:

	static CCScene* pScene = CCScene::create();
	if(GGameLogic.init(pScene)==false)
		return false;
	pDirector->getScheduler()->scheduleUpdateForTarget(&GGameLogic,0,false);
  
	// run
	pDirector->runWithScene(pScene);

会看到程序跑起来,然后自己结束了;

shutdown函数执行了两次

log信息显示为:

?operator:fishingjoy::base::Delegate<void __cdecl(void)>::operator ()
?н:fishingjoy::logic::CGameLogic::shutdown
?operator:fishingjoy::base::Delegate<void __cdecl(void)>::operator ()
?н:fishingjoy::logic::CGameLogic::shutdown

大家可以将delegate与cocos2d-x中的menu_selector等实现对比一下,看看各自的优劣。
还可以尝试自己扩展带参的delegate和signal。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:446249次
    • 积分:6600
    • 等级:
    • 排名:第3736名
    • 原创:188篇
    • 转载:3篇
    • 译文:1篇
    • 评论:187条
    博客公告
    博客专栏