phaser-mobile について
phaser-mobileは、Phaser 4のゲームをモバイル端末やさまざまな画面サイズに対応させる開発者向けガイドです。スケーリング、タッチ入力、パフォーマンス、Capacitorでのデプロイ、PWA設定を扱います。
主な機能
- 01Scale Managerの設定
- 02タッチ操作とレスポンシブレイアウト
- 03ブラウザー操作の抑止
- 04モバイル性能の指針
- 05Capacitorでのデプロイ手順
- 06PWA設定ガイド
活用シーン
- 01異なる解像度にゲームUIを適応
- 02モバイルゲームへのタッチ操作追加
- 03CapacitorでのPhaserゲーム公開準備
- 04インストール可能なPWAの設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yakoub-ai/ phaser4-gamedev --skill phaser-mobileインストール後、Claude Code で/phaser-mobileを入力して読み込まれたか確認します。
同梱ファイルreferences/device-profiles.mdreferences/mobile-patterns.md
詳細
Phaser 4 モバイル & レスポンシブ
このガイドでは、Scale Manager の設定、タッチ操作、ブラウザのジェスチャー防止、モバイルでのパフォーマンス、Capacitor へのデプロイ、PWA のセットアップについて説明します。
Scale Manager の設定
Scale Manager は、Phaser が内部解像度を画面にどのようにマッピングするかを制御します。
// In GameConfig:
const config: Phaser.Types.Core.GameConfig = {
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
width: 800,
height: 600,
},
};
スケールモード
| モード | 動作 | 用途 |
|---|---|---|
Phaser.Scale.FIT | レターボックス表示、アスペクト比を維持 | 固定解像度のゲーム(最も一般的) |
Phaser.Scale.ENVELOP | 画面を埋める、端が切れる場合がある | 背景、カジュアルゲーム |
Phaser.Scale.RESIZE | Canvas がウィンドウの正確なサイズにリサイズされる | 適応型 UI のゲーム(複雑) |
Phaser.Scale.NONE | スケーリングなし、元のピクセルサイズ | デスクトップ専用ゲーム |
FIT はほとんどのゲームに適しています。Canvas はアスペクト比を維持しながらコンテナに収まるようにスケーリングされ、必要に応じてレターボックスバーが追加されます。
RESIZE は流動的な Canvas を提供しますが、すべての UI とレイアウトのコードがサイズ変更に対応する必要があります。ゲームをあらゆるデバイスの形状にぴったり収める必要が本当にある場合にのみ使用してください。
動的レイアウトを伴う RESIZE モード
// GameConfig for RESIZE:
scale: {
mode: Phaser.Scale.RESIZE,
autoCenter: Phaser.Scale.CENTER_BOTH,
// No fixed width/height — canvas matches window
}
// In the scene:
create(): void {
this.layoutUI(this.scale.width, this.scale.height);
// Re-layout whenever window resizes (orientation change, keyboard appearing, etc.)
this.scale.on('resize', (size: Phaser.Structs.Size) => {
this.cameras.main.setSize(size.width, size.height);
this.layoutUI(size.width, size.height);
});
}
private layoutUI(w: number, h: number): void {
this.scoreText?.setPosition(w * 0.05, h * 0.05);
this.healthBar?.setPosition(w * 0.5, h * 0.95);
this.pauseBtn?.setPosition(w - 40, 40);
}
タッチ操作
Phaser のポインターイベントはモバイルでも自動的に動作します — pointerdown、pointerup、pointermove はすべてタッチに対して発火します。
タップターゲットの最小サイズ: 44×44 論理ピクセル。これより小さいターゲットはモバイルでタップの失敗を引き起こします。
// Simple tap interaction (works on both mouse and touch)
const btn = this.add.image(x, y, 'button')
.setInteractive()
.on('pointerdown', () => this.handleTap())
.on('pointerover', () => btn.setTint(0xdddddd))
.on('pointerout', () => btn.clearTint());
モバイルでの方向制御については、references/mobile-patterns.md を参照してください — VirtualGamepad クラス。
レスポンシブレイアウト
UI 要素は画面サイズの割合として配置し、あらゆる解像度で機能するようにします。
create(): void {
const { width, height } = this.scale;
// Top-left HUD
this.scoreText = this.add.text(width * 0.05, height * 0.05, 'Score: 0', {
fontSize: `${Math.round(height * 0.05)}px`,
color: '#ffffff',
});
// Bottom-center action button
this.actionBtn = this.add.image(width * 0.5, height * 0.9, 'btn-action')
.setInteractive()
.setDisplaySize(width * 0.15, width * 0.15); // square button, proportional to width
}
フォントサイズのヒント: フォントサイズは height * 0.04~0.06 にスケーリングしてください。固定ピクセルサイズは小さな画面では巨大に見えます。
ブラウザのジェスチャー防止
モバイルブラウザは、ズーム、スクロール、コンテキストメニューのためにタッチイベントを横取りします。ネイティブのような操作感のゲームにするために、これらを防止してください。
// In your game's index.html or a boot script (not inside Phaser scenes):
// Prevent pinch-to-zoom and scroll
document.addEventListener('touchmove', (e) => e.preventDefault(), { passive: false });
// Prevent double-tap zoom on iOS
let lastTap = 0;
document.addEventListener('touchend', (e) => {
const now = Date.now();
if (now - lastTap < 300) e.preventDefault();
lastTap = now;
});
// Prevent right-click / long-press context menu
document.addEventListener('contextmenu', (e) => e.preventDefault());
// Inside a Phaser scene:
// Disable right-click context menu on the canvas
this.input.mouse?.disableContextMenu();
// Lock to landscape orientation (for most action games)
// Must be triggered from a user interaction (button press), not on load
async lockOrientation(): Promise<void> {
try {
await screen.orientation?.lock?.('landscape-primary');
} catch {
// Not supported on all browsers/platforms — fail silently
}
}
モバイルでのオーディオのアンロック
iOS と Android は、ユーザーがページを操作するまでオーディオの再生をブロックします。Phaser は、最初のポインター/キーイベントを監視し、その時点で AudioContext を再開することで、これを自動的に処理します。
読み込み直後にオーディオを再生するゲーム(オープニングジングル、環境音)では、「タップしてスタート」オーバーレイを表示します:
create(): void {
this.bgMusic = this.sound.add('music-main', { loop: true, volume: 0.6 });
if (this.sound.locked) {
// Show overlay — audio will unlock when user taps
const overlay = this.add.rectangle(
this.scale.width / 2, this.scale.height / 2,
this.scale.width, this.scale.height,
0x000000, 0.75
).setInteractive().setDepth(100);
this.add.text(
this.scale.width / 2, this.scale.height / 2,
'TAP TO START', { fontSize: '32px', color: '#ffffff' }
).setOrigin(0.5).setDepth(101);
this.sound.once(Phaser.Sound.Events.UNLOCKED, () => {
overlay.destroy();
this.bgMusic.play();
});
} else {
this.bgMusic.play();
}
}
デバイスの検出
create(): void {
const device = this.sys.game.device;
const isMobile = device.os.android || device.os.iOS;
const isTablet = isMobile && Math.min(window.innerWidth, window.innerHeight) > 600;
const hasTouch = device.input.touch;
if (isMobile) {
this.createVirtualControls();
} else {
// Show keyboard hint for desktop
this.add.text(16, this.scale.height - 30, 'WASD / Arrow Keys to move', {
fontSize: '14px', color: '#aaaaaa',
});
}
}
private createVirtualControls(): void {
// See references/mobile-patterns.md for VirtualGamepad class
}
その他の便利なデバイスフラグ:
device.os.windows、device.os.macOS、device.os.linuxdevice.browser.chrome、device.browser.safari、device.browser.firefoxdevice.features.webGL— WebGL サポートのチェック
モバイルでのパフォーマンス
モバイルの GPU と CPU はデスクトップよりも大幅に非力です。ミッドレンジのデバイスで 60fps を維持するために、以下の制約を適用してください。
テクスチャ:
- アトラスの最大サイズ: 2048×2048 px。古いデバイスとの互換性のために 1024×1024 を推奨します。
- テクスチャアトラスを使用してください — ドローコール間の GPU ステート切り替えを最小化できます。
- 一意のテクスチャの総数を減らしてください: 一意のテクスチャが少ないほど、ドローコールが減ります。
物理演算:
- 動的ボディが少ないほど FPS が向上します。モバイルでは同時に 50 個未満の動的ボディを目標にしてください。
- 画面外のオブジェクトでは物理演算を無効にしてください。
パーティクル:
- すべてのエミッターで
maxParticlesを設定してください。モバイルでの厳しい上限: 最大 50~100 パーティクル。 - シンプルなパーティクルテクスチャ(単色の四角形/円)を使用してください — 複雑なテクスチャはコストが高くなります。
カメラエフェクト:
camera.shake()や急速なcamera.zoomは GPU 負荷が高いです。控えめに使用してください。- シンプルな画面フラッシュ(
camera.flash())は問題ありません。
ピクセルアートゲーム:
const config: Phaser.Types.Core.GameConfig = {
pixelArt: true, // disables antialiasing — required for crisp pixel art
roundPixels: true, // prevents sub-pixel rendering artifacts
// These two together are a free performance win for pixel-art games
};
デバッグビルドでの FPS 監視:
// Show FPS counter during development
create(): void {
if (import.meta.env.DEV) {
this.add.text(4, 4, '', { fontSize: '12px', color: '#00ff00' })
.setDepth(999)
.setScrollFactor(0);
// Update in update():
// fpsText.setText(`FPS: ${Math.round(this.game.loop.actualFps)}`);
}
}
60fps を目標にしてください。60 を維持できない場合は、physics.arcade.fps: 30 と this.game.loop.targetFps = 30 で 30fps を受け入れてください — カクカクした 45fps は、滑らかな 30fps よりも悪いです。
Capacitor へのデプロイ(iOS / Android)
Capacitor は Web ビルドをネイティブの WebView でラップし、実際のアプリストア用バイナリを提供します。
# Install Capacitor
npm install @capacitor/core @capacitor/cli @capacitor/ios @capacitor/android
# Initialize (run once)
npx cap init "My Game" com.mygame.app --web-dir=dist
# Build the web project
npm run build
# Add native platforms (run once)
npx cap add ios
npx cap add android
# Sync web build into native projects
npx cap sync
# Open in Xcode (requires macOS + Xcode)
npx cap open ios
# Open in Android Studio
npx cap open android
cap open ios の後、Xcode の Signing & Capabilities タブで Team を設定し、デバイスまたはシミュレーターにビルドします。
Capacitor 設定(capacitor.config.ts)
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.mygame.app',
appName: 'My Game',
webDir: 'dist',
server: {
androidScheme: 'https',
},
plugins: {
SplashScreen: {
launchShowDuration: 0, // Hide splash immediately for games with their own loading screen
},
},
};
export default config;
Capacitor プラグインによるネイティブ機能
import { Haptics, ImpactStyle } from '@capacitor/haptics';
import { ScreenOrientation } from '@capacitor/screen-orientation';
// Vibration on hit
await Haptics.impact({ style: ImpactStyle.Medium });
// Lock orientation (native — more reliable than screen.orientation.lock on mobile)
await ScreenOrientation.lock({ orientation: 'landscape' });
PWA セットアップ
2 つのファイルで、ゲームをインストール可能なプログレッシブウェブアプリにできます。
// public/manifest.json
{
"name": "My Game",
"short_name": "MyGame",
"description": "An awesome Phaser 4 game",
"display": "fullscreen",
"orientation": "landscape",
"background_color": "#000000",
"theme_color": "#000000",
"start_url": "./index.html",
"icons": [
{ "src": "icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "icons/icon-512.png", "sizes": "512x512", "type": "image/png" },
{ "src": "icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
]
}
<link rel="manifest" href="./manifest.json">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="theme-color" content="#000000">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
オフラインサポートを備えた完全な PWA にするには、サービスワーカーを追加します(Vite の vite-plugin-pwa がこれを自動的に処理します)。
npm install -D vite-plugin-pwa
// vite.config.ts
import { VitePWA } from 'vite-plugin-pwa';
export default {
plugins: [
VitePWA({
registerType: 'autoUpdate',
manifest: false, // use your own public/manifest.json
workbox: {
globPatterns: ['**/*.{js,css,html,png,ogg,mp3,json}'],
},
}),
],
};
デバイス固有のプロファイル
注意点と推奨設定を含む完全なプロファイルについては、references/device-profiles.md を参照してください。
クイック判断マトリクス
| 判断項目 | iOS Safari | Android Chrome | デスクトップ | Capacitor | PWA |
|---|---|---|---|---|---|
| 音声フォーマットの優先度 | mp3(ogg 非対応) | mp3+ogg | 任意 | mp3+ogg | mp3+ogg |
| 最大アトラスサイズ | 2048x2048 | 2048x2048(ローエンド) | 4096+ | 2048x2048 | 2048x2048 |
| 画面の向きの固定 | Capacitor のみ | Fullscreen API | 該当なし | ネイティブプラグイン | manifest.json |
| 仮想コントロール | 必須 | 必須 | 任意 | 必須 | 必須 |
| 触覚フィードバック | なし | なし | なし | あり(プラグイン) | なし |
| オフラインサポート | 限定的(50MB) | あり | 該当なし | 組み込み | サービスワーカー |
| インストールプロンプト | ホーム画面に追加 | インストールバナー | 該当なし | App Store | ブラウザのプロンプト |
主要プラットフォームの選択
- Web のみ(itch.io、ポートフォリオ): デスクトップ優先の設定、FIT スケールモード、800x600 または 1280x720
- モバイル優先: FIT スケールモード、640x360 横向きまたは 360x640 縦向き、仮想コントロール
- クロスプラットフォーム: FIT スケールモード、実行時にデバイスを検出し、コントロールとアセット品質を適応させる
- ネイティブアプリ(App Store / Play Store): Capacitor + プラットフォーム固有の最適化
その他のリソース
リファレンスファイル
references/mobile-patterns.md— 完全なレスポンシブ GameConfig、VirtualGamepad クラス(ジョイスティック + ボタン)、OrientationGuard オーバーレイ、MobileAudioUnlock コンポーネント、DeviceCapabilities 検出、Capacitor ネイティブプラグイン統合references/device-profiles.md— iOS Safari、Android Chrome、デスクトップ、Capacitor(iOS/Android)、PWA 向けのデバイス固有の最適化プロファイルと、ターゲットごとに推奨される GameConfig