今回は、キャラクターの動きに合わせて背景を動かします。
これまでSpriteBuilderで配置した主人公や背景を、ついに動かします。
今回はcocos2dのコードも書きます。といっても普通に開発する場合と比べるとコードを書く量はかなり少ないですが。
地面の無限ループなども実装します。
前回まで
主人公を動かす
SpriteBuilderで設定したオブジェクトとXcodeで書くコードをつなげます。
主人公のノードを選択し、右カラムの左から2番目のタブを選択肢ます。
この画面でXcode上のコードと接続します。プルダウンで「Doc root var」を選択して、右には「_hero」と記述します。
保存をしてPublishボタン(左上のボタン)を押した後、Xcodeに移ります。
[code language=”objc” title=”MainScene.m”]
#import "MainScene.h"
static const CGFloat scrollSpeed = 80.f; // スクロール速度の定数を定義
@implementation MainScene{
CCSprite *_hero; // SpriteBuilderと接続する主人公のスプライト
}
// アップデート
– (void)update:(CCTime)delta {
// 主人公のX座標を右に進める
_hero.position = ccp(_hero.position.x + delta * scrollSpeed, _hero.position.y);
}
@end
[/code]
これで、主人公が動くようになります。
早速ビルドしてみましょう。
起動と同時に主人公が右に飛んでいきます。
カメラの設定
続いて、主人公の動きに合わせてカメラが動くように設定します。
ただcocos2dにはカメラという機能はないので、主人公に合わせて地面などが動くように設定します。
まずSpriteBuilderのMainScene.ccbを開き、CCPhysicsNodeを選択します。
続いてCode ConnectionsタブでDoc root varを選択し、_physicsNodeと記述します。
保存してPublishしたらSpriteBuilder側はこれで完了。
続いてはXcodeにコードを書いていきます。
@implementationの部分に以下のように追記します。これでSpriteBuilderの_physicsNodeとXcode側の接続が完了しました。
[code language=”objc” title=”MainScene.m”]
@implementation MainScene{
CCSprite *_hero; // SpriteBuilderと接続する主人公のスプライト
CCPhysicsNode *_physicsNode; // SpriteBuilderと接続する全画面の物理ノード
}
[/code]
続いて、画面と主人公の位置が連動するようにコードを書きます。
[code language=”objc” title=”MainScene.m”]
// アップデート
– (void)update:(CCTime)delta {
// 主人公のX座標を右に進める
_hero.position = ccp(_hero.position.x + delta * scrollSpeed, _hero.position.y);
// 主人公の座標に合わせて_physicsNode全体を逆方向(左方向)に動かす
_physicsNode.position = ccp(_physicsNode.position.x – (scrollSpeed *delta), _physicsNode.position.y);
}
@end
[/code]
これで画面が主人公を追いかけるようになりました。
まだ地面をループさせていないので、しばらくすると奈落へ落ちていってしまいますが。
地面をループさせる
主人公が地獄に落ちないよう、地面をループさせます。
まずはスプライトビルダーの表示設定を変更して、画面外も見られるようにしましょう。
Document > Stage Border > None
と選択し、画面境界の表示を消します。
これで画面外にスプライトを設置できるようになりました。
続いて、2番目の地面を画面上に設置します。ArtPackからground.pngをドラッグアンドドロップし、その後画像の位置を変更します。座標を(348, 12)に、アンカーポイントのX座標を0にします。
また、このときCCPhysicsNodeの子ノードに入っていない場合は、下画面でドラッグアンドドロップして、groundがCCPhysicsNodeの中に入っているようにしましょう。
続いて、物理演算を可能にします。
Enable physicsにチェックを入れ、Staticを選択します。このあたりは1つ目の地面を設定した時と同じですね。
次に、ループを実装するため、connectionを設定する必要があります。
最初に設定したground.pngのスプライトに「_ground1」、さきほど設定した方に「_ground2」と設定します。
これでSpriteBuilderは完了。保存してPublishしたら、Xcode側に移ります。
[code language=”objc” title=”MainScene.m”]
#import "MainScene.h"
static const CGFloat scrollSpeed = 80.f; // スクロール速度の定数を定義
@implementation MainScene{
CCSprite *_hero; // SpriteBuilderと接続する主人公のスプライト
CCPhysicsNode *_physicsNode; // SpriteBuilderと接続する全画面の物理ノード
CCNode *_ground1; // SpriteBuilderと接続する地面その1
CCNode *_ground2; // SpriteBuilderと接続する地面その2
NSArray *_grounds; // 地面ループ処理用のArray
}
// CCBファイルからロード
– (void)didLoadFromCCB {
// 地面その1とその2を配列に追加
_grounds = @[_ground1, _ground2];
}
// アップデート
– (void)update:(CCTime)delta {
// 主人公のX座標を右に進める
_hero.position = ccp(_hero.position.x + delta * scrollSpeed, _hero.position.y);
// 主人公の座標に合わせて_physicsNode全体を逆方向(左方向)に動かす
_physicsNode.position = ccp(_physicsNode.position.x – (scrollSpeed *delta), _physicsNode.position.y);
// 地面をループさせる
for (CCNode *ground in _grounds) {
// 地面のワールド座標を取得
CGPoint groundWorldPosition = [_physicsNode convertToWorldSpace:ground.position];
// 地面のスクリーン城の位置を取得
CGPoint groundScreenPosition = [self convertToNodeSpace:groundWorldPosition];
// ひとつの地面が画面の左端から完全に外れたら、それを右に移動させる。
if (groundScreenPosition.x <= (-1 * ground.contentSize.width)) {
ground.position = ccp(ground.position.x + 2 * ground.contentSize.width, ground.position.y);
}
}
}
@end
[/code]
これで地面が永遠につづくようになりました。
次回は画面をタッチして主人公を飛ばします。