parcel + phinaで簡単ゲーム開発環境構築 その2
前回、導入部分のみ書きました。
本記事では早速開発環境を構築していきたいと思います。
最小構成
目標
はじめに最小構成を作成します。
以下の画面が表示されるのを目標にします。
サンプルコードは以下にあるので詳しい内容は以下のリポジトリから直接確認してください。
構築方法
アプリケーションの作成
まず、プロジェクトフォルダを作成してnpmの初期化を行います。
$ mkdir sample-project $ cd sample-project $ npm init ##### 以下は入力例です ##### This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (code) sample-project version: (1.0.0) description: sample project for parcel and phina.js entry point: (index.js) test command: git repository: keywords: author: license: (ISC) MIT About to write to /xxxxxx/xxxxxx/sample-project/package.json: { "name": "sample-project", "version": "1.0.0", "description": "sample project for parcel and phina.js", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "MIT" } Is this OK? (yes) yes
次に parcel と phina.js をインストールします。
$ npm i parcel --save-dev $ npm i phina.js --save
作業用ディレクトリを作成して、index.html
を作成します。
$ mkdir src $ touch src/index.html
作成した index.html
に以下のコードを書きます。
<!DOCTYPE html> <html lang=ja> <head> <meta charset="utf-8"> <meta http-equiv=X-UA-Compatible content="IE=edge"> <meta name=viewport content="width=device-width,initial-scale=1"> <title>Parcel + Phina.js sample</title> </head> <body> <script src="index.js"></script> </body> </html>
次に index.js
を作業ディレクトリに作成します。
この index.js
にメインのコードを書いていきます。
// phina.jsを有効化 <--- (1) import 'phina.js' phina.globalize() // メインシーン定義 <--- (2) phina.define('MainScene', { superClass: 'DisplayScene', init() { this.superInit() // 背景色指定 this.backgroundColor = 'gray' // スプライト作成・表示 this.label = Label({ text: 'Hello Parcel + Phina.js', fill: 'white', x: this.gridX.center(), y: this.gridY.center() }).addChildTo(this) } }) // アプリ実行 <--- (3) phina.main(() => { const app = GameApp({ startLabel: 'main' }) app.run() })
これで「Hello Parcel + Phina.js」という文字が画面に表示されます。
上のコードを部分ごとに解説していきます。
まず、(1)
の箇所で phina.js
を読み込んで有効化しています。
これは必ず始めに書かないと GameApp
などでエラーになるので注意してください。
(2)
の部分で MainScene
を定義しています。
phina.js では普通の js と異なるクラス定義方法を取っています。
ここでは画面に「Hello Parcel + Phina.js」という文字を表示させる処理を書いています。
本記事では phina.js 自体の細かい説明は省かせて頂きます。
(3)
の部分でアプリを実行させています。
今回は MainScene
から起動させたいので、startlabel: 'main'
を定義しています。
実行
では、実際に確認してみましょう。
npx parcel src/index.html
でビルドしてください。
今回は parcel をローカルインストールしたので、実行させるには npx
をつける必要があります。
$ npx parcel src/index.html Server running at http://localhost:1234 ✨ Built in 3.16s.
ビルドが完了したら、http://localhost:1234
にブラウザでアクセスしてください。
上記のように表示されたら完了です。
ビルドされたファイルはdist
ディレクトリ以下の出力されます。
js
や map
ファイルにつく数字はランダムなので別の数字になっていても問題ありません。
$ ls -l dist/ total 1864 -rw-r--r-- 1 musashi staff 342 8 22 16:49 index.html -rw-r--r-- 1 musashi staff 398898 8 22 16:49 src.86dd6973.js -rw-r--r-- 1 musashi staff 483932 8 22 16:49 src.86dd6973.map
ランダム数字で問題ないか確認してみましょう。
src/index.html
では index.js
を読み込む箇所を <script src="index.js"></script>
と記載しています。
一方 dist/index.html
では <script src="/src.86dd6973.js"></script>
に書き換わっています。
なので、ビルド後も index.js
は正しくインポートされます。
これで開発環境は整いました。
すごい簡単ですよね?私もそう思います。
正直これで開発環境の構築は終わってしまうのですが……私が開発する時に構成について紹介します。
おすすめ構成
この構成は私がおすすめというか、自分んがよく使っている構成について説明していきます。
必ずしもこの構成にする必要はありません。あくまで私の一例です。
目標
以下の画面が表示されるのを目標にします。
サンプルコードは以下にあるので詳しくはそちらを確認してください。
構成の解説
ディレクトリ構成
src
ディレクトリ以下は以下のようになります。
. ├── GameClass │ ├── MainScene.js │ ├── PixcelSrite.js │ └── index.js ├── assets │ └── parcelPhina.png ├── config.js ├── index.html └── index.js
各ファイルとその役割は以下のようになります。
ディレクトリ名・ファイル名 | 用途 |
---|---|
GameClass | ゲームクラスを定義するフォルダです。 簡単なゲームでもそれなりの量のクラスを作るのでクラスごとにフォルダを分けています。 必要があればさらに階層を設けていいと思います。 |
assets | アセットデータを配置するディレクトリです。 必要があればさらに階層を設けていいと思います。 |
config.js | ゲーム内の設定やアセットデータを定義します。 設定はマジックナンバーを避けたり、ハードコーディングを避けるに使用します。 |
index.html | エントリーポイントとなるファイルです。 最小構成と全く同じ内容です。 |
index.js | 最小構成と異なっています。 詳細に関しては後ほど説明します。 |
クラス定義
ゲームで使用するクラスは GameClass
ディレクトリ以下に定義します。
例えば MainScene.js
は以下のように定義してます。
// メインシーン定義 export default { superClass: 'DisplayScene', init() { this.superInit() // 背景色指定 this.backgroundColor = 'gray' // スプライト作成・表示 this.parcelPhina = PixcelSprite('parcelPhina') .setPosition(this.gridX.center(), this.gridY.center() - 50) .setScale(7) .addChildTo(this) // ラベル作成・表示 this.label = Label({ text: 'Hello Parcel + Phina.js', fill: 'white', x: this.gridX.center(), y: this.gridY.center() + 200 }).addChildTo(this) } }
phina.define()
の第二引数に当たる object のみ記述しています。
各クラスファイルで phina.define()
を使って定義する方法もあるとは思いますが、少なくとも私が試した限り上手く出来ませんでした。
phina にクラスと登録するのは別の場所で行なっています。
GameClass
内で定義したクラスを GameClass/index.js
で一つのオブジェクトにまとめます。
import MainScene from './MainScene' import PixcelSprite from './PixcelSrite' export default { MainScene, PixcelSprite }
index.js
で GameClass
オブジェクトを元に phina 向けのクラス定義をします。
import GameClass from './GameClass' // *** 省略 *** // クラスを定義 for (const className in GameClass) { phina.define(className, GameClass[className]) }
このような構成にすることで、クラスをファイルごとに分割しながらも効率的に phina にクラスを登録出来ます。
アセットの定義
parcel でビルドする際に、各アセットにランダムな文字列が追加されます。
ランダム文字列付きのアセット名は import xxx from '<assetsのパス>'
のよすると変数xxx
にランダム文字列付きのアセット名が格納されています。
今回の構成では config.js
にアセット関連の定義を行なっています。
config.js
は以下のようなコードになります。
import parcelPhina from './assets/parcelPhina.png' export default { // アセットを定義 assets: { image: { parcelPhina: parcelPhina } } }
定義した物を index.js
で GameApp
に設定をしています。
import config from './config' // *** 省略 *** // アプリを実行 phina.main(() => { const app = GameApp({ startLabel: 'main', assets: config.assets // <-- ここでアセットを読み込ませている }) app.run() })
package.json
よく使うコマンドは scripts
に定義しておきます。
"scripts": { "clear": "rm -rf ./dist && rm -rf ./.cache && rm -rf build", "dev": "parcel src/index.html", "build": "npm run clear && parcel build src/index.html" }
parcel はキャッシュに関連して正しくビルドが出来ない場合があります。
なので、npm run clear
で dist
、.cache
、build
ディレクトリを消せるようにしておきます。
上手くビルド出来ない時などに実行します。
ビルドする際は必ずキャッシュをクリアしてます。
ビルドする際、出力先のパスを指定しないと dist
へ出力されるので -d build
のオプションをつけて出力先ディレクトリを開発用と分けておきましょう。
その他
今回のサンプルで PixelSrite
というクラスを作成しています。
これはドット絵をスプライトで表示させる時、拡大してもアンチエリアスを無効にするクラスです。
実行
開発する際は npm run dev
を実行します。
問題がなければビルドが完了するので、ブラウザで http://localhost:1234
を開いてください。
ファイルを編集したら、自動でビルド・ブラウザをリロードされます。
ビルドする際は npm run build
を実行します。
ビルドが走り、生成物は build
ディレクトリへ出力されます。
これは次の章で web に公開する際に使います。
まとめ
最小構成とおすすめの構成の2種類を紹介しました。
おすすめの構成はあまり作り込みすぎず、使いやすさを考えてみました。
これで開発環境は整いました。
次の記事では web への公開方法について説明していきます。