読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

CCNotificationCenterを使ってみよう。

こんにちは。今回2回目の担当となる加藤です。

今回はCocos2d-xの便利な機能「CCNotificationCenter」を紹介していきたいと思います。
提供される機能としては、Objective-Cの「NSNotificationCenter」と同じ機能となります。
具体的にどんな時に使うのかを、一例として「くるるファンタズマ」の戦闘におけるゲームオーバー時のケースを挙げてみましょう。

くるるファンタズマには戦闘画面の「BattleScene(バトルシーン)」とマップ画面の「MapScene(マップシーン)」があります。ゲームオーバー時は「BattleScene」にゲームオーバーを表示する「GameOverLayer」が画面の一番上に生成されます。そしてゲームオーバーを閉じると「MapScene」に戻ります。

普通に考えると「GameOverLayer」が「MapScene」の生成処理を呼べばいい気がしますが、シーンの子であるレイヤーが、親シーンを操作するのはリスクが高い気がします。もうBAD_ACCESSの匂いがプンプンです。

img_01

そこでこの通知機能の出番なのです。

■通知の登録

CCNotificationCenter::sharedNotificationCenter()->addObserver(呼び出したいメソッドを持つクラスへのポインタ, callfuncO_selector(呼び出したいメソッド), "識別用のキー", NULL);

■通知の破棄

CCNotificationCenter::sharedNotificationCenter()->removeObserver(呼び出したいメソッドを持つクラスへのポインタ, "識別用のキー");

■通知の送信

CCNotificationCenter::sharedNotificationCenter()->postNotification("識別用のキー");

◆◆◆ ゲームオーバー側 ◆◆◆

BattleSceneの子であるLayer型のGameOverLayerがやることといえば、CCNotificationCenterに通知を送るだけです。
そして通知がされたタイミングで、BattleSceneを管理しているクラスの「BattleController」に通知登録されているBattleSceneの「BattleController::playContinue」が実行されます。

/**  
 * ゲームオーバー時の処理に成功したときに呼ばれるメソッド  
 */  
void GameOverLayer::successSaveLose(TransferDataModel *receive)  
{  
    CCNotificationCenter::sharedNotificationCenter()->postNotification("Battle_LoseEnd");  
}  

◆◆◆ バトルコントローラー側 ◆◆◆

呼び出される側の「BattleController」には通知登録しておく必要があります。

/**  
* コンストラクタ  
*/  
BattleController::BattleController(BattleModel *model)  
{  
    // 通知を登録  
    CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(BattleController::gameover), "Battle_LoseEnd", NULL);  
}  
  
/**  
* デストラクタ  
*/  
BattleController::~BattleController()  
{  
    // 通知登録を破棄  
    CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, "Battle_LoseEnd");  
}  
  
/**  
* GameOver時の処理がもろもろ(通知で呼ばれるメソッド)  
*/  
void BattleController::gameover()  
{  
    AudioManager::getInstance()->playBGM(SOUND_MAIN);  
    CCScene* scene = MapScene::scene();  
    CCDirector::sharedDirector()->replaceScene(scene);  
}  

イメージ的にはこんな感じでしょうか。

img_02

通知の仕組みを知っておけば、クラスの構造に関係なく間接的にどんなメソッドも呼び出せることになります。
自由度が高い分使いどころが大事ですが、とても便利な機能ですよね!