JavaScript
Phaser

Phaser 3 でゲーム作成入門

0. 対象

  • JavaScript はそこそこわかる人
  • phaser って何?くらいの人

1. Phaser 基本のキ

  • 世界で一番人気のゲームエンジン(範囲:JavaScript + 2D + オープンソース)

    • github
      • スター数: 21357 凄すぎだろ...
    • 商用OK
      • MIT ライセンス
    • 高速
      • WebGLで動作, クライアントが対応してなければ Canvas にフォールバック
  • 特別な開発環境不要

    • CDN から 1 JSファイルをロードするだけで使える
    • npm でもインストールも可能
    • 好きなエディタを使える
    • TypeScript の定義ファイルも同梱

2. チュートリアルから学ぶ Phaser 3

Phaser のことを本当に何も知らなくても、そこそこ面白いゲームが作れる公式のチュートリアルがある。これをいじって、Phaser 3の概要をつかむ。

2.1. 動くもので遊ぶ

チュートリアル本編

ゲーム概要

  • キャラを矢印で操作して、画面にちりばめられたコインを集める
  • コインを集めるほど、爆弾が増える
  • 爆弾にあたると死ぬ
  • ハイスコアを競う
  • たった200 行のHTML ファイル

デプロイ方法

  • Webサーバ上に、配布された zip を展開して、part10.html にアクセスするだけ
    • 要調整 = 画像ファイルの取得先の変更
    • this.load.image(... で始まる5箇所のパスを変更
    • 私は /games/part10.html でアクセスするので、画像ファイルの取得先は、/game/assets/sky.png などに設定した

スクリーンショット

無題.png

2.2 要点を押さえる

全10回のチュートリアル を読めばいいのだけれど、超特急でレビューする。

全体構造

Phaser.Game オブジェクトを作った瞬間にゲームが開始する。オブジェクト作成時に渡すコンフィグの中に、ゲームの各種情報を詰め込んでおく。

// コンフィグ
var config = {
    //...(前略)
    scene: {
        preload: preload, // 以下に定義する preload 関数をセットする
        create: create, // 以下に定義する create 関数をセットする
        update: update // 以下に定義する update 関数をセットする
    }
};

// ゲーム開始!!!
var game = new Phaser.Game(config);

// ゲーム開始前に呼び出される関数定義
function preload ()
{ // アセット(画像とか)の取得を行う

// ゲーム開始時に呼び出される関数
function create ()
{ // 背景を設定したり、プレイヤーの初期配置をしたりする

// ゲーム進行時に呼び出される関数
function update ()
{ // 矢印が押されたら、プレイヤーを動かしたり、衝突判定からのロジックを回したり

ゲーム開始前に呼び出される preload() の中で画像等のアセットをロードする。ゲーム開始時に呼び出される create() の中で背景・地面・プレイヤーの初期設定や、衝突判定などを詰め込む。update() の中で、ゲーム進行時における画面・状態の更新を行うロジックを記載する。

■入力のハンドリング

ユーザからの入力イベントは、カーソルというオブジェクトで表される。

// カーソルの作成 @ create()
cursors = this.input.keyboard.createCursorKeys();

こんな風に使う

// extracted from update()
    if (cursors.left.isDown)
    {
        player.setVelocityX(-160);
        player.anims.play('left', true);
    }

■物理エンジン

プレイヤーはジャンプしたら自由落下するし、地面とぶつかったら少しだけ跳ねる。このように物理現象に支配されるモノは、 Dynamic と呼ばれ、地面などのように、固定されているものは、Static と呼ばれる。

// 地面を三つ作る。 extracted from create()
platforms = this.physics.add.staticGroup();
platforms.create(600, 400, 'ground');
platforms.create(50, 250, 'ground');
platforms.create(750, 220, 'ground');

// プレイヤーを初期配置する。
player = this.physics.add.sprite(100, 450, 'dude');
player.setBounce(0.2); // ぶつかったらちょっと跳ねる
player.setCollideWorldBounds(true); // 画面枠にぶつかっちゃう

オブジェクト同士の衝突判定、また衝突時のコールバックの設定がゲームのキモになる。どのオブジェクト同士が衝突するかを明示的に宣言する。

// 地面は、コイン・プレイヤー・爆弾と衝突する
this.physics.add.collider(player, platforms);
this.physics.add.collider(stars, platforms);
this.physics.add.collider(bombs, platforms);

// プレイヤーとコインが重なれば、collectStar() を呼び出す
this.physics.add.overlap(player, stars, collectStar, null, this);

// プレイヤーと爆弾が重なれば、hitBomb() を呼び出す
this.physics.add.collider(player, bombs, hitBomb, null, this);

世界よ、とまれ。

// from hitBomb()
this.physics.pause();

■用語

  • キャンバスとシーン

800 x 600 のブラウザで表示される部分はキャンバスと呼ばれるが、ゲーム作成時には目に見えない部分にもオブジェクトを配置したりできる。この無限に広がる部分をシーンと呼ぶ。

  • 座標系

左上の角の座標が、(0, 0) になる。原点から右にずれるのがプラスの方向で、左にずれるのがマイナスの方向。原点から下にずれるのがプラスの方向で、上にずれるのがマイナスの方向。

// 左ボタンが押されたらX方向にマイナスの速度を設定
  if (cursors.left.isDown) {
    player.setVelocityX(-160);
    player.anims.play('left', true);


// 上ボタンが押されたら、Y方向の速度をマイナスに設定する
  if (cursors.up.isDown && player.body.touching.down) {
    player.setVelocityY(-330);
  }

3. 次のステップ

コミュニティのチュートリアル https://phaser.io/learn/community-tutorials

が良いと思う。Phase 2 とPhase 3でAPIがかなり違うので、あまり古いのは見ない方が良い。