第7回 ゲーム開始、スコア表示
前回の記事では、Tiledの基本的な作成とPhaserでの描画ができるようになりました。
今回の記事では、ゲームの開始ボタン、スコア表示、Tiledでのオブジェクト配置をして、最低限のゲームの要素すべて実装します。
ゲーム開始ボタンの作成
最初にゲーム開始ボタンとスコア作成ですが、Phaserでも作れるのですが、htmlで作成ほうが、私は早いので、htmlで作成した例を載せます。この実装はデザインにこだわりが無ければそれほど難しくはないです。仕組みは簡単で、メニューとスコア表示をゲームを描画するcanvasの上に表示させゲーム開始したら、ゲーム開始ボタンを消すだけとしています。
<div id="game_frame">
<div id="canvas"></div>
<div id="score"></div>
<div id="menu">
<h1>ゲーム開発学習サンプル</h1>
<button id="startButton" class="button-simple" onclick="startGame()">開始ボタン</button>
</div>
</div>
* {
text-align: center;
}
#menu {
display: fixed;
width: 100vw;
height: 100vh;
align-items: center;
justify-content: center;
border-radius: 5px;
}
#game_frame {
display: block;
position: relative;
width: 100vw;
height: 90vh;
margin: 0;
padding: 0;
}
#canvas,
#menu,
#score {
display: fiexed;
position: absolute;
width: 100vw;
height: 90vh;
margin: 0;
padding: 0;
}
#score {
opacity: 0.8;
}
h1 {
background-color: rgb(194, 224, 250);
}
#menu {
background-image: url('../assets/SampleA.png');
background-size: cover;
/* 背景画像を要素全体に広げます */
background-position: center center;
/* 画像の中央に配置します */
}
実際に作成したサンプルの画像です。
ゲーム開始ボタンの押す処理の実装
「開始ボタン」を押したときの処理を以下に示します。
メニュー画面を消すとともに、Phaserの関数 game.scene.start('Scene') を呼び出します。この関数を呼び出すと、ゲームを最初から開始します。
// ゲーム開始のための関数
function startGame() {
// ボタンを非表示にする
document.getElementById("menu").style.display = "none";
// ゲームを開始
game.scene.start('Scene');
}
Tiledでバックグランドレイヤーとオブジェクトを追加
前回のTiledのMAPから、今回新たにオブジェクトとバックグランドを追加します。
オブジェクトは、プレイヤーがアイテムを取得するときの要素などを配置するとき使用します。またバックグランドは背景とかを表示するとき使用します。
あと、今回MAPの画面を縦長に大きく拡張しました。なぜかと言うと、スマフォで表示させたとき、縦長のサイズのほうがスマフォに適しているためです。
まずMAPのレイヤーに地面を配置します。
次に、バググランドレイヤーに森を配置します。
最後に、オブジェクトに宝石を配置し、名前をつけます。
Tiledで作成したデータをPhaserで実装
実装上の重要ポイントを説明します。
宝石(jewel)の画像データ読み込み
宝石(jewel)の画像データ読み込みを読み込みます。ここが私は最初理解できませんでした。タイルセットのデータを指定して読み取ると思ったのですが、予め用意した宝石(jewel)の画像データを個別に指定しないといけないようです。
// ゲーム開始前の事前準備(アセットのロード)を行うメソッド
preload() {
:
this.load.image('jewel', 'assets/tiled/maneo-2/tile/tile_0067.png');
:
}
レイヤーの作成と優先順位
Tiledで作成したMAPと背景のオブジェクトを作成します。ここでポイントは、setLayerでmaneo_layerを現在の有効レイヤーにすることです。これをやらないと、MAPとプレイヤーの物理演算が対象でなくなり、プレイヤーがMAPを超えて落ちていきます。(衝突しない)
create() {
// ゲームのマップとタイルを設定
Game.map = this.make.tilemap({ key: 'map' });
Game.tiles = Game.map.addTilesetImage('maneo_tileset');
// 背景色を指定(ここでは空色に設定)
this.cameras.main.setBackgroundColor('#87CEEB');
// マップレイヤーの作成と設定
const layer = Game.map.createLayer('maneo_layer', Game.tiles, 0, 0);
layer.setScale(map_scale);
// 背景レイヤーの作成と設定
const bg = Game.map.createLayer('background', Game.tiles, 0, 0);
bg.setScale(map_scale);
// レイヤーの順序を設定
Game.map.setLayer('maneo_layer');
:
オブジェクトの取得と配置
Tiledで作成したオブジェクトを取得して、スプライトとして配置します。また、スプラウトはグループに追加してします。
create() {
:
// オブジェクトレイヤーの取得と設定
const objectLayer = Game.map.getObjectLayer('maneo_object');
Game.objectLayer = this.physics.add.group();
// オブジェクトの生成
objectLayer.objects.forEach(object => {
const { gid, name, x, y, width, height } = object;
const sprite = this.physics.add.sprite(x, y, name);
console.log(sprite);
// スプライトのサイズを設定
sprite.setDisplaySize(width, height);
// オブジェクトを固定(物理的な衝突の対象外に)に設定
sprite.body.setImmovable(true);
// オブジェクトをグループに追加
Game.objectLayer.add(sprite);
// レイヤーとオブジェクトの衝突を設定
this.physics.add.collider(sprite, layer);
});
:
プレイヤーとMAP、オブジェクトの衝突検出を実装します。setCollisionで衝突するタイル番号を指定しますが、今回は範囲指定しています。
また、バクグランドは衝突させないので、空データをセットしています。
オブジェクトの衝突は、overlapで設定しています。以下の例では、オブジェクトとプレイヤーが衝突すると、音の鳴らし、オブジェクトを破棄しています。
create() {
:
// 衝突するタイルの設定
const startTileIndex = 1;
const endTileIndex = 152;
const collidableTiles = Array.from({ length: endTileIndex - startTileIndex + 1 }, (_, index) => startTileIndex + index);
Game.map.setCollision(collidableTiles, true, 'maneo_layer');
// 背景のレイヤーに対してコリジョンを設定しない
Game.map.setCollision([], false, 'background');
// プレイヤーと物体の衝突処理
this.physics.add.overlap(Game.player, Game.objectLayer, (player, objectSprite) => {
// 衝突したオブジェクトを削除
objectSprite.destroy();
// コインサウンドを再生
this.playCoinSound();
// スコアを増やす
Game.score += 1;
displayScore();
});
:
実際のサンプル
以上、実装すべて完了すると、以下のような動きになります。
今回で、ゲームらしくなってきたので、次回からさらにゲームらしくするために、いろいろ試していきたいと思います。お付き合いいただければ幸いです。
実際のサンプルゲーム(https://honda-workshop.com/works/phaser/maneo-2.html)