夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【cocos2d】ポーズメニューの実装方法

BeeClusterにポーズメニューを実装したときの方法をメモしておきます。

f:id:takujidev:20130831200102j:plain:w300

cocos2dでアプリの動作を一時停止するにはCCDirectorにpauseメッセージを送ります。

[[CCDirector sharedDirector] pause];

BGMを止める場合はSimpleAudioEngineにpauseBackgroundMusicメッセージを送ります。

[[SimpleAudioEngine sharedEngine] pauseBackgroundMusic];

ポーズ状態からアプリの動作とBGMを再開する方法はつぎのとおりです。

[[CCDirector sharedDirector] resume];
[[SimpleAudioEngine sharedEngine] resumeBackgroundMusic];

なお、アプリをポーズ状態で放置してiPhoneの画面がロックされた場合、ロックを解除するとゲームのポーズ状態も自動的に解除されます。この処理はAppDelegate.mのapplicationDidBecomeActiveメソッドが行っています。

自動的に解除したくない場合は、ポーズを掛けるときにフラグを立て、AppDelegate.mのapplicationDidBecomeActiveメソッドでそのフラグを見てポーズを解除するかしないか判断します。
このあたりは、こちらのサイトを参考にさせていただきました。
BeeClusterの場合は、次のようにpausedというフラグを作ってそれを参照しています。

-(void) applicationDidBecomeActive:(UIApplication *)application
{
	if( [navController_ visibleViewController] == director_ ) {
        if (![InfoLayer sharedInfo].paused) { // ポーズ中の復帰の場合はresumeしない
            [director_ resume];
        }
    }
}

ただのポーズボタンでは物足りないので、ポーズメニューを作り、「ポーズの解除」、「同じ面をはじめから」、「タイトル画面へ戻る」、「ボリューム調整」ができるようにしました。

ゲーム画面とポーズメニューの文字が重なると見にくいので、ポーズ中はゲーム画面の輝度を落としています。
画面の輝度を落とすには、iPhoneの画面と同じサイズの真っ黒の画像を重ね、opacityで透過率を調整しています。

        _paused = YES; // ポーズ中フラグをたてる
        [[CCDirector sharedDirector] pause];
        [[SimpleAudioEngine sharedEngine] pauseBackgroundMusic];
        _darkMask = [CCSprite spriteWithFile:@"darkMask.png"];
        _darkMask.anchorPoint = ccp(0, 0);
        [self addChild:_darkMask z:190];
        _darkMask.opacity = 100;

少し面倒なのが、「同じ面をはじめから」、「タイトル画面へ戻る」機能の実装です。「【cocos2d】パーティクルを表示中にパーティクルバッチノードからRemoveするとクラッシュ!どうするか?」の記事に書きましたが、表示中のパーティクルのオブジェクトをParticleBatchNodeからremoveするとクラッシュしてしまうのです。
これを防ぐため、強制的にremoveせずにパーティクルの生成を止め、画面上に残ったパーティクルが消えるのを待ちます。(トランジション中に消えてくれます。)
次のようにパーティクルの生成を止めるために_teminatedというフラグを立てています。パーティクル生成側ではこのフラグを見て、立っているときはパーティクルのオブジェクトを生成しないようにしています。

            // タイトル画面に戻る
            _paused = NO;
            _terminated = YES; //パーティクルの生成を止める
            [self dismissPauseScreen];
            [[CCDirector sharedDirector] resume];
            [LoadingScene startFrom:0]; // 1面からスタート
            [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.5 scene:[TitleScene node] withColor:ccBLACK]];