Closed17

【作業ログ】【Phaser】【Typescript】「Making your first Phaser 3 game」

おねいちゃんおねいちゃん

Part1

https://phaser.io/tutorials/making-your-first-phaser-3-game/part1

完了時点のソース

index.html
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<title>Vite + TS + Phaser</title>
	<style>
		body {
			margin: 0;
		}
	</style>
</head>

<body>
	<div id="app"></div>
	<script type="module" src="/src/main.ts"></script>
</body>

</html>
main.ts
import Phaser from 'phaser';
import { MainScene } from './mainScene';

const config: Phaser.Types.Core.GameConfig = {
	type: Phaser.AUTO,
	width: 800,
	height: 600,
	parent: 'app',
	scene: MainScene,
}

new Phaser.Game(config);
MainScene.ts
export class MainScene extends Phaser.Scene {
	constructor() {
		super('main');
	}

	preload() {

	}

	create() {

	}

	update() {

	}
}

実行画面

まだ何もしていないので真っ暗

おねいちゃんおねいちゃん

Part2

https://phaser.io/tutorials/making-your-first-phaser-3-game/part2

あらかじめアセットを用意しておく

完了時点のソース

MainScene.ts
export class MainScene extends Phaser.Scene {
	constructor() {
		super('main');
	}

	preload() {
		// アセット読込
		this.load.image('sky', 'assets/sky.png');
		this.load.image('ground', 'assets/platform.png');
		this.load.image('star', 'assets/star.png');
		this.load.image('bomb', 'assets/bomb.png');
		this.load.spritesheet(
			'dude',
			'assets/dude.png',
			{ frameWidth: 32, frameHeight: 48 });
	}

	create() {
		// 画面サイズが800*600なのでその半分(中心)に配置する
		this.add.image(400, 300, 'sky');
		this.add.image(400, 300, 'star');

		// setOriginでアンカー変更できる
		// this.add.image(0, 0, 'sky').setOrigin(0, 0)

	}

	update() {

	}
}

実行画面

すてきなおそらが表示されました

おねいちゃんおねいちゃん

Part3

https://phaser.io/tutorials/making-your-first-phaser-3-game/part3

完了時点のソース(変更箇所)

MainScene
	create() {
		this.add.image(400, 300, 'sky');
		// 地面の追加
		const platforms = this.physics.add.staticGroup();
		platforms.create(400, 568, 'ground').setScale(2).refreshBody();
		platforms.create(600, 400, 'ground');
		platforms.create(50, 250, 'ground');
		platforms.create(750, 220, 'ground');
	}
main.ts
const config: Phaser.Types.Core.GameConfig = {
	type: Phaser.AUTO,
	width: 800,
	height: 600,
	physics: {
		default: 'arcade',
		arcade: {
			gravity: { y: 300 },
			debug: false
		}
	},
	parent: 'app',
	scene: MainScene,
}

実行画面

地面ができました

おねいちゃんおねいちゃん

Part5

https://phaser.io/tutorials/making-your-first-phaser-3-game/part5

完了時点のソース(変更箇所)

MainScene.ts
create() {
		this.add.image(400, 300, 'sky');

		// 地面の追加(省略)

		// プレイヤーの追加
		const player = this.physics.add.sprite(100, 450, 'dude');
		player.setBounce(0.2);// 跳ね返る設定
		player.setCollideWorldBounds(true); // 画面の枠で衝突するか?

		// アニメーションの追加
		this.anims.create({
			key: 'left',
			frames: this.anims.generateFrameNumbers('dude', { start: 0, end: 3 }),
			frameRate: 10,
			repeat: -1
		});

		this.anims.create({
			key: 'turn',
			frames: [{ key: 'dude', frame: 4 }],
			frameRate: 20
		});

		this.anims.create({
			key: 'right',
			frames: this.anims.generateFrameNumbers('dude', { start: 5, end: 8 }),
			frameRate: 10,
			repeat: -1
		});

	}

実行画面

上からふってきた

おねいちゃんおねいちゃん

Part7

https://phaser.io/tutorials/making-your-first-phaser-3-game/part7

完了時点のソース(変更箇所)

MainScene.ts→main_scene.tsに変更

main_scene.ts
import Phaser from 'phaser';

export class MainScene extends Phaser.Scene {
  // プロパティを追加
	private _cursors!: Phaser.Types.Input.Keyboard.CursorKeys;
	private _player!: Phaser.Types.Physics.Arcade.SpriteWithDynamicBody;

(省略)

	create() {
		this.add.image(400, 300, 'sky');

		// 地面の追加(省略)

		// プレイヤーの追加
		this._player = this.physics.add.sprite(100, 450, 'dude');
		this._player.setBounce(0.2);// 跳ね返る設定
		this._player.setCollideWorldBounds(true); // 他のオブジェクトとの衝突設定?

		// アニメーションの追加(省略)

		// 地面とプレイヤーを衝突させる
		this.physics.add.collider(this._player, platforms);

		// キー入力の取得
		this._cursors = this.input.keyboard.createCursorKeys();

	}

	update() {
		// プレイヤー左右移動
		if (this._cursors?.left.isDown) {
			this._player.setVelocityX(-160);
			this._player.anims.play('left', true);
		} else if (this._cursors.right.isDown) {
			this._player.setVelocityX(160);
			this._player.anims.play('right', true);
		} else {
			this._player.setVelocityX(0);
			this._player.anims.play('turn');
		}

		// 地面に立っていればジャンプできる
		if (this._cursors.up.isDown && this._player.body.touching.down) {
			this._player.setVelocityY(-330);
		}
	}
}

実行画面

プレイヤーが動いた

おねいちゃんおねいちゃん

Part8

https://phaser.io/tutorials/making-your-first-phaser-3-game/part8

完了時点のソース(変更箇所)

main_scene.ts

	create() {
                 (省略)

		// キー入力の取得
		this._cursors = this.input.keyboard.createCursorKeys();

		// 星の追加
		const stars = this.physics.add.group({
			key: 'star',
			repeat: 11,
			setXY: { x: 12, y: 0, stepX: 70 }
		});
		stars.children.iterate((child) => {
			(child as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody).setBounceY(Phaser.Math.FloatBetween(0.4, 0.8)); //いいかんじにバウンド値をばらけさせる
		});
		this.physics.add.collider(stars, platforms);
		this.physics.add.overlap(this._player, stars, this.collectStar, undefined, this);// 衝突検知はするけど跳ね返らない?

	}

	private collectStar(
		player: Phaser.Types.Physics.Arcade.GameObjectWithBody,
		star: Phaser.Types.Physics.Arcade.GameObjectWithBody) {
		(star as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody).disableBody(true, true);
	}

実行画面

星をゲットできるようになった!

おねいちゃんおねいちゃん

Part9

https://phaser.io/tutorials/making-your-first-phaser-3-game/part9

完了時点のソース(変更箇所)

main_scene.ts
import Phaser from 'phaser';

export class MainScene extends Phaser.Scene {
(省略)
	private _score: number = 0;
	private _scoreText!: Phaser.GameObjects.Text;

	create() {
    (省略)
		// スコア表示を追加
		this._scoreText = this.add.text(16, 16, 'score: 0',
			{ fontSize: '32px', color: '#000' });
	}

	private collectStar(
		player: Phaser.Types.Physics.Arcade.GameObjectWithBody,
		star: Phaser.Types.Physics.Arcade.GameObjectWithBody) {
		(star as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody).disableBody(true, true);
     // スコア計算
		this._score += 10;
		this._scoreText.setText(`Score: ${this._score}`);
	}
}

実行画面

星をとるとスコアが増えた!

おねいちゃんおねいちゃん

Part10

https://phaser.io/tutorials/making-your-first-phaser-3-game/part10

完了時点のソース(変更箇所)

main_scene.ts
export class MainScene extends Phaser.Scene {
(省略)
	private _bombs!: Phaser.Physics.Arcade.Group;
	private _isGameOver: boolean = false;
	private _stars!: Phaser.Physics.Arcade.Group;
(省略)
	create() {
    (省略)
		// スコア表示を追加
		this._scoreText = this.add.text(16, 16, 'score: 0',
			{ fontSize: '32px', color: '#000' });

		// 爆弾を追加
		this._bombs = this.physics.add.group();
		this.physics.add.collider(this._bombs, platforms);
		this.physics.add.collider(this._player, this._bombs, this.hitBomb, undefined, this);
	}

	update() {
		// ゲームオーバーなら以降の処理はしない
		if (this._isGameOver) return;
    (省略)
	}

	private collectStar(
		player: Phaser.Types.Physics.Arcade.GameObjectWithBody,
		star: Phaser.Types.Physics.Arcade.GameObjectWithBody) {
		(star as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody).disableBody(true, true);
		this._score += 10;
		this._scoreText.setText(`Score: ${this._score}`);

		if (this._stars.countActive(true) === 0) {
			// 星を全部撮ったら(有効状態の星がなくなったら)
			this._stars.children.iterate((child) => {
				// 星を全て再有効化する
				const dbody = child as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody;
				dbody.enableBody(true, dbody.x, 0, true, true);
			});

			// 爆弾生成する
			const x = (player as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody).x < 400 ?
				Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
			const bomb = this._bombs.create(x, 16, 'bomb');
			bomb.setBounce(1);
			bomb.setCollideWorldBounds(true);
			bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
		}
	}

	private hitBomb(
		player: Phaser.Types.Physics.Arcade.GameObjectWithBody,
		bomb: Phaser.Types.Physics.Arcade.GameObjectWithBody) {

		// 当たったらゲームオーバー
		this.physics.pause();
		(player as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody).setTint(0xff0000);
		(player as Phaser.Types.Physics.Arcade.SpriteWithDynamicBody).anims.play('turn');
		this._isGameOver = true;
	}
}

実行画面

星を全てとるたびに爆弾が降ってくる
爆弾に当たるとゲームオーバー

このスクラップは2023/03/18にクローズされました