どうもです。タドスケです。
スマホだけで作るPhaserゲームも今回でいよいよ完成です。
最後の仕上げに障害物とゲームオーバー処理を入れましょう。
目次
動かしてみる
最後なので全てのコードを載せます。
JSタブに丸ごとコピペしてください。(パスは適宜置き換えてください)
//---------------------------
// グローバル変数
//---------------------------
// ゲーム設定
var config = {
type: Phaser.AUTO,
width: 300,
height: 400,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
// ゲーム本体
var game = new Phaser.Game(config);
// プレイヤー
var player;
// 足場グループ
var platforms;
// 星グループ
var stars;
// ボムグループ
var bombs;
// スコア
var score = 0;
// スコア表示テキスト
var scoreText;
//---------------------------
// ロード
//---------------------------
function preload ()
{
this.load.image('star', 'img/20210425182551.png');
this.load.image('sky', 'img/20210425175550.png');
this.load.image('ground', 'img/20210425175525.png');
this.load.image('bomb', 'img/20210425182611.png');
this.load.spritesheet('dude',
'img/20210425182602.png',
{ frameWidth: 32, frameHeight: 48 }
);
}
//---------------------------
// 足場の生成
//---------------------------
function createPlatforms(scene)
{
// 足場グループを生成
platforms = scene.physics.add.staticGroup();
// 足場1
platforms.create(300, 150, 'ground').setScale(0.5).refreshBody();
// 足場2
platforms.create(0, 250, 'ground').setScale(0.5).refreshBody();
// 地面
platforms.create(150, 385, 'ground');
}
//---------------------------
// プレイヤーの生成
//---------------------------
function createPlayer(scene)
{
// プレイヤー
player = scene.physics.add.sprite(150, 200, 'dude');
player.setBounce(0.2);
player.setCollideWorldBounds(true);
// プレイヤーアニメーション:正面
scene.anims.create({
key: 'turn',
frameRate: 20,
frames:
[{ key: 'dude', frame: 4 }],
});
// プレイヤーアニメーション:左
scene.anims.create({
key: 'left',
frameRate: 10,
repeat: -1,
frames:
scene.anims.generateFrameNumbers(
'dude',
{ start: 0, end: 3 }
),
});
// プレイヤーアニメーション:右
scene.anims.create({
key: 'right',
frameRate: 10,
repeat: -1,
frames:
scene.anims.generateFrameNumbers(
'dude',
{ start: 5, end: 8 }
),
});
}
//---------------------------
// 星の生成
//---------------------------
function createStars(scene)
{
// グループの生成
stars = scene.physics.add.group({
key: 'star',
repeat: 4,
setXY: { x: 13, y: 0, stepX: 68 }
});
// 星の物理挙動を設定
stars.children.iterate(function (child) {
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
});
}
//---------------------------
// 新しいボムを生成する
//---------------------------
function createNewBomb()
{
// プレイヤーから離れたランダムな場所
var x = (player.x < 150)
? Phaser.Math.Between(150, 300)
: Phaser.Math.Between(0, 150);
// ボムの生成
var bomb = bombs.create(x, 16, 'bomb');
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
}
//---------------------------
// 衝突の設定
//---------------------------
function colliderSetting(scene)
{
// プレイヤーと星
scene.physics.add.collider(stars, platforms);
scene.physics.add.overlap(player, stars, collectStar, null, this);
// プレイヤーと足場
scene.physics.add.collider(player, platforms);
// ボムと足場
scene.physics.add.collider(bombs, platforms);
// プレイヤーとボム
scene.physics.add.collider(player, bombs, hitBomb, null, scene);
}
//---------------------------
// プレイヤーと星の衝突時に呼ばれる
//---------------------------
function collectStar (player, star)
{
// 星を消す
star.disableBody(true, true);
// スコアを加える
score += 10;
scoreText.setText('Score: ' + score);
// 全ての星を取った時
if (stars.countActive(true) === 0)
{
// 星を復活させる
stars.children.iterate(function (child) {
child.enableBody(true, child.x, 0, true, true);
});
createNewBomb();
}
}
//---------------------------
// プレイヤーとボムの衝突時に呼ばれる
//---------------------------
function hitBomb (player, bomb)
{
this.physics.pause();
player.setTint(0xff0000);
player.anims.play('turn');
gameOver = true;
}
//---------------------------
// ロード後処理
//---------------------------
function create ()
{
// this = scene
// マウス入力を有効にする
this.input.mouse.capture = true
// 背景
this.add.image(300, 300, 'sky');
// スコア
scoreText = this.add.text(16, 16, 'Score: 0', { fontSize: '32px', fill: '#000' });
// 足場
createPlatforms(this);
// プレイヤー
createPlayer(this);
// 星
createStars(this);
// ボム
bombs = this.physics.add.group();
// 衝突の設定
colliderSetting(this);
}
//---------------------------
// 更新処理
//---------------------------
function update ()
{
var pointer = this.input.activePointer;
if(pointer.isDown)
{
// 左移動
if(pointer.x < 150)
{
player.setVelocityX(-160);
player.anims.play('left',true);
}
// 右移動
else if(150 < pointer.x)
{
player.setVelocityX(160);
player.anims.play('right',true);
}
// ジャンプ
if(pointer.y < 200 && player.body.touching.down)
{
player.setVelocityY(-330);
}
}
// 停止
else
{
player.setVelocityX(0);
player.anims.play('turn');
}
}
実行して⭐️を全部取ると、ランダムな位置にボムが現れます。
ボムに触れるとゲームオーバーです。
※やり直すにはページをリロードしてください。
コード解説
create
bombs = this.physics.add.group();
ボムは途中から出てくるので、createのタイミングではグループだけ作っています。
衝突設定
// ボムと足場
scene.physics.add.collider(bombs, platforms);
// プレイヤーとボム
scene.physics.add.collider(player, bombs, hitBomb, null, scene);
足場との判定は他と同じです。
プレイヤーと当たった際にはhitBomb関数が呼ばれるように設定しています。
hitBomb内でscene要素を使えるように、最後の引数にsceneを渡しています。
プレイヤー衝突時の処理
function hitBomb (player, bomb)
{
this.physics.pause();
player.setTint(0xff0000);
player.anims.play('turn');
gameOver = true;
}
physics.pauseを呼ぶと物理計算が止まるので、ゲーム内のキャラクターやボムなどの動きも止まります。
setTintではプレイヤーの色を赤くしています(0xff0000は赤色)。
ボム・⭐️の生成
if (stars.countActive(true) === 0)
⭐️を取るとアクティブではなくなるのを利用して、アクティブな⭐️がなくなったら全ての⭐️を取ったとみなしています。
enableBodyを呼ぶことで⭐️が復活します。
同じタイミングでボムも生成しています。
ボムは画面内のプレイヤーからある程度離れた地点にランダムで出現します。
⭐️を全て取るたびに一個ずつボムが増えていくので、ゲームの難易度も上がっていきます。
まとめ
Part10まで及んだPhaserのチュートリアルもこれで終了となります。
ただチュートリアルを動かすだけではなく、記事としてコード解説を書くことで理解も深まった気がします。
今後は自分の作りたいゲームを決めて、都度ドキュメントを見ながら作っていこうかと思います。
コメント
コメント一覧 (4件)
[…] どうもです。タドスケです。 PCに向かえる時間が取れないけど、それでもスキマ時間にスマホでゲームを作りたい! ということで、前回の記事で調査した スマホアプリ:JS Anywhereゲームライブラリ:Phaser … 【Part8】スマホで作るPhaserゲーム〜チュートリアル編〜 【Part10(最終回)】スマホで作るPhaserゲーム〜チュートリアル編〜 […]
[…] […]
[…] […]
[…] PlayCanvasでスプライト機能を使ってみました。 参考にしたのはこちらのチュートリアルです。 完成品 できあがったのがこちらです。 WASDキーでキャラクターが移動します。 ※キャ… 【Part8】スマホで作るPhaserゲーム〜チュートリアル編〜 【Part10(最終回)】スマホで作るPhaserゲーム〜チュートリアル編〜 […]