Vueが好き?モダンフロントエンドが好き?ゲームを作ってみたい?
だったらPhavuerを使おう!!!!
Phavuerとは何か
Phavuerは、JavaScriptの超人気2Dゲームエンジン「Phaser 4」と「Vue 3」を統合したラッパーライブラリです。
Phaserが提供するGameObject(画像や矩形やテキストといったゲームを作り上げるパーツ)をVueコンポーネントとして扱い、Vueのテンプレートやリアクティビティを使ってゲームを開発できます。
簡単に言うと、ゲーム開発の世界へモダンフロントエンドの考えを持ち込んだライブラリです。
Phavuerのメリット
Vueテンプレートで画面を組み立てられる
Phavuerでは、PhaserのGameObjectがVueコンポーネントに、GameObjectのプロパティがpropsに対応します。
たとえば、ゲーム全体は<Game>、シーンは<Scene>、画面上のコンテナは<Container>、四角形や文字は<Rectangle>や<Text>として記述します。
<Game :config="gameConfig">
<Scene name="MainScene">
<Container :x="100" :y="100">
<Rectangle
:width="120"
:height="40"
:fillColor="0x42b883"
/>
<Text
:x="60"
:y="20"
:origin="0.5"
text="START"
/>
</Container>
</Scene>
</Game>
タグの入れ子がゲーム画面の親子関係を表すため、画面がどのような構造になっているのかをコードから読み取りやすくなります。
状態に応じた表示を宣言的に書ける
ゲームは、HP、所持アイテム、会話、選択肢、メニューなど、プレイ中に状態に応じて表示が頻繁に変わります。
素のPhaserでは、状態が変わるたびに、それを表示しているすべてのGameObjectを手続き的に更新する必要があります。
たとえばHPが変化したら、HPの数値、HPゲージの幅、ゲームオーバー表示などを、それぞれ忘れずに書き換えなければなりません。
表示箇所が増えるほど更新処理はあちこちへ散らばりやすくなり、一部の更新を忘れて表示が食い違う不具合も起きやすくなります。
Phavuerでは、状態と表示の関係をVueテンプレートへ宣言的に記述できます。
<Text :text="`HP: ${player.hp}`" />
<Rectangle :width="200 * (player.hp / player.maxHp)" :height="12" />
<Text v-if="player.hp <= 0" text="GAME OVER" />
あとはplayer.hpを変更するだけで、Vueのリアクティビティによって、それを参照するすべての表示が自動的に追従します。
HPを変更する処理はHPの値だけに集中でき、個々の表示へ更新命令を送る必要がありません。
実装がメチャクチャ楽になるだけでなく、更新漏れによる不具合も減らせます。
コンポーネントとして分割・再利用できる
ゲーム固有の見た目や振る舞いを、propsやemitsを持つVueコンポーネントとして分割できます。
たとえば、汎用的なボタンをGameButton.vueとして作っておけば、ラベルや座標、クリック時の処理を変えながら再利用できます。複雑な画面も、小さな部品を組み合わせて構築できます。
Vueアプリケーションで普段利用しているコンポーネント設計の知識を、ゲーム開発にも持ち込めるのが大きな利点です。
追加と削除をVueに任せられる
GameObjectをシーンやコンテナへ追加する処理や、不要になったGameObjectを破棄する処理は、PhavuerがVueのライフサイクルとPhaserの間を橋渡しします。
<Enemy v-if="enemy.isAlive" :x="enemy.x" :y="enemy.y" />
表示条件をv-ifで記述すれば、その条件に応じたGameObjectの追加と削除をPhavuerへ任せられます。配列をv-forで描画する場合も同様です。
シーンへの追加、親子関係の管理、破棄といった定型的なViewロジックを減らし、ゲーム固有の状態やルールへ集中できます。
UIをHTML/CSSで実装することもできる
ゲーム本体はPhaserのCanvasへ描画しつつ、メニューや設定画面、テキスト入力などのUIだけをHTML/CSSで実装することもできます。
Phavuerのコンポーネントも通常のHTML要素も、同じVueテンプレートとリアクティブな状態を使って記述できます。
そのため、Canvas側とHTML側で別々の処理系や状態管理を用意する必要がありません。
<div class="game">
<Game :config="gameConfig">
<Scene name="MainScene">
<Player :hp="player.hp" />
</Scene>
</Game>
<div class="hud">
<span>HP: {{ player.hp }}</span>
<button @click="openMenu = true">
メニュー
</button>
</div>
</div>
ゲームらしい描画はPhaserに任せ、フォームや複雑なレイアウト、アクセシビリティが重要なUIにはHTML/CSSを使う、といった役割分担が自然にできます。
AI時代のゲーム開発とも相性がいい
Phavuerは、シンプルなTypeScriptプロジェクトとして動作するため、AIエージェントとの親和性が高いです。
GUIエディタや特殊な実行環境に依存しないため、AIエージェントがコードを検索し、変更を加えやすいです。
AIエージェントとの統合が急速に進むVS Codeの恩恵も受けられます。
Steamなどでの配信も可能
Phavuerで作ったゲームはWebで公開するだけでなく、Electronでデスクトップアプリ化して、Steamなどで配信することもできます。
electron-builderを使えば、Vueで作ったゲームをWindows、macOS、Linux向けの配布可能なアプリとしてパッケージングできます。
さらにsteamworks.jsを組み合わせることで、実績やクラウドセーブなどのSteam機能にも対応可能です。
簡単なゲームを作ってみる
セットアップは、ViteでVueプロジェクト立ち上げ、Phavuerを追加するだけ!
$ npm create vite@latest # Vue+TypeScriptを選ぼう
$ npm install phavuer
まずはGameとSceneでゲームの舞台を用意します。その中に、ドキュメントを見ながら目的に合ったコンポーネントを配置していきます。
<Game :config="{ width: 640, height: 480 }">
<Scene name="MainScene">
<Image texture="player" :x="320" :y="400" />
<Container :x="20" :y="20">
<Rectangle :width="160" :height="40" :fillColor="0x222222" />
<Text :x="10" :y="10" text="SCORE: 100" />
</Container>
</Scene>
</Game>
画像ならImage、文字ならText、図形ならRectangle、複数の要素をまとめるならContainer、という具合です。
時間経過に伴うゲーム進行の処理は、Scene配下に置くコンポーネントでonPreUpdateなどへ記述します。
Enemy.vue
<script setup lang="ts">
import { Image, onPreUpdate } from 'phavuer'
import { ref } from 'vue'
const y = ref(0)
onPreUpdate((_time, delta) => {
y.value += 0.1 * delta // 毎フレーム下方向へ進む
})
</script>
<template>
<Image texture="enemy" :y="y" />
</template>
サンプルゲーム
Phavuerで作られたゲーム
ネムルへの手紙
プレイヤーが書いた手紙をAIが読み取り、その内容に応じて物語が分岐するADVです。
リブラの見た夢
「リブラの見た夢」は、二人の少女が臨死体験の世界を彷徨う夢探索アドベンチャーゲームです。
おわりに
AIエージェントによってゲーム開発がより手軽になった今こそ、Phavuerで何か作ってみよう!




