2024/01/06

第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)

プロフィール

管理者 HONDA

福島県出身

ITで商売を効率化したいが、ITが苦手、分からない方是非ご相談ください。50過ぎの「おっさん」です。そのほうが話しやすい方はお勧めします。

カテゴリ

美容

ファッション

お酒


西暦和暦干支年齢対応表


設定

時計表示

都道府県

ブックマーク1

ブックマーク2

ブックマーク3

プライバシーポリシー

はじめに

HONDA WORK SHOPでは、ご利用のユーザ様個人情報の取り扱いに細心の注意を払っております。

また当サイトではアフィリエイトプログラムを利用しております。

第三者配信事業者(Amazonアソシエイト、楽天アフィリエイト、A8.net)がCookie を使用して、サイト利用者が当サイトや他のサイトに過去にアクセスした際の情報に基づいて広告を配信します。

Google が広告 Cookie を使用することにより、サイト利用者が当サイトや他のサイトにアクセスした際の情報に基づいて、Google やそのパートナーは適切な広告をサイト利用者に対して表示します。

広告設定でパーソナライズ広告を無効にすることができます。

Cookieの利用について

Cookieは、当サイトや他サイトへのアクセスに関する情報が含まれており、多くのサイトで利用者に有益な機能を提供する目的で使用されています。

Cookieには、サイト利用者の個人情報(氏名、住所、メールアドレス、電話番号)は一切含まれません。

アクセス解析ツールについて

当サイトでは、アクセス解析ツール「Google Analytics」を利用しています。

「Google Analytics」はトラフィックデータの収集のためにCookieを使用しています。

このトラフィックデータは匿名で収集されており、個人を特定するものではありません。

この機能はCookieを無効にすることで収集を拒否することができますので、ご利用のブラウザ設定をご確認のうえ、拒否設定を行ってください。

本ポリシーの変更

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。