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

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

【Objective-C, cocos2d】BGMの切り替えを並列処理して画面のコマ落ちを防ぐ方法

前回、
【cocos2d】テクスチャーをキャッシュに先読みしてゲーム中に画面が一瞬止まるのを防ぐ方法 - 夏までにiPhone アプリつくってみっか!
で画面のコマ落ちを防ぐためにテクスチャーの先読みを行いました。
これで完璧か!とテストをしてみると、改善はされているものの、ボスが登場するときにまだ一瞬だけ画面がカクついています。

スペハリではボスの登場と共にBGMがボス戦用のものに切り替わるのですが、どうやらその部分で処理落ちしているようです。試しにBGMの切り替えを止めてみるとスムーズに動きます。

cocos2dに付いてくるCocos Denshionではあらかじめ音楽データを読み込むpreloadBackgroundMusicという機能がありますので当然ながらそれは使っています。

[[SimpleAudioEngine sharedEngine] preloadBackgroundMusic:@"squila.m4a"];

それでもコマ落ちするということは、BGMの切り替え自体が結構時間がかかる処理なのかもしれません。

そういう重い処理はゲームループとは別のスレッドで並列処理することで画面表示への影響を防ぐ事ができます。並列処理などやった事ありませんので早速いろいろと調べてみます。
どうやら、並列処理を手軽に実現するにはNSOperationとかNSOperationQueueクラスが使えそうです。
しかもNSOperationQueueクラスのaddOperationWithBlock:メソッドを使えばNSOperationのサブクラスを作ったりする手間も一切掛けずに並列処理できます。

並列処理によるBGMの切り替えはこうなりました。思ったより100倍簡単でした。

NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
    [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"squila.m4a"];
}];

早速テストしてみると、常時60fpsを維持できていました!

これにて、偽スペハリの1面が無事完成となります。
2面以降は作りません。
次回作のプロトタイプとして偽スペハリを作り始めて約2ヶ月、とりあえずスペースハリアーをそのままiPhoneで再現できるくらいの機能を持つプログラムができました。
来年からはゲームキャラクターや面をデザインして行くというあまり得意でないジャンルの作業が待ち構えていますが、宣言した4月1日のリリースに向けてボチボチ作って行きたいと思います。
https://itunes.apple.com/jp/app/travelshooting-jp-toraberushutingu/id917570972?mt=8&uo=4&at=10laCt
https://itunes.apple.com/jp/app/beecluster-wu-liaono-zongsukurorushutingugemu/id663801586?mt=8&uo=4&at=10laCt