尊重开发者的劳动成果,转载的时候请务必注明出处: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。