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

プログラミングの魔物

エラー、バグ、仕様変更と戦うブログ

cocos2d アクションとアニメーションの処理

cocos2dで作るiPhone&iPadゲームプログラミング8章

移植してみたものの、サンプルのテクスチャアトラスが不完全で一部のテクスチャが追加されていないようだった。
というわけでテクスチャアトラスをつくり直すか、テクスチャを手動で読み込む必要がありそうだ。
面倒なので元々含まれていた自機の弾で動作確認を行った。
手動でテクスチャを読み込む場合は、テクスチャアトラスで書かれている部分も変更する必要があるので修正しなければならない箇所がいくつかある。テクスチャアトラスと単体テクスチャを透過的に扱えるようなクラスを作れば、素材を追加しながら作る場合に便利かもしれない。

8章はアクションとアニメーションの処理らしい。
敵と弾丸を作成する。

BulletCacheクラス

前の章では弾丸を表示する際にあらかじめキャッシュされたスプライトの表示状態を変更することでオーバーヘッドを減らしていた。
それをカプセル化したのがこのクラスらしい。
敵も同じようにEnemyCacheクラスによってキャッシュする。
※どのプロジェクトでも言えることだが、最初は見やすさを重視して作成し、リファクタリングが必要になった段階でオーバーヘッドとなる部分を修正する。

弾の画面境界判定

screenRectは画面サイズから割り出されたCGRectで、静的変数。

if (CGRectIntersectsRect([self boundingBox], screenRect) == NO){
//画面外に出た場合の処理
}

敵の作成

自機と敵のクラス設計のアプローチ。

  1. 全部同じクラスにする。デメリット・・・1つのオブジェクトに対する拡張が別のオブジェクトに与える影響が大
  2. 共通部分を般化する。デメリット・・・スーパークラスが肥大化する可能性がある。スーパークラスの変更がサブクラスに影響を与える。
  3. コンポーネントシステム。敵や自機の機能をコンポーネント単位に分けて、オブジェクトごとに必要なコンポーネントを導入する。

全部乗せか継承か委譲。委譲は結びつきが弱いので扱いやすい。
クリーンなコードよりも取りあえず動くコード。モチベーション減少の原因は高望み。
このゲームではとりあえず継承とコンポーネントを使うらしい。
arrayWithCapacityではautoreleaseのスコープが切れた時点で破棄されてしまうので、スコープをまたぐ際にはallocする。
しかし、alloc済みの配列にarrayWithCapacityで確保した配列を入れる場合は参照が保持されるので問題はない。

ループ回数が同じでも処理の意図が異なれば、ループを分けた方がいい。
オーバーヘッドはたかが知れている。

コンポーネント

cocos2dにおけるコンポーネントはCCNodeを継承した親(たとえばCCSprite)にaddChildされ、自動的に動作する。
CCNodeに追加された子は親を参照できるので移動なども容易。
CCSpriteBatchNodeにはCCSpriteしか保持できないので、親がSpriteBatchならコンポーネントがテクスチャを利用しなくてもCCSpriteを継承する。

サンプルプログラムStandardShootComponentには、@propertyでcopyしているのでdeallocでreleaseしなければならない処理がある。メンバでプロパティがretainやcopyのオブジェクトはdeallocにreleaseを書いておく。
この辺の動作を考えるとARCが使えるKobold2dはとても便利だなぁ。
しかし、勉強が終わったらKobold2dより先にcocos2d-xを試してみようと思っている。

発射コンポーネント

親が表示されているかを確認し、カウントして、カウントが溜まったら親の位置を基準に弾を生成。

射撃

すべての弾を管理するBulletCacheで自機と敵の当たり判定メソッド実装。
それを利用し、敵のupdateで当たり判定をチェックして倒している。

体力ゲージ

体力ゲージを表示するコンポーネントを作成し、ラスボスに追加している。

参考:

cocos2dで作る iPhone&iPadゲームプログラミング

cocos2dで作る iPhone&iPadゲームプログラミング