FC2ブログ

Entries

cocos2d 初心者ガイド レッスン2の巻

レッスン1に引き続き、cocos2d 初心者ガイドレッスン2を日本語に訳しながら読んで行きます。

ここでは、スプライトを自動でまたはタッチイベントで動かすようです。

----------------------------------
<初心者ガイドレッスン1 初心者ガイドレッスン3>

始めてのゲーム

このレッスンのゴール

このレッスンでは、新規の cocos2d プロジェクト作成、スプライトの追加、自動かタッチベントでのスプライトの動作の解説を行います。

このレッスンの前に、基本コンセプトレッスン1を理解しておいてください。

初期のセットアップ

まずは、レッスン1で説明した通りに、“cocos2d-(version) Application” テンプレートで新規プロジェクトを作成してみましょう。

レッスン1で作ったものを、どこかへ手動でコピーし使用してもよいです。プロジェクトを実行すると、 “Hello World” という文字が期待通りに表示されることを確かめてみてください。

その際に、cocos2d のスプラッシュスクリーンが起動され、ホームボタンを押してデモンストレーションプロジェクトを終了すると、cocos2d のアイコンがホーム画面に追加されていることも確認してみてください。

スプラッシュスクリーンやアイコンは、プロジェクト内(ディスク上)の Resources フォルダの中に特別な名前で保存されています。

これらの画像を自分自身で用意した画像に差し替えたい時のため、そして背景やスプライトのための画像を追加するときのために、Resources フォルダと画像の場所を確認しておいてください。

(今すぐにスプラッシュやアイコンの画像を差し替えたいのであれば、同じ名前で同じ大きさの画像ファイルに差し替えてください。そうすれば、表示される画像が差し替えたものとなります。)


ここで、スプライトとして使用するための画像を一つ追加しておきます。ディスク上のプロジェクト内の Resources フォルダ直下に seeker.png という名前でこの画像を保存してください。

保存後に、Xcode の Resources フォルダを確認してみてください。

seeker.png は、Resources フォルダ内に存在していないと思います。ディスク上に追加しただけでは、自動的に Xcode のプロジェクトには追加されません。




ファインダーから Xcode プロジェクトの Resources フォルダ内にファイルをドラッグアンドドロップしてください。

いくつかのオプションが選択された状態のダイアログが表示されるので、それらのチェックを全部外して、追加ボタンをクリックしてください。

Xcode のプロジェクトの Resources フォルダ内に、seeker.png が追加されています。

このレッスンでは、ふたつのスプライトが必要ですが、画像を用意する時間を省くため、2個目のスプライトとして、すでにプロジェクトに入ってる Icon.png を使用することにします。


スプライトの構築

さっそく、Classes フォルダを開いてみてください。代表的な二つのクラス、HelloWorldScene と Lesson1AppDelegate (新しいテンプレートの場合は、代わりに HelloWorldLayer と AppDelegate)の、4つのファイルがフォルダ内にあると思います。

今回のレッスンでは、すべてのコーディングを HelloWorldScene.m におこなっていきますので、このファイルを選択してください。

まずは、何かしらの方法で我々が定義したスプライトを参照する手段が必要となってきます。

ひとつのメソッド内のみで参照すればいいのであれば、ローカル変数を使用すればよいのですが、これは稀なケースです。

タッチイベントに応じたスプライトの動作を行ったり、何らかのロジックに基づいてフレームごとにスプライトを動かしたり、そういったことを実現するためには、様々なメソッドからスプライトが参照可能である必要があります。

様々なメソッドからスプライトを参照するために、いくつかの方法があります。

今回ご紹介しているプロジェクト内のほとんどのデモンストレーションやテストのコード内では、スプライトをレイヤーに追加するときに割り当てる tag を使用しています。

tag を使用すれば、後ほど getChildByTag メソッドを使用してそのスプライトを参照することができます。

この方法は安全ですが、内部的には余計な処理を行っているので、何百個ものスプライトを使用するような大きなゲームではパフォーマンス上の問題が発生する場合があります。

そこで、より簡単な方法を使用することとします。この方法は、シーンのインスタンスを一度にひとつしか実行させない(通常ではあまり考えられない状態ですが)限り安全です。

スプライトの参照としてファイルスコープの変数を宣言します。ファイルの先頭の #import 行の下に、以下の2行を追加してください。

CCSprite *seeker1;
CCSprite *cocosGuy;


スプライトオブジェクトが参照できる2つの CCSprite のポインタを宣言しました。

宣言しただけでは何も参照していないので、次に、init メソッドで参照するものを定義します。

ファイル内から、-(id) init メソッドを見付け出してください。

このメソッドは、シーン(正確に言うと、シーンの中のメインレイヤ)が構築されているときに自動で呼び出されます。

if 文と 最後の return self は、常套句です。ここでは特に気にしなくてもよいでしょう。

変更は、if ブロック内におこなっていきます。

Hello World ラベルの構築は不要なので、最初から記述されている if ブロック内のコードは削除して、かわりに以下のコードを追加してください。

        // seeker スプライトを構築して初期化し、レイヤーに追加
seeker1 = [CCSprite spriteWithFile: @"seeker.png"];
seeker1.position = ccp( 50, 100 );
[self addChild:seeker1];
 
// cocos2d 君も同様に。アプリのアイコンを再利用します。
cocosGuy = [CCSprite spriteWithFile: @"Icon.png"];
cocosGuy.position = ccp( 200, 300 );
[self addChild:cocosGuy];


それぞれのスプライトのために3行ずつ追加しました。

最初の行は、spriteWithFile を呼び出して、このプロジェクトに追加されている画像でCCSprite オブジェクトを構築しています。

次の行は、スクリーン上のスプライトの中心位置を設定しています。ccp (cocos2d point の略) マクロを使って、X 、Y 座標で2次元位置(技術的には CGPoint 構造体)を作成しています。

メモ:cocos2d では、X 座標はスクリーンの左から始まって右側に向かって増加します。Y座標はスクリーンの下から始まって上に向かって増加します。

最後に、ぞれぞれのスプライトの3行目で、addChild メソッドを呼び出し、新しく作ったスプライトをレイヤーに追加しています。

コードを保存(cmd-s)して、実行(cmd-R)してみましょう。

結果は下のようになります。



動かし方

スクリーンにスプライトを表示する方法が理解できたと思います。

次は、これらのスプライトを動かしてみたいと思います。

スプライトを動かすには、基本的な2つの方法があります。

1.Action を使用して、決まった時間で、ターゲットとなる位置へ自動的にスプライトを動かす方法
または
2.ゲーム中定期的に呼び出されるメソッド内でスプライトを自分で動かす方法

まずは、2番目の方法を試してみます。

HelloWorldScene.m の init メソッドに変更を加えていきます。

先ほど、if ブロック内のコードでスプライトを構築しました。

その時行ったスプライトの初期化にもうひとステップ加えます。定期的に呼び出されるコールバック関数のスケジューリングをおこないます。

if ブロック内の [self addChild: cocosGuy]; の真下に以下のコードを追加してください。

        // フレームごとに繰り返し呼ばれるコールバックをスケジュール
[self schedule:@selector(nextFrame:)];


このコードでは、自身(HelloWorldのCCLayer)の schedule メソッドに対して、ひとつの引数を持つ nextFrame メソッドのアドレスを指定し、呼び出しています。

nextFrame メソッドは存在しないので作成しましょう。

HelloWorldScene.m の中でメソッド内以外の空行、例えば init メソッドの最終行と dealloc メソッドの開始行の間に、次のコードを挿入してください。

- (void) nextFrame:(ccTime)dt {
seeker1.position = ccp( seeker1.position.x + 100*dt, seeker1.position.y );
if (seeker1.position.x > 480+32) {
seeker1.position = ccp( -32, seeker1.position.y );
}
}


このように記述することにより、cocos2d ライブラリはアニメーションの各フレーム毎に nextFrame イベントを呼び出すようになります。

この定期的に呼び出されるイベントはいろいろなことを実施する機会を与えてくれます。例えば、スプライトの動作の実行、衝突の判定、物理的なモデルの更新、新しい敵の生成、不要なスプライトの削除などを行うことができます。

今回のレッスンでは、このイベント内で seeker のスプライトを動作させます。

position プロパティに新しい値を設定することで、スプライトを動作させることができます。(position の .x と .y に値を設定してもスプライトは動作しません。新しく point オブジェクトを指定する必要があります。)

イベント内では、スプライトの position プロパティの x の値に 100 * dt 加算しています 。こうすることで、スプライトは一秒間に 100 ピクセル動作します。

dtを使用してスプライトの移動する量を決めて動かしたい速さ(ピクセル毎秒)を指定する方法はとても有用です。
もしフレームレートが少しだけ変化した場合でも、一定のスピードを保ったまま動作させることができるからです。

それから、スプライトがスクリーンから、はみ出たかどうかを確認する必要があります。

iPhone がランドスケープモードと仮定し、横幅を 480 ピクセルとします。コードをより汎用的にしたい場合は、
[[CCDirector sharedDirector] winSize] で実際のスクリーンサイズを取得してください。

ただここでは、480 ピクセルとしておきます。そして、480 ピクセルにスプライトの半分のサイズの 32 を加算します。

こうしておくことで、スプライトの中心が 480 + 32 を超えた時にスプライト全体が右側から完全に見えなくなるので、そうなった場合に、スプライトの位置を左側から完全に見えなくなる -32 に再設定します。

タッチへの応答

イベントのハンドリングはコールバック関数のスケジューリングと少しの違いがあります。

イベントは、スクリーンにタッチした場合や、加速度計の読み込みなどに応じて呼び出されます。

これらのイベントはすでに定義されており、タッチイベントに関しては場合は、標準的な方法と目的が定められた方法の2つの異なる導入法があります。

これらふたつのタッチイベントの詳しい解説は、タッチデリゲート を参照してください。

このレッスンでは、目的の定められたデリゲート(target delegate)を使用します。そのためには、少しコードを変更する必要があります。

まず最初に、ファイルの上部、HelloWorldScreen.h をインポートしているコードの真下に以下のコードを追加してください。

#import "CCTouchDispatcher.h"


init メソッドの下あたりに、新しくメソッドを追加します。CCLayer に、標準的な方法(standard) ではなく 目的が定められた方法(targeted)を使用することを伝えるために以下のように記述します。、

-(void) registerWithTouchDispatcher
{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}


つぎに、再び init メソッドに戻って、if ブロックの終了直前に、タッチイベントを登録するための以下の行を追加してください。

    self.isTouchEnabled = YES;


追加したら、さらに新しいメソッドの場所を探してください。先ほど追加した nextFrame メソッドの真下あたりとなるでしょう。

それぞれのタッチイベントの目的の定められた(targeted)イベントセットを使用するので、少なくとも CCTouchBegan メソッドを実装擦る必要があります。

CCTouchBegan で YES を返却し、タッチディスパッチャに、このタッチに対するイベントを要求することを伝えましょう。

- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
return YES;
}


こうすることで、同じタッチで別のメソッドが呼び出されるようになります。タッチが終了した場所にふたつめのスプライトを移動するコードを追加します。

- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint location = [self convertTouchToNodeSpace: touch];
 
[cocosGuy stopAllActions];
[cocosGuy runAction: [CCMoveTo actionWithDuration:1 position:location]];
}



convertTouchToNodeSpace は、以下の動作を行います。

1.まず、ビュー内でのタッチの位置の取得します。
2.次に、CCDirector にその位置を GL 座標すなわち、描画のために使用するのと同じ座標系に変換するよう依頼します。(ポートレートとランドスケープ間の変換等を行います。)
3.最後に、それらの GL 座標を CCLayer のためのノードスペースに変換する。あまり大差はありませんが。

その後、我々は以下のことを行います。

1.次に、cocosGuy スプライトが直前までに行っているすべてのアクションを停止します。
2.最後に、1秒かけてスプライトをタッチ位置に移動させる新しいアクションを開始する。

メモ:アクションを使用しているので、nextFrame にこのスプライトを移動するためのコードを記述する必要はありません。

アプリを実行して実際に試してみましょう。指がスクリーンから離れたら(シュミレータでは、マウスのボタンをはなしたら)、ちょうどその位置に cocos2d のアイコンが疾走してくるでしょう。その間ずっと、シーカーロボットはスクリーン上を駆け回っているでしょう。

では、準備ができ次第、レッスン3に進みましょう。

---------------------------

いちいち nextFrame メソッドに動作を書かないでも、Action の定義で スプライトが動かせることがわかった。

次回はこれを試していきます。

じっちゃん、オラワクワクしてきた。
スポンサード リンク

コメント

コメントの投稿

コメントの投稿

管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://miyachikantaro.blog.fc2.com/tb.php/8-a316a786
この記事にトラックバックする(FC2ブログユーザー)

Appendix

出演ゲーム

みやちかんたろうの大冒険

↑インストールはこちらから
予告編

21面デモ

ステージ作成

検索フォーム

訪問者

Apple製品紹介

Apple MacBook Air 1.6GHz 13.3インチ MB003J/A

中古価格
¥59,800から
(2013/1/24 06:45時点)

QRコード

QR

メールフォーム

名前:
メール:
件名:
本文:

Extra

プロフィール

みやちかんたろう

Author:みやちかんたろう
種別:きいろいねこ
年齢:10歳
性別:オス
趣味:昆虫採集
twitter:@gatsupport

※このサイトはリンクフリーです。ご自由にリンクしてください。相互リンクもじゃんじゃん募集中です!!

最新記事

最新コメント

最新トラックバック

月別アーカイブ