iPhone用2Dゲーをやたら簡単につくれるcocos2dの紹介とTips
iPhoneゲー開発日記その3。
今回は、iPhone用の2Dゲーム開発フレームワーク「cocos2d for iPhone」を簡易紹介してみます。
ぼく自身が「つくる前に読んで見たかったなあ」と思う、あえて細かい話は置いといて、雰囲気だけ伝える感じでまとめます。またぼくが作ったゲームで使った機能が中心になります(といっても、基本的なところのみだと思いますが)
その1
個人でかんたんiPhoneゲーム制作、愛と勇気とかしわもち、cocos2dについてのまとめ - カタテマ日記
cocos2d for IPhoneとは
ぼくはもともとObjective-Cは全く知らなかったし、できればObjective-Cは避けたいなあ...と思っていたのですが、いざやってみると、言語周りはあまり苦になりませんでした。
間違いなく、cocos2dがゲーム制作まわりのいろいろを面倒をみてくれたおかげで、本質的でない部分の負荷が減ったおかげだと思います。
ぼくがcocos2dでつくったやつ
「愛と勇気とかしわもち」
http://itunes.apple.com/jp/app/love-mochi/id464653777
いわゆるマッチ系パズルに属すると思います。
cocos2dのインストール
インストールはすぐ終わります(必要なもの:Mac)
http://www.cocos2d-iphone.org/download
最新版(現在は「cocos2d-iphone-1.0.1.tar.gz」)をダウンロードしてどっかに展開。
コマンドラインから以下を実行でインストール完了。
sudo ./install-templates.sh
これだけで、Xcodeのプロジェクト新規作成からcocos2dプロジェクトが作れるようになります。
ビルドするだけで「Hello World!」がうごきます。
縦持ち専用にする
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return NO; // この行を追加 ...
これは任意ですが、単にぼくが作ったゲームではこうしているので、とりあえず。
とりあえず絵を出す
とりあず細かい話は置いておいて、HelloWorldLayer.mのinitメソッドの後ろに足していけば、いろいろ遊べます。
// 160,240の位置に絵を出す CCSprite *s = [CCSprite spriteWithFile:@"Icon.png"]; s.position = ccp(160, 240); [self addChild:s];
必要ならz軸も指定することができます。
CCSprite *s = [CCSprite spriteWithFile:@"Icon.png"]; s.position = ccp(160, 240); [self addChild:s z:1]; // z軸指定
z軸が同じだと、後から追加されたのが上に表示されるっぽいです。
グラフィックは、勝手にキャッシュされて、次回以降は使い回されます。
アクション
「N秒かけてXXする」みたいなのが簡単に処理できます。
3秒かけて(10,20)の位置に移動する。
CCSprite *s = [CCSprite spriteWithFile:@"Icon.png"]; s.position = ccp(160, 240); [self addChild:s z:1]; CCMoveTo *m = [CCMoveTo actionWithDuration:3 position:ccp(10,20)]; [s runAction:m];
3秒かけて、今の位置から見て(100,20)の位置に移動する。
CCSprite *s = [CCSprite spriteWithFile:@"Icon.png"]; s.position = ccp(50, 100); [self addChild:s z:1]; CCMoveBy *m = [CCMoveBy actionWithDuration:3 position:ccp(100,20)]; [s runAction:m];
全体的に〜Toだと最終的な値そのものを指定、〜Byだと今の状態からの相対的な値の指定になります。
他にも、CCScaleTo/CCScaleBy(拡縮)、CCRotateTo/CCRotateBy(回転)、CCFadeTo(透明度)などなど用意されています。
この辺は便利すぎる必須機能で、ぼくが作ったゲームでもあらゆるところで使っています。
アクションの組み合わせ
複数のアクションを順番に実行したり、同時に実行したりするには、CCSpawnやCCSequenceを使います。
CCSprite *s = [CCSprite spriteWithFile:@"Icon.png"]; s.position = ccp(50, 100); [self addChild:s z:1]; 同時に // 1:移動 CCMoveBy *a1 = [CCMoveTo actionWithDuration:3 position:ccp(100,200)]; // 2:5倍に拡大 CCScaleTo *a2 = [CCScaleTo actionWithDuration:2 scale:5]; // ..を、同時に実行 CCSpawn *m = [CCSpawn actions:a1,a2,nil]; [s runAction:m];
順番に
CCSprite *s = [CCSprite spriteWithFile:@"Icon.png"]; s.position = ccp(50, 100); [self addChild:s z:1]; // 1:移動 CCMoveBy *a1 = [CCMoveTo actionWithDuration:3 position:ccp(100,200)]; // 2:5倍に拡大 CCScaleTo *a2 = [CCScaleTo actionWithDuration:2 scale:5]; // ..を、順番に実行 CCSequence *m = [CCSequence actions:a1,a2,nil]; [s runAction:m];
他にも、くりかえすためのCCRepeatとかCCRepeatForeverといったものもあります。
たとえば、タイトルロゴを上下にゆらすのは、上移動アクションとした移動アクションを、CCRepeatForeverしています。
ちょっと変化をつけた動き
ふつうに「N秒かけて(100,200)の位置に移動」みたいに書くと等速運動になりますが、「はじめは勢い良く、最後はゆるやかに」みたいな感じにすることもできます。
そのために使うのは、CCEaseIn/CCEaseOutなど。
CCSprite *s = [CCSprite spriteWithFile:@"Icon.png"]; s.position = ccp(50, 100); [self addChild:s z:1]; CCMoveBy *a1 = [CCMoveTo actionWithDuration:3 position:ccp(200,200)]; //CCEaseIn *m = [CCEaseIn actionWithAction:a1 rate:5]; CCEaseOut *m = [CCEaseOut actionWithAction:a1 rate:5]; [s runAction:m];
詳しくはこのへん。
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:actions_ease
他
アクションと同じ感覚で使える、メソッド実行の「CCCallFuncND」というものがあります。
「アニメーションが終わったときにメソッド実行」みたいなことができるので、「アニメーション終わった後に音をならす」「アニメーション終わった後に解放」などなどが簡単にできます。
音
BGM
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"xxx.mp3"];
効果音としてxxx.wavを鳴らす。
[[SimpleAudioEngine sharedEngine] playEffect:@"xxx.wav"];
画像と同じく音は勝手にキャッシュされるので、2回目移行は高速です。逆に言うと1回目は遅いので、それがまずいときは事前にporeloadしておきます。
[[SimpleAudioEngine sharedEngine] preloadEffect:@"xxx.wav"];
シーン
ここまではガンガン適当にスプライトを追加していっていますが、このまま適当にやっていると破綻します。
複雑なものを分割して管理するために、cocos2dにはレイヤーとかシーン管理機能もあります。
「愛と勇気とかしわもち」では、以下のようなシーンを作りました。
- Title
- Play
- GameOver
- Text
- Movie
で、各シーンに応じてLayerを定義して、Scheneが保持します。
(例:TitleシーンはメインとなるLayerを保持し、そこにキャラクターやらアイコンやらロゴやらを配置する感じです。そして、ヘルプ表示時は別途定義してあるHelpLayerを生成して重ねる)
シーンからシーンへの切り替えは、こんな感じで。
// タイトルシーンへ
TitleScene *nextSchene = [TitleScene node];
[[CCDirector sharedDirector] replaceScene:nextSchene];
他、必須すぎるけどソラで書けないコード
定期的に処理
//0.1秒後度にupdateを実行 [self schedule:@selector(update) interval:0.1];
// 定期更新メソッド - (void) update { // なんかを0.1病後度に実行 }
タッチ
self.isTouchEnabled = YES;
Layerなどで上のコードを書いておいて、以下のようなメソッドを定義しておくと、タッチしたときに勝手にメソッドが実行される。
// タッチ開始 - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:[touch view]]; location = [[CCDirector sharedDirector] convertToGL:location]; ...
// タッチ移動 - (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:[touch view]]; location = [[CCDirector sharedDirector] convertToGL:location]; ...
// タッチ終了 - (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:[touch view]]; location = [[CCDirector sharedDirector] convertToGL:location]; ...
location.x、location.yで、さわったところの位置がとれる。
本作での「さわってからスワイプで回転」する処理は、タッチ開始した位置を覚えておいて、移動イベントで移動距離が一定量を超えたら処理、みたいにわりあい泥臭くやっています。
他、興味深い機能
- パーティクル
- 物理エンジン(Box2D/Chipmunk)
- テキスト表示
- 高速に描画する工夫(CCBatchNode)
ゆにばーさる
デフォルトでと、iPhone/iPad両対応のユニバーサルなアプリになります。
ただ、iPad/iPhone両対応にすると、縮尺などを両者に合わせて開発するのは大変そうだったので「愛と勇気とかしわもち」では、iPhone(&iPod)専用にしています。こうすると、iPadではエミュレータ上での動作になります。
本作はiPadでもエミュレータ上でプレイできますが、拡大するとちょっと画像が荒くなります。近々Retina対応する予定で、そうすればかなり良い感じになる気がします。
まとめ
ここまで紹介した機能だけでも、簡単なゲームなら簡単につくれそうな気がしないでしょうか? はい、実際に、本当に簡単につくれます。
cocos2dには他にもいろいろな機能があるので、本気でつくるかたはぜひ書籍などをあたってみてください。