自キャラをランダムにロックオンする

kobold2dのサンプルに入っていたParallax-Side-Scrollerを改造して自分のゲームにしている件です。
前回、敵キャラを自キャラへ誘導する仕組みを作りました。
今回は、自キャラをランダムにロックオンする仕組みを敵キャラに実装します。

今回も過去に作ったFlashと同じ要領でやれば簡単と考えていましたが、クラス間での配列の共有と共有した配列のプロパティの取り出し方でドツボにハマりました。
何か試しては戻り、試しては戻りの繰り返しで、危うく挫折するところでした。トライ&エラーには、XcodeのSnapShotが大活躍でした。

段取りとしては、自キャラの入った配列を用意して、その配列からランダムに自キャラを取り出し、その自キャラの位置を前回やった敵キャラへの誘導に使うことになります。

まず、自キャラを管理しているBaseCacheクラスのヘッダで配列(_friendliesとしました)を宣言します。
NSArrayではなくCCArrayにしたのは、CCArrayの方が高速に配列内を検索できるらしいからです。

ここで躓いたのは、配列を共有するための方法です。
ググったところ、こちらのページ(「Smart Gadget Laboratory」)で見つけました。
でも、この@propertyと@synthesizeを使ってクラス間で変数を共有する方法って「Xcode4ではじめる Objective-Cプログラミング」という参考本で過去に勉強済みのことでした。本で勉強した時は分かったつもりでいましたが、やはり実戦で使わないとスキルは身に付かないですね。

次に、BaseCache.mのinitBaseメソッドで、BaseEntityインスタンスの生成と同時に配列を使います。

ここで今回最も躓いた箇所が、配列の初期化です。ヘッダファイルで宣言していたので、いきなり追加できると勘違いしていたのですが、Objective-Cでは初期化しないとオブジェクトを配列に加えてくれないみたいですね。。。
これに気付かず、何度NSLogで配列の中身を見ても空っぽで時間を無駄にしました。
ActionScriptなら、以下で終わっちゃうんですけどね。

これで、自キャラを配列に格納しました。

さて、次は敵キャラであるEnemyEntityクラスで目標をランダムに選びます。
まず、EnemyEntity.hで標的のX座標を格納するtargetBaseXを宣言します。これは前回のEnemyEntity.mのupdateメソッドで、標的のX座標をとりあえず的にCGFloat targetX=200としていたのを、ちゃんとクラス内のローカル変数にしたものです。

あと、前回までと変えたところは、敵キャラの降下速度と誘導速度をそれぞれfloat ySpeed、float xSpeedとして変数で持つことにしました。

次に、EnemyEntity.mで先ほどのtargetXを@synthesizeに加え、spawnメソッド内で標的を決めます。
ここで躓いたのは、共有する時にインスタンスを使う必要があったことです。ただ、これはParallax-Side-Scrollerの様々なところで使われていた方法なので、すぐに分かりました。

先ほどBaseCacheクラスで生成した配列をEnemyEntitiyクラスで使うため、baseCacheクラスのインスタンスを作ります。
それから、配列から取り出した自キャラ(オブジェクト)を入れるためのmyTargetインスタンスを作ります。
配列friendliesの長さを取得して、ランダムな整数を発生させる際に使います。乱数の発生方法は、「iPhoneアプリ開発の虎の巻」で見つけました
私の1作目のアプリ「とけいであそぶ」を作った時にも大変お世話になったサイトです。
ただ、このままだとワンパターンな乱数になってしまうので、後でチューニングするつもりです。
配列friendliesの長さ分のランダムな整数を、そのまま配列から抽出するさいのobjectAtIndexのキーとして使います。取り出した自キャラ(オブジェクト)は、先ほどのmyTargetインスタンスに格納し、myTargetのプロパティからposition.xと取り出して、ヘッダで宣言したtargetBaseXに格納します。

あとは前回の誘導ロジックへ渡して終わりです。

130613 0002
ワラワラワラ〜っと敵キャラが出現するようになりました。

動画で見るとこんな感じになります。

少し、動きがゲームっぽくなって、テンション上がってきました!

次は、敵キャラが自キャラに衝突したかの当たり判定をやってみます。