Cocos2d-x觀察者模式其實很簡單!!--之遊戲開發《趙雲要格鬥》(13),趙雲要格鬥

來源:互聯網
上載者:User

Cocos2d-x觀察者模式其實很簡單!!--之遊戲開發《趙雲要格鬥》(13),趙雲要格鬥

        這裡是Evankaka的部落格,歡迎大家前來討論與交流~~~~~~

       轉載請註明出處http://blog.csdn.net/evankaka

       本文主要詳細講解了設計模式中的觀察都模式及其在Coco2d-x的簡單應用,最後,結合遊戲中的技能冷卻類放大招進行了一個使用。

cocos2d-x版本:2.2.5

工程環境:windows7+VS2010

開啟檔案:將工程放在cocos2d-x安裝目錄下的project檔案夾下用VS開啟

先來看看效果:

 本文效果:


一、觀察者模式簡介 

   觀察者模式(有時又被稱為發布/訂閱模式)是軟體設計模式的一種。在此種模式中,一個目標對象管理所有相依於它的觀察者對象,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實作事件處理系統。我的另一篇博文,24天學會設計模式------觀察者模式,這裡有更加詳細的介紹,有興趣可以看這裡。

    在開發遊戲的時候我們經常需要在層與層之間、情境與情境之間傳遞資料和訊息,Cocos2dx架構應用觀察者模式為我們封裝了一CCNotificationCenter類,也叫訊息通知中樞,它也是一個單例類。

    從觀察者模式來講,CCNotificationCenter類是觀察者模式中的目標對象(主題),而CCNotificationObserver則是觀察者。一個目標對象可以註冊多個觀察者,當目標對象的狀態改變的時候,可以通知觀察者對象作出相應的反應,這是標準的觀察者模式的實現。但是CCNotificationCenter稍微有些許差別,CCNotificationCenter不是通過自身狀態改變來通知觀察者,而是通過顯式地發送觀察者感興趣的訊息來通知它們,訊息名稱則是用來標識觀察者是否感興趣。每次訊息傳遞給CCNotificationCenter,CCNotificationCenter就會遍曆所有的觀察者,找到註冊了該訊息標識符的觀察者,然後將訊息發送給它們。

實現步驟:

1、添加觀察者:

在任何地方,只要你你對某個訊息感興趣(和pureMVC中的listNotification一樣),你就可以在那裡監聽該訊息。

void addObserver(CCObject* target,SEL_CallFuncO callBack,const char* name, CCObject* data);

參數1為事件監聽的目標,參數2為回呼函數(即接收到訊息後執行的函數),參數3為訊息名,參數4為訊息體。

具體實現如下:

  CCNotificationCenter::sharedNotificationCenter()->addObserver(this,
callfunco_selector(GameLayer::callBack),
name,
NULL
2、發送訊息:在需要發送訊息的地方,調用postNotification方法即可,postNotification有兩種,可以不帶資料和帶資料。
void postNotification(const char* name);void postNotification(const char* name,CCObject* data);

name是訊息名,是訊息唯一標識,在整個遊戲過程中是唯一的,因此,我們一般把所有的訊息名放在一個標頭檔中,紡織訊息名重複,data是訊息體,即發送的資料。

發送通知如下:

CCNotificationCenter::sharedNotificationCenter()->postNotification(name);
3、釋放訊息觀察者:

釋放訊息觀察者是很重要的,不釋放的話,會產生記憶體泄露。我們需要在解構函式方法裡面,釋放訊息觀察者。

CCNotificationCenter::sharedNotificationCenter()->removeObserver(
this,
name //訊息名
}
二、使用範例1、一個層內使用觀察者模式

首先,建立一個HelloWord的工程,然後HelloWorldScene.h添加

<span style="font-size:18px;">//添加目標式通知觀察者之後調用的事件void ObserverFunction(CCObject * object);</span>
開啟HelloWorldScene.cpp,在init()函數添加

//註冊Message,如果接收到了,執行ObserverFunctionCCNotificationCenter::sharedNotificationCenter()->addObserver(this,callfuncO_selector(HelloWorld::ObserverFunction),"Message",NULL);
然後HelloWorld::~HelloWorld()添加:

//注意最後一定要釋放訊息,否則內容泄露    CCNotificationCenter::sharedNotificationCenter()->removeObserver(this,"Message");
再實現函數:

//添加目標式通知觀察者之後調用的事件void HelloWorld::ObserverFunction(CCObject * object){CCLOG("You Click menuButton");}


接下來就可以給觀察都通知事件 了~,這裡我直接把項目的menu按鈕的事件(它原本是退出的)改成:

//第一個參數是訊息的名字,第二個參數是CCObject * 類型的訊息值,也就是你要發送的東西CCNotificationCenter::sharedNotificationCenter()->postNotification("Message",NULL);

看看效果:



觀察都模式不僅可以通知更新,也可以傳遞資料 ,下面來看看第2個例子

2、兩個不同的層使用觀察都模式

(1)首先,還是建立一個HelloWord工程,然後建立一個層類 SecondLayer

標頭檔 SecondLayer.h

<span style="font-size:18px;">#ifndef __SecondLayer_SCENE_H__#define __SecondLayer_SCENE_H__#include "cocos2d.h"class SecondLayer : public cocos2d::CCLayer{public:    virtual bool init();  ~SecondLayer();    static cocos2d::CCScene* scene();    CREATE_FUNC(SecondLayer);//添加目標式通知觀察者之後調用的事件void ObserverFunction(CCObject * object);};#endif // __SecondLayer_SCENE_H__</span>

實現檔案SecondLayer.cpp

#include "SecondLayer.h"USING_NS_CC;CCScene* SecondLayer::scene(){    CCScene *scene = CCScene::create();    SecondLayer *layer = SecondLayer::create();    scene->addChild(layer);    return scene;}SecondLayer::~SecondLayer(){//注意最後一定要釋放訊息,否則內容泄露CCNotificationCenter::sharedNotificationCenter()->removeObserver(this,"Message");}bool SecondLayer::init(){    if ( !CCLayer::init() )    {        return false;    }//註冊Message,如果接收到了,執行ObserverFunctionCCNotificationCenter::sharedNotificationCenter()->addObserver(this,callfuncO_selector(SecondLayer::ObserverFunction),"Message",NULL);    return true;}//添加目標式通知觀察者之後調用的事件void SecondLayer::ObserverFunction(CCObject * object){CCLOG("SecondLayer Receive num=%d",(int)object);}

(2)使用

HelloWorldScene.cpp中添加標頭檔 #include "SecondLayer.h"

init()函數中添加:

SecondLayer* second=SecondLayer::create();this->addChild(second,0);
改寫項目menu按鈕的事件:

void HelloWorld::menuCloseCallback(CCObject* pSender){int num=CCRANDOM_0_1()*1000;//0-1000的隨機數CCNotificationCenter::sharedNotificationCenter()->postNotification("Message",(CCObject *)num);//向觀察者傳遞資料}
(3)效果:


看到了吧,SenondLayer類可以收到目標發給它的訊息了啦!

三、《趙雲要格鬥》中使用觀察者模式

    前面我們設計了一個技能冷卻的類,不懂看這裡Cocos2d-x技能冷卻還要等多久?---之遊戲開發《趙雲要格鬥》(9),它是一個層類,現在我們要實現我們一旦按下特殊技術的按鈕,趙雲就要釋放特殊技術(放大招),這裡我的思路是在英雄類(即趙雲)中設定成一個觀察者,一旦觀察到按下了特殊技術的按鈕,而且技能不在冷卻,那麼趙雲就停下所有動作,直接放大招。

英雄類標頭檔 Hero.h中添加

 //技能特效 void SkillAmiation(CCObject * object);//注意要有參數,因為是觀察者模式的調用函數,要不會提示“類型轉換”: 無法從“void (__thiscall Hero::* )(void)”轉換為“cocos2d::SEL_CallFuncO”
英雄類實現檔案 Hero.cpp中初始化英雄InitHeroSprite(char *hero_name)函數中添加

//註冊MessageSkill,如果接收到了,執行SkillAmiationCCNotificationCenter::sharedNotificationCenter()->addObserver(this,callfuncO_selector(Hero::SkillAmiation),"MessageSkill",NULL);

一旦觀察到技能按鈕按下,調用函數:

//技能特效void Hero::SkillAmiation(CCObject * object){m_HeroSprite->stopAllActions();//當前精靈停止所有動畫CCAnimation* animation = CCAnimation::create();  for( int i=1;i<=6;i++)  {  char szName[100] = {0};  sprintf(szName,"skill_%d.png",i);  animation->addSpriteFrameWithFileName(szName); //載入動畫的幀  }  animation->setDelayPerUnit(0.1f);  animation->setRestoreOriginalFrame(true);  animation->setLoops(5); //動畫迴圈//將動畫封裝成一個動作CCAnimate* act=CCAnimate::create(animation);//建立回調動作,攻擊結束後調用AttackEnd()CCCallFunc* callFunc=CCCallFunc::create(this,callfunc_selector(Hero::AttackEnd));//建立連續動作CCActionInterval* skillattack=CCSequence::create(act,callFunc,NULL); IsAttack=true;m_HeroSprite->runAction(skillattack);}

最後記得要釋放:

Hero::~Hero(void){//注意最後一定要釋放訊息,否則內容泄露    CCNotificationCenter::sharedNotificationCenter()->removeObserver(this,"MessageSkill");}
然後在SkillButton.cpp的BeginSkill()函數中,這個類可以看Cocos2d-x技能冷卻還要等多久?---之遊戲開發《趙雲要格鬥》(9)
添加一句:

//第一個參數是訊息的名字,第二個參數是CCObject * 類型的訊息值,也就是你要發送的東西CCNotificationCenter::sharedNotificationCenter()->postNotification("MessageSkill",NULL);

好了,Ok,:




四、再說觀察者模式1、優點:

     實現了目標對象和觀察者之間的抽象耦合,在本例中,則是實現了訊息與觀察者的抽象耦合。可以定義一種訊息與訊息處理對象的一對多的關係,而不用擔心彼此的實現細節。

2、缺點

     如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。

3、適用場合

    (1)一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將這些方面封裝在獨立的對象中使它們可以各自獨立地改變和複用。

    (2)一個對象的改變將導致其他一個或多個對象也發生改變,而不知道具體有多少對象將發生改變,可以降低對象之間的耦合度。

    (3)一個對象必須通知其他對象,而並不知道這些對象是誰。需要在系統中建立一個觸發鏈,A對象的行為將影響B對象,B對象的行為將影響C對象……,可以使用觀察者模式建立一種鏈式觸發機制。

更多的觀察都模式講解可以看24天學會設計模式------觀察者模式

後記:

      這幾天好冷,寫個好的博文不容易啊。這文章都趟我草稿箱好久了啊,又寫代碼又寫文字的又,GIF動畫還不能超2M,我都不知重新了多少張了!CSDN你這個功能要好好的改改下,遊戲中加了聲音了,可惜沒法傳上來聽。。。。看了兩晚的電影,這個遊戲都沒更新了,推薦大家去看《親愛的》(很感人的,要記得內建紙巾。。),《星球崛起》(1,2,拍得很好),《太極》(1,2,打得很舒服),美劇《摩登家庭》(很搞笑.)啦啦啦。我又廢話了,好久沒這麼多廢話了,這個遊戲要完結了,我也要轉到3.3了,下個遊戲出打飛機!


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.