久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

cocos2dx中菜單響應(yīng)回調(diào)的實(shí)現(xiàn)原理

 愛藍(lán)斯 2013-12-17

前言:這幾天在做cocos2dx上的跨平臺(tái)的socket庫,,看來看去也只能用BSD去實(shí)現(xiàn)了,。因?yàn)橐邮辗?wù)器的推送消息,所以要做成異步處理,。也參考了很多別人的文章,,本來是想能有個(gè)輪子直接給我用的,看來還是得自己重復(fù)造下,。目前的想法是封裝一個(gè)業(yè)務(wù)層,,內(nèi)部包含一個(gè)socket封裝,使用pthread起一個(gè)線程去select接收數(shù)據(jù),,當(dāng)有數(shù)據(jù)到達(dá)時(shí),,調(diào)用業(yè)務(wù)層的函數(shù)處理數(shù)據(jù)。業(yè)務(wù)層注冊(cè)有界面層的回調(diào)函數(shù),,然后預(yù)處理完畢后直接丟給對(duì)應(yīng)的界面回調(diào)函數(shù)處理,。但是中途編譯上遇到了問題,當(dāng)今天看了下cocos2dx內(nèi)部對(duì)應(yīng)的菜單響應(yīng)事件才搞懂原來是這樣弄的,。

其實(shí)這個(gè)問題可以簡單得看成是A類注冊(cè)了B類的回調(diào)函數(shù),,當(dāng)A類對(duì)象接收到對(duì)應(yīng)的事件后,直接調(diào)用B類的回調(diào)函數(shù)處理,。本來回調(diào)函數(shù)就是給C語言的規(guī)范,,因?yàn)榈搅薈++里面有對(duì)象對(duì)象的概念后,每個(gè)成員對(duì)象調(diào)用的時(shí)候都隱含了一個(gè)this指針,,當(dāng)然,,A類是不具有B類的回調(diào)函數(shù)實(shí)現(xiàn)的,自然編譯的時(shí)候就會(huì)有問題,。

看到網(wǎng)上也有很多解決方法,,其中最牛氣的一個(gè)就是用一個(gè)thunk解決,這個(gè)有點(diǎn)高端,,因?yàn)槭侵苯油ㄟ^匯編代碼修改EAX寄存器的值來實(shí)現(xiàn)這個(gè)this指針的問題,,怕不通用,,其實(shí)最麻煩的是對(duì)這個(gè)不熟悉,到時(shí)候出問題都不知道如何解決,,想想還是作罷,。其實(shí)開始的時(shí)候就有人提到可以把調(diào)用的this指針替換成回調(diào)函數(shù)的真正擁有者,當(dāng)時(shí)沒理解,,現(xiàn)在翻看了cocos2dx的代碼才發(fā)現(xiàn),這貨就是這么搞的,!當(dāng)時(shí)我還覺得很神奇,,原來也是這種土辦法,呵呵,。就拿CCMenuItemImage做例子好了,。

看下CCMenuItem的類定義:

  1. class CC_DLL CCMenuItem : public CCNodeRGBA  
  2. {  
  3. protected:  
  4.     /** whether or not the item is selected 
  5.      @since v0.8.2 
  6.      */  
  7.     bool m_bSelected;  
  8.     bool m_bEnabled;  
  9.   
  10. public:  
  11.     CCMenuItem()  
  12.     : m_bSelected(false)  
  13.     , m_bEnabled(false)              
  14.     , m_pListener(NULL)              
  15.     , m_pfnSelector(NULL)  
  16.     , m_nScriptTapHandler(0)  
  17.     {}  
  18.     virtual ~CCMenuItem();  
  19.   
  20.     /** Creates a CCMenuItem with no target/selector */  
  21.     static CCMenuItem* create();  
  22.     /** Creates a CCMenuItem with a target/selector */  
  23.     static CCMenuItem* create(CCObject *rec, SEL_MenuHandler selector);  
  24.     /** Initializes a CCMenuItem with a target/selector */  
  25.     bool initWithTarget(CCObject *rec, SEL_MenuHandler selector);  
  26.     /** Returns the outside box */  
  27.     CCRect rect();  
  28.     /** Activate the item */  
  29.     virtual void activate();  
  30.     /** The item was selected (not activated), similar to "mouse-over" */  
  31.     virtual void selected();  
  32.     /** The item was unselected */  
  33.     virtual void unselected();  
  34.       
  35.     /** Register menu handler script function */  
  36.     virtual void registerScriptTapHandler(int nHandler);  
  37.     virtual void unregisterScriptTapHandler(void);  
  38.     int getScriptTapHandler() { return m_nScriptTapHandler; };  
  39.   
  40.     virtual bool isEnabled();  
  41.     //@note: It's 'setIsEnable' in cocos2d-iphone.   
  42.     virtual void setEnabled(bool value);  
  43.     virtual bool isSelected();  
  44.       
  45.     virtual void setOpacityModifyRGB(bool bValue) {CC_UNUSED_PARAM(bValue);}  
  46.     virtual bool isOpacityModifyRGB(void) { return false;}  
  47.       
  48.     /** set the target/selector of the menu item*/  
  49.     void setTarget(CCObject *rec, SEL_MenuHandler selector);  
  50.   
  51. protected:  
  52.     CCObject*       m_pListener;      // 回調(diào)函數(shù)擁有者  
  53.     SEL_MenuHandler    m_pfnSelector; // 回調(diào)函數(shù)  
  54.     int             m_nScriptTapHandler;  
  55. };  

其中有兩個(gè)很關(guān)鍵的成員變量,CCObject* m_pListener 和 SEL_MenuHandler m_pfnSelector,。來看下SEL_MenuHandler的定義:
  1. typedef void (CCObject::*SEL_MenuHandler)(CCObject*);  
  2.   
  3. #define menu_selector(_SELECTOR) (SEL_MenuHandler)(&_SELECTOR)  

是的,,這個(gè)就是回調(diào)函數(shù)的類型,然后下面的宏定義是為了方便壘代碼用的,。

再來看看注冊(cè)的代碼:

  1. CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage)  
  2. {  
  3.     return CCMenuItemImage::create(normalImage, selectedImage, NULL, NULL, NULL);  
  4. }  
  5.   
  6. CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage, CCObject* target, SEL_MenuHandler selector)  
  7. {  
  8.     return CCMenuItemImage::create(normalImage, selectedImage, NULL, target, selector);  
  9. }  
  10.   
  11. CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector)  
  12. {  
  13.     CCMenuItemImage *pRet = new CCMenuItemImage();  
  14.     if (pRet && pRet->initWithNormalImage(normalImage, selectedImage, disabledImage, target, selector))  
  15.     {  
  16.         pRet->autorelease();  
  17.         return pRet;  
  18.     }  
  19.     CC_SAFE_DELETE(pRet);  
  20.     return NULL;  
  21. }  
  22.   
  23. bool CCMenuItemImage::initWithNormalImage(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector)  
  24. {  
  25.     CCNode *normalSprite = NULL;  
  26.     CCNode *selectedSprite = NULL;  
  27.     CCNode *disabledSprite = NULL;  
  28.   
  29.     if (normalImage)  
  30.     {  
  31.         normalSprite = CCSprite::create(normalImage);  
  32.     }  
  33.   
  34.     if (selectedImage)  
  35.     {  
  36.         selectedSprite = CCSprite::create(selectedImage);  
  37.     }  
  38.       
  39.     if(disabledImage)  
  40.     {  
  41.         disabledSprite = CCSprite::create(disabledImage);  
  42.     }  
  43.     return initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, target, selector);  
  44. }  

最后反正就是調(diào)用下面的一個(gè)實(shí)現(xiàn)回調(diào)函數(shù)注冊(cè),。

  1. // 后期注冊(cè)  
  2. void CCMenuItem::setTarget(CCObject *rec, SEL_MenuHandler selector)  
  3. {  
  4.     m_pListener = rec;  
  5.     m_pfnSelector = selector;  
  6. }  
  7.   
  8. // 初期綁定  
  9. CCMenuItem* CCMenuItem::create(CCObject *rec, SEL_MenuHandler selector)  
  10. {  
  11.     CCMenuItem *pRet = new CCMenuItem();  
  12.     pRet->initWithTarget(rec, selector);  
  13.     pRet->autorelease();  
  14.     return pRet;  
  15. }  
  16.   
  17. bool CCMenuItem::initWithTarget(CCObject *rec, SEL_MenuHandler selector)  
  18. {  
  19.     setAnchorPoint(ccp(0.5f, 0.5f));  
  20.     m_pListener = rec;  
  21.     m_pfnSelector = selector;  
  22.     m_bEnabled = true;  
  23.     m_bSelected = false;  
  24.     return true;  
  25. }  
好了,就這么綁定起來了,,調(diào)用的時(shí)候也特簡單,,看如下代碼:
  1. void CCMenuItem::activate()  
  2. {  
  3.     if (m_bEnabled)  
  4.     {  
  5.         if (m_pListener && m_pfnSelector)  
  6.         {  
  7.             (m_pListener->*m_pfnSelector)(this);    // 直接調(diào)用了便是  
  8.         }  
  9.           
  10.         if (kScriptTypeNone != m_eScriptType)  
  11.         {  
  12.             CCScriptEngineManager::sharedManager()->getScriptEngine()->executeMenuItemEvent(this);  
  13.         }  
  14.     }  
  15. }  

(m_pListener->*m_pfnSelector)(this); 這句可能要稍微解釋下,其實(shí)也挺好懂的,。首先前面這個(gè)括號(hào)就是對(duì)應(yīng)的函數(shù),,后面的this就是參數(shù),這個(gè)滿足對(duì)函數(shù)指針的定義,,即void (CCObject::*)(CCObject*); 因?yàn)镃CMenuItem基類是CCObject,,那其實(shí)調(diào)用的場景(CScene)基類也一樣。然后就是m_pListener->*m_pfnSelector這個(gè)了,,前面的Listener應(yīng)該沒啥疑議,,關(guān)鍵是*m_pfnSelector可能有些人會(huì)懵,其實(shí)也很簡單,,m_pfnSelector是函數(shù)指針,,首先他是個(gè)指針,存的是個(gè)地址,,然后*自然是取對(duì)應(yīng)地址內(nèi)的內(nèi)容(函數(shù)地址),,對(duì)于函數(shù)調(diào)用來講,其實(shí)就是調(diào)用一個(gè)地址,,而m_pListener->m_pfnSelector明顯是錯(cuò)誤的,,因?yàn)檎{(diào)用者沒有m_pfnSelector這個(gè)成員變量,,他只有對(duì)應(yīng)這個(gè)指針內(nèi)部存儲(chǔ)的函數(shù)地址對(duì)其是有效的。

順便把調(diào)用active的代碼也放一下更清楚:
  1. void CCMenu::ccTouchEnded(CCTouch *touch, CCEvent* event)  
  2. {  
  3.     CC_UNUSED_PARAM(touch);  
  4.     CC_UNUSED_PARAM(event);  
  5.     CCAssert(m_eState == kCCMenuStateTrackingTouch, "[Menu ccTouchEnded] -- invalid state");  
  6.     if (m_pSelectedItem)  
  7.     {  
  8.         m_pSelectedItem->unselected();  
  9.         m_pSelectedItem->activate();    // 就是這里  
  10.     }  
  11.     m_eState = kCCMenuStateWaiting;  
  12. }  
ccTouchEnded這種反正就是響應(yīng)屏幕的操作了,,再網(wǎng)上我就不貼了,,自己找找也能找到的。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多