Edited at

【連載】ジャンプ&ランゲームを作ろう(3) 床の生成・カメラ移動に伴うスクロール・非可視床の削除


はじめに

こちらのQiitaは勝手連載「ジャンプ&ランゲームを作ろう」になります。

初回の記事はこちらです。

【連載】ジャンプ&ランゲームを作ろう(1) プロジェクト作成

※お断り※ 毎日お昼休みに15分程度で執筆していおり細切れになりましてすみません


まずは

プラットフォーム(床)のブロックを自動で作成し続けます。

ブロックは移動しないがカメラが移動します。

カメラ外に外れたブロックは削除します。


先に結論

今回のソースコードはMain.tsのみいじっています。Main.tsの完成像はこちらです。

https://github.com/liberapp-inc/h5g-qiita-jump-and-run/blob/1b50e73244528bb126427ca24efb7789075acfea/src/Main.ts


ゲームの初期化

カメラの対象となるゲーム内オブジェクトを格納するコンテナオブジェクトworldを作成します。

まずはカメラの位置を 0に初期化します。


Main.ts

    protected createGameScene(): void {

this.world = new egret.DisplayObjectContainer();
this.addChild(this.world);

this.lastDrawnX = - this.width / 2;
this.cameraX = 0;
this.updateCamera();
}



ゲームループのスタート

ENTER_FRAMEイベントを処理するenterFrameメソッドがゲームのループ処理になります。


Main.ts

    private async runGame() {

:
this.addEventListener(egret.Event.ENTER_FRAME, this.enterFrame, this);
}

各フレームでは

1. カメラの位置を右に移動させます。

2. 次にカメラの視界の先のブロックを生成します。

4. カメラの位置にあわせてすべてのオブジェクトの表示位置を更新します。

5. カメラの視界から外れたブロックを削除します。


Main.ts

    private enterFrame(t:number):boolean {

this.cameraX += 1; // 1
this.generateNewBlocks(); // 2
this.updateCamera(); // 3
this.eraseBlocksOutOfCamera(); // 4
return true;
}


カメラの視界の先のブロックを生成

generationBorderはカメラの位置からちょうど画面幅分右先の位置です。最後に作成したブロックの右端をthis.lastDrawnXで管理しています。最後に生成したブロックの右端がgenerationBorderより左まで来た場合にブロックを生成します。

this.colorsで生成するブロックの色のパターンを管理しています。this.generationIndexで次のブロックがどのパターンになるかを管理しています。

ブロックのサイズはPLATFORM_BLOCK_WIDTHで、ブロックの世界座標から右方向に幅PLATFORM_BLOCK_WIDTH、下方向に幅PLATFORM_BLOCK_WIDTHのブロックを生成します。


Main.ts

    private generateNewBlocks() {

const generationBorder = this.cameraX + this.width;
while(this.lastDrawnX < generationBorder) {
const p = new egret.Shape();
p.x = this.lastDrawnX;
p.y = 0;
this.lastDrawnX += PLATFORM_BLOCK_WIDTH;

const c = this.colors[this.generationIndex];
p.graphics.beginFill(c);
p.graphics.drawRect(0, 0, PLATFORM_BLOCK_WIDTH,PLATFORM_BLOCK_WIDTH);
p.graphics.endFill();
this.world.addChild(p);
this.platforms.push(p);
this.generationIndex = (this.generationIndex + 1) % 2;
}
}



カメラ位置に応じて表示の更新

カメラ位置に連動するオブジェクトはすべてthis.worldオブジェクトの子として生成しています。そのためにthis.worldの画面座標を調整するだけですべてのオブジェクトの位置が更新されます。


Main.ts

    private updateCamera(): void {

this.world.x = this.width / 2 - this.cameraX;
this.world.y = this.height / 2;
}


最後に

画面の左端(カメラの位置から画面幅の半分だけ左)より左側にある非可視のオブジェクトをすべて削除します。


Main.ts

    private eraseBlocksOutOfCamera() {

const visibilityLeft = this.cameraX - this.width / 2;
this.platforms = this.platforms.filter((p) => {
const r = p.x + p.width;
const inCamera = visibilityLeft <= r;
if (!inCamera) {
this.world.removeChild(p);
}
return inCamera;
});
}