CCCallFunc是CCActionInstant的子類,是非常重要的一個類族,就是適配器。用大白話說,就是做了一層包裝,把函數包裝成動作,這樣你在執行動作的時候,就可以執行函數了。聽起來很怪異嗎?爲什麼不直接執行函數呢?這是因爲執行條件不同。
使用CCCallFunc家族的類
CCCallFunc家族一共有四個類。這是四個類對象的靜態生成函數:
1. CCCallFunc * CCCallFunc::actionWithTarget(SelectorProtocol* pSelectorTarget,SEL_CallFunc selector);
2. CCCallFuncN * CCCallFuncN::actionWithTarget(SelectorProtocol* pSelectorTarget,SEL_CallFuncN selector);
3. CCCallFuncND * CCCallFuncND::actionWithTarget(SelectorProtocol* pSelectorTarget,SEL_CallFuncND selector, void* d);
4. CCCallFuncO * CCCallFuncO::actionWithTarget(SelectorProtocol* pSelectorTarget,SEL_CallFuncO selector, CCObject* pObject)
我們在寫的時候,就直接用這四個生成相關的動作對象,然後讓節點執行就行。
但是要注意這四個類,分別對應的是四種不同的函數接口,也可以說是他包裝了四種不同的回調函數。這四個回調函數的不同主要是參數表的不同。(貌似是廢話)我們來看這四個回調函數的類型定義
1. typedef void (SelectorProtocol::*SEL_CallFunc)();
2. typedef void (SelectorProtocol::*SEL_CallFuncN)(CCNode*);
3. typedef void (SelectorProtocol::*SEL_CallFuncND)(CCNode*, void*);
4. typedef void (SelectorProtocol::*SEL_CallFuncO)(CCObject*);
這四個玩意要解釋清楚比較麻煩,這是用typedef定義了類成員函數指針。如果你對C++不熟悉,你不需要搞懂具體什麼意思,但你必須保證你的函數簽名和這四個其中之一一致。
也就是說,你自己寫的回調函數簽名,看起來像這樣:
1. void A::f1( );
2. void A::f2(CCNode *node);//接受一個節點,該節點是動作的執行節點
3. void A::f3(CCNode *node,void *param);//接受動作的執行節點,還有一個void參數
4. void A::f4(CCObject* obj);//接受一個CCObject對象指針
你可以在回調函數裏操作這些被傳進來的參數。
另外,在用靜態函數生成動作的時候,你需要使用一個宏,來幫助轉換函數指針類型,就是上面那個callfunc_selector,因爲有四種類型的回調函數,所以也就有四個類型轉換宏
1. #define callfunc_selector(_SELECTOR) (SEL_CallFunc)(&_SELECTOR)
2. #define callfuncN_selector(_SELECTOR) (SEL_CallFuncN)(&_SELECTOR)
3. #define callfuncND_selector(_SELECTOR) (SEL_CallFuncND)(&_SELECTOR)
4. #define callfuncO_selector(_SELECTOR) (SEL_CallFuncO)(&_SELECTOR)
下面寫一個實例供參考:
- void Enemy::boxAttacked(Direction dir,Behaviour be,int i)
- {
- behaviour=be;
- direction=dir;
- this->cleanup();
- sprite->cleanup();
- CCAction *sequneceAction = CCSequence::actions(
- getAnimate("box"),
- CCCallFuncND::actionWithTarget(this, callfuncND_selector(Enemy::boxAttackedDone),(void*)i),
- NULL);
- sprite->runAction(sequneceAction);
- }
- void Enemy::boxAttackedDone(CCNode* pSender,void* i)
- {
- int j=(int)i;
- if(j==1)
- {
- behaviour=MOVE;
- direction=BONE;
- }
- else if(j==2)
- {
- behaviour=MOVE;
- direction=BTWO;
- }
- else if(j==3)
- {
- behaviour=MOVE;
- direction=BTHREE;
- }
- sprite->stopAllActions();
- sprite->runAction(CCRepeatForever::actionWithAction(getAnimate("box")));
- }