はじめに
ブラウザで動く2Dゲームを作りたいと思ったことはないでしょうか。個人的には、ちょっとしたミニゲームを作りたくなる時があるんですよね。
そんなとき候補に挙がるのがPhaserというフレームワークです。これ、意外と歴史が長くて、10年以上も開発が続いているんですよ。GitHubのスター数は38,000以上で、コントリビューターは574名。正直なところ、HTML5ゲーム開発フレームワークとしては定番中の定番という位置づけです。
今回は、Phaserがどういうフレームワークなのか、なぜ個人開発にも向いているのかという話をしていきます。
百聞は一見に如かずということで、実際にブラウザ上で動くPhaserのサンプルを用意しました。先に触ってから読み進めたい方はこちらからどうぞ。
Phaserとは
Phaserは、Phaser Studio Inc.が開発・保守しているオープンソースのHTML5ゲームフレームワークです。「fast, free, and fun」を謳っていて、デスクトップとモバイル両方のWebブラウザで動作する2Dゲームが作れます。
現在の最新バージョンは3.90.0で、WebGLとCanvas両方のレンダリングに対応しています。MITライセンスなので、商用利用も問題なしです。
特徴・メリット
1. 圧倒的なドキュメントと学習リソース
Phaserの強みは、なんといっても学習リソースの豊富さです。
- 公式ドキュメント(docs.phaser.io)が充実
- 2,000以上のコード例
- 500ページの無料書籍「Phaser by Example」
30代になって思うのは、新しい技術を学ぶとき、ドキュメントが充実しているかどうかでQOLがだいぶ変わるということです。Phaserはその点で安心感があります。
2. 幅広いフレームワーク対応
React、Vue、Angular、Next.js、Svelte、SolidJSなど、40以上のフロントエンドフレームワークと統合できます。
普段Reactを使っている人なら、既存のスキルを活かしながらゲーム開発ができるわけです。これは時短になりますね。
3. マルチプラットフォーム展開
Webブラウザだけでなく、以下のプラットフォームにも展開可能です。
- YouTube Playables
- Discord Activities
- Twitch Overlays
- iOS / Android(ネイティブアプリ化)
- Steam
一度作ったゲームを複数プラットフォームに展開できるのは、コスパ的にかなり良いです。
4. TypeScript対応
JavaScript だけでなくTypeScriptにも完全対応しています。型があるとIDEの補完が効くので、開発効率が上がるんですよね。
インストール方法
NPMでインストール
npm install phaser
プロジェクトのスキャフォールディング
公式のCLIツールを使うと、プロジェクトのひな形を一発で作成できます。
npm create @phaserjs/game@latest
CDN経由で読み込む
簡単なプロトタイプなら、CDNから直接読み込む方法もあります。
<script src="https://cdn.jsdelivr.net/npm/phaser@3.90.0/dist/phaser.min.js"></script>
バンドルサイズは約335KB(Minified + Gzipped)です。ゲームフレームワークとしては許容範囲かなと思います。
Phaserのサンプルを動かす
説明を読む前に、実際にPhaserを触ってみましょう。下のエディタはブラウザ上でそのまま実行できるサンプルになっていて、Phaser.Sceneを継承したクラスの中でthis.add.rectangle()を使って四角形を1つ表示しています。画面をクリックするとpointerdownイベントが発火し、Phaser.Display.Color.RandomRGB()でランダムな色に変わります。
Phaserのゲームは、Phaser.Gameのコンストラクタに設定オブジェクトを渡すところから始まります。要点だけ抜き出すと、次のような形です。
class MainScene extends Phaser.Scene {
create() {
// 四角形のゲームオブジェクトを作成
this.box = this.add.rectangle(400, 300, 80, 80, 0x38bdf8)
// クリックで色を変える
this.input.on('pointerdown', () => {
this.box.setFillStyle(Phaser.Display.Color.RandomRGB().color)
})
}
}
new Phaser.Game({
type: Phaser.AUTO,
width: 800,
height: 500,
scene: MainScene
})
実際に動かせるサンプルが下です。画面をクリックしてみてください。
this.add.rectangle()で作った図形はthis.box.setFillStyle()やthis.box.setScale()のように、あとから見た目を書き換えられます。0x38bdf8の部分を別の16進カラーコードに変えたり、setScale(1.5)の倍率を2.5に変えると、初期状態や変化の大きさが変わるので試してみてください。
基本的な使い方
シンプルなゲームの構成
Phaserでは、ゲームをシーン(Scene)という単位で管理します。
import Phaser from 'phaser';
// ゲームシーンの定義
class MainScene extends Phaser.Scene {
constructor() {
super('MainScene');
}
// アセットの読み込み
preload() {
this.load.image('player', 'assets/player.png');
}
// ゲームオブジェクトの作成
create() {
this.add.image(400, 300, 'player');
// テキストの表示
this.add.text(400, 100, 'Hello Phaser!', {
fontSize: '32px',
color: '#ffffff'
}).setOrigin(0.5);
}
// 毎フレーム実行される処理
update() {
// ゲームロジックをここに書く
}
}
// ゲームの設定と起動
const config: Phaser.Types.Core.GameConfig = {
type: Phaser.AUTO, // WebGL優先、フォールバックでCanvas
width: 800,
height: 600,
scene: MainScene,
physics: {
default: 'arcade',
arcade: {
gravity: { x: 0, y: 300 },
debug: false
}
}
};
const game = new Phaser.Game(config);
キャラクターの移動
キーボード入力でキャラクターを動かす例です。
class GameScene extends Phaser.Scene {
private player!: Phaser.Physics.Arcade.Sprite;
private cursors!: Phaser.Types.Input.Keyboard.CursorKeys;
create() {
// プレイヤーの作成
this.player = this.physics.add.sprite(400, 300, 'player');
this.player.setCollideWorldBounds(true);
// キーボード入力の設定
this.cursors = this.input.keyboard!.createCursorKeys();
}
update() {
// 左右移動
if (this.cursors.left.isDown) {
this.player.setVelocityX(-160);
} else if (this.cursors.right.isDown) {
this.player.setVelocityX(160);
} else {
this.player.setVelocityX(0);
}
// ジャンプ
if (this.cursors.up.isDown && this.player.body?.touching.down) {
this.player.setVelocityY(-330);
}
}
}
Reactとの統合
React環境で使う場合のパターンです。
import { useEffect, useRef } from 'react';
import Phaser from 'phaser';
const GameComponent: React.FC = () => {
const gameRef = useRef<Phaser.Game | null>(null);
useEffect(() => {
const config: Phaser.Types.Core.GameConfig = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'game-container',
scene: MainScene
};
gameRef.current = new Phaser.Game(config);
// クリーンアップ
return () => {
gameRef.current?.destroy(true);
};
}, []);
return <div id="game-container" />;
};
export default GameComponent;
実践的なユースケース
Phaserには用途に応じたAPIがいくつも用意されています。ここでは代表的な3つのパターン(キーボード操作、物理演算、Tweenアニメーション)を、実際に動かせるサンプル付きで紹介します。
1. キーボード操作でキャラクターを動かす
アクションゲームの基本となるのが、キー入力に応じたキャラクター移動です。Phaserではthis.input.keyboard.createCursorKeys()で矢印キーの状態を取得し、Arcade Physicsのbody.setVelocityX() / setVelocityY()で速度を与えて動かします。
要点だけ抜き出すと、次のような構成になります。
create() {
this.player = this.add.rectangle(400, 300, 50, 50, 0xf97316)
this.physics.add.existing(this.player)
this.player.body.setCollideWorldBounds(true)
this.cursors = this.input.keyboard.createCursorKeys()
}
update() {
const speed = 220
this.player.body.setVelocity(0)
if (this.cursors.left.isDown) this.player.body.setVelocityX(-speed)
if (this.cursors.right.isDown) this.player.body.setVelocityX(speed)
if (this.cursors.up.isDown) this.player.body.setVelocityY(-speed)
if (this.cursors.down.isDown) this.player.body.setVelocityY(speed)
}
実際に動かせるサンプルです。プレビュー内をクリックしてフォーカスを合わせてから、矢印キーを押してオレンジ色の四角形を動かしてみてください。壁際まで動かすとsetCollideWorldBounds(true)によって画面外に出ないことも確認できます。
speedの値を大きくすると移動が速くなりますし、if (this.cursors.up.isDown)の条件をthis.player.body.touching.downと組み合わせればジャンプ処理にもできます。記事前半の「基本的な使い方」で紹介したキャラクター移動のコードも、このcursorsとsetVelocityX()の組み合わせが土台になっています。
2. Arcade Physicsで重力とバウンドを再現する
Phaserの物理エンジン(Arcade Physics)を使うと、重力や反発(バウンド)といった挙動を数行で実装できます。this.physics.add.existing()で図形に物理ボディを与え、body.setBounce()で反発係数、ゲーム設定のgravityで重力の強さを指定します。
create() {
this.input.on('pointerdown', (pointer) => {
// クリック位置にボールを追加
const ball = this.add.circle(pointer.x, 60, 18, 0x4ade80)
this.physics.add.existing(ball)
ball.body.setBounce(0.7)
ball.body.setCollideWorldBounds(true)
})
}
// ゲーム設定側
physics: {
default: 'arcade',
arcade: { gravity: { y: 400 } }
}
実際に動かせるサンプルです。プレビュー内をクリックするたびにボールが追加され、重力で落下してから床でバウンドします。
gravity: { y: 400 }の数値を大きくすると落下が速くなり、setBounce(0.7)を0.2のように小さくすると跳ね返りが弱くなります。Arcade Physicsは軽量な分、当たり判定もシンプルなので、こうした「降らせる・跳ねさせる」系のミニゲームとの相性が良いです。
3. Tweenでアニメーションを付ける
ゲームオブジェクトを滑らかに動かしたいときは、Phaserのthis.tweens.add()を使います。scaleやangle、alphaといったプロパティを指定するだけで、duration(時間)やease(イージング関数)に沿ったアニメーションを再生できます。
const box = this.add.rectangle(400, 300, 100, 100, 0xa78bfa)
this.tweens.add({
targets: box,
scale: 1.4,
angle: 360,
duration: 1500,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
})
実際に動かせるサンプルです。紫色の四角形が自動で拡大・縮小と回転を繰り返し、クリックするとalpha(透明度)が切り替わります。
durationを短くするほどアニメーションが機敏になり、easeを'Bounce.easeOut'などに変えると動きの質感が変わります。repeat: -1は無限リピート、yoyo: trueは往復再生を意味するオプションで、Phaserのキャラクターアイドルモーションやエフェクト演出でよく使われる組み合わせです。
4. ポートフォリオサイトのインタラクティブ要素
自己紹介サイトにちょっとしたミニゲームを入れておくと、印象に残りやすいです。Phaserなら既存のReact/Next.jsプロジェクトに組み込めるので、導入のハードルが低いです。
5. プロトタイピング
ゲームのアイデアを素早く形にしたいとき、Phaserは便利です。Phaser Sandboxというオンラインエディタも用意されているので、環境構築なしでコードを試せます。
6. 教育用コンテンツ
プログラミング学習の教材として、ゲーム開発は題材としてわかりやすいです。Phaserは無料で使えて、ドキュメントも豊富なので、教育用途にも向いています。
7. Discord/YouTube向けのカジュアルゲーム
Discord ActivitiesやYouTube Playablesに対応しているので、友人と遊べるちょっとしたゲームを作るのにも使えます。
まとめ
Phaserは、HTML5で2Dゲームを作りたいなら正直一択と言っていいレベルのフレームワークです。
- 10年以上の開発実績で安定している
- ドキュメントと学習リソースが充実
- React/Vue/Next.jsなど既存の技術スタックと統合可能
- TypeScript対応で開発効率が良い
- MITライセンスで商用利用も可能
個人的には、週末にちょっとしたゲームを作る趣味にはちょうど良いと思っています。本格的なゲーム開発をするなら他の選択肢もありますが、Webで動く2Dゲームという条件なら、Phaserを選んでおけば間違いないですね。
公式サイトの例やドキュメントを眺めるだけでも、いろいろとインスピレーションが湧いてくるので、興味がある方は一度触ってみてください。