phaserでブラウザゲームつくり001

phaser
nullkara
nullkara

おはようございます。ぬるからです。
今回は環境構築~ブラウザ上で動かす(webpackを使って)
までをしています。


phaserとは?

私も詳しくは知りません> <
多分ですが、JavaScriptでゲームを作る機能(2D画像の描画など)を提供するAPIだと思います。

Phaser - A fast, fun and free open source HTML5 game framework
Desktop and Mobile HTML5 game framework. A fast, free and fun open source framework for Canvas and WebGL powered browser games.

公式サイトに行けば、サンプルゲームなども置いています。

環境

Linux(ubuntu)で環境構築しています。
RedHat系の場合、少しコマンドが違う場合があります。
また、Windowsの場合は大きく異なってくると思います。

インストール作業

sudo apt install nodejs npm

でnode.jsとnpmを取得します。
npmはNode Package Managerの略でnode.jsのパッケージ管理ソフトになっています。
今回使うphaserもnpm経由で落とします。

注意点ですが、aptで取得した場合node.jsのバージョンが古い場合があります。

npm -v

などをして、確認しましょう。
最新でない場合は、以下手順で最新版をインストールします。

sudo npm install n -g
sudo n stable
sudo apt purge -y nodejs npm

nパッケージと呼ばれるものからインストールすることにより、最新版が入るそうです。
その後はpurgeでaptのnode.jsを削除します。

ぬるから
ぬるから

ぬるからの躓きポイントその1です。
バージョンが古いと、この先の手順でエラーが起きます。
しっかりと最新版にしておきましょう。

プロジェクト作成

プロジェクトファイル(作業場所)作って、そこに移動します。
原則、場所の指定が無い限りはプロジェクトファイル直下で行ってください。

npm init

でnpmの初期化を行います。対話型のコマンドですが、内容はエンターで飛ばして問題なしです。(少なくとも起動はします。)
※initの結果、実行したファイルにjsonのファイルができるのですが、そこに対話型の結果が記載されます。

npm i -D phaser typescript webpack webpack-cli webpack-dev-server ts-loader html-webpack-plugin copy-webpack-plugin

phaser(今回主役のAPI)、typescript(JavaScriptの後継型?今回はtsでコーディングする)、webpack(ローカルでphaserを動かすために使う)をインストールします。

Did you name your project the sameのようなエラーが発生する場合、initでできたjsonファイルの中に記載されているnameの値と、パッケージ名が衝突している可能性があります。jsonファイルの方を直接書き換えることにより動くようになります。

tsconfig.json、webpack.config.jsを作成し、srcディレクトリを作成します。
srcディレクトリの中にはindex.htmlとindex.tsを置きます。
今回、起動テストとして下記のqiitaのものを使いました。

TypeScriptを使ってノベルゲームを作ろう - Qiita
こちらはQiita夏祭り2020の「〇〇(言語)のみを使って、今△△(アプリ)を作るとしたら」というテーマに沿って投稿した記事です。 完成イメージ 0. はじめに この章は読み飛ばして「1. 環境構築」に進んでも問...

tsconfig.json

{
  "compilerOptions": {
    "strict": true,
    "target": "es5",            // ES5準拠のコードを出力
    "moduleResolution": "node"  // node方式のモジュール解決方法(node_modulesを探索)
  }
}

webpack.config.js

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const config = {
  mode: 'production',
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html'
    }),
    new CopyWebpackPlugin({
      patterns: [
        { from: 'src/assets/', to: 'assets/' }
      ]
    })
  ],
  resolve: {
    extensions: ['.ts', '.js']
  },
  devServer: {
    contentBase: path.resolve(__dirname, 'dist'),
    port: 3000,
    open: true
  }
};

module.exports = config;

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>PHASER GAME</title>
  <style>
    html, body {
      height: 100%;
      margin: 0;
    }
    #game-app {
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    #game-app > canvas {
      max-width: 100%;
      max-height: 100%;
    }
  </style>
</head>
<body>
  <div id="game-app"></div>
</body>
</html>

index.ts

import * as Phaser from 'phaser';

class MyScene extends Phaser.Scene {
  constructor() {
    // Phaser.Sceneのコンストラクタにはstringかオブジェクト(Phaser.Types.Scenes.SettingsConfig)を渡す
    // 以下は { key: 'myscene' } を渡したのと同義になる
    super('myscene');
  }

  preload() {
    // アセット読み込み
    this.load.image('street', 'assets/street.png');
    this.load.image('robot', 'assets/robot.png');
  }

  create() {
    // 画面中央に画像とテキストを配置
    this.add.image(400, 300, 'street');
    this.add.image(400, 300, 'robot');
    this.add.text(400, 300, 'Hello World', {fontFamily:'arial', fontSize: '60px'}).setOrigin(0.5);
  }
}

const config: Phaser.Types.Core.GameConfig = {
  type: Phaser.AUTO,  // webGLを使うかcanvasを使うかをphaserが自動で判断してくれる
  width: 800,
  height: 600,
  resolution: window.devicePixelRatio,  // Retina環境で多少見た目がよくなる
  parent: 'game-app',  // #game-app内にcanvasを生成
  scene: MyScene
};

new Phaser.Game(config);

.tsを見ての通り、assetsフォルダにあるstreet.pngとrobot.pngを呼ぶような作りになっています。
適当な画像か、参考にしたQiitaに貼ってある画像を保存し、準備しましょう。

起動

npx webpack-dev-server

でローカルホスト3000で起動します。
起動した後、一行目に出てくるURLを叩けばブラウザに画像が表示されるはずです。

何かエラーが出て起動しない場合、以下の2つが考えられます。
・プロジェクトフォルダの直下でnpxを実行していない。
 (厳密にはnpm initをした場所で実行しないといけません)
・webpackのバージョンが新しい
 不思議なことを書いているみたいですが、どうも2020/10/22時点だと、最新版で揃えるとwebpack-dev-serverが動きません。

npm i -D webpack@X.X.X

みたいにすると指定のバージョンでインストールできます。
これで、webpackの各ソフトをダウングレードさせる必要があります。
私の環境は以下のバージョンにしたら動きました。

"webpack": "^5.1.3",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.3.0"
ぬるから
ぬるから

ぬるからの躓きポイントその2です。
stack overflow見まくって発見しました。
最新版で動かないは罠すぎます…。

おわりに

今回はphaserと呼ばれるAPIの起動確認を行いました。
まだ触ったばっかりですが、これで何か作れたらなぁと思っています。

コメント

タイトルとURLをコピーしました