---
title: Phaserで始めるゲーム開発入門
tags:  #phaser #ゲーム  
author: [Daizen Ikehara](https://www.docswell.com/user/Neri78)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/GE8685XZ7D.jpg?width=480
description: 2023/01/21に開催されたBurikaigi 2023で発表したセッション資料の公開版です。 こちらのチュートリアルについての理解をお話しさせていただきました。 https://phaser.io/tutorials/making-your-first-phaser-3-game/part1
published: January 21, 23
canonical: https://www.docswell.com/s/Neri78/KE6XNK-2023-01-21-phaser
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/GE8685XZ7D.jpg)

Phaserで始める
ゲーム開発入門
2023/01/21
池原大然 (@Neri78)
#burikaigi #burikaigi_s


# Page. 2

![Page Image](https://bcdn.docswell.com/page/LEL9RY81JR.jpg)

自己紹介
池原 大然
Twilio デベロッパーエバンジェリスト
Twitter: @neri78
趣味はゲーム（エンジョイ勢）
#burikaigi #burikaigi_s


# Page. 3

![Page Image](https://bcdn.docswell.com/page/4JMZRN65EW.jpg)

あらためて
#burikaigi #burikaigi_s


# Page. 4

![Page Image](https://bcdn.docswell.com/page/PJR6RDPZ79.jpg)

エンジョイ勢です
#burikaigi #burikaigi_s


# Page. 5

![Page Image](https://bcdn.docswell.com/page/PEXMR1317X.jpg)

Phaserとは？
オープンソースで開発されているHTML5ゲームフレームワーク
https://phaser.io/
#burikaigi #burikaigi_s


# Page. 6

![Page Image](https://bcdn.docswell.com/page/3EKGR2YMJD.jpg)

Q.なぜこの話をするのか？
#burikaigi #burikaigi_s


# Page. 7

![Page Image](https://bcdn.docswell.com/page/L73N849275.jpg)

A. ゲーマーだから
#burikaigi #burikaigi_s


# Page. 8

![Page Image](https://bcdn.docswell.com/page/87DWMQG6JG.jpg)

ではなく
#burikaigi #burikaigi_s


# Page. 9

![Page Image](https://bcdn.docswell.com/page/VJP9RL8ZE8.jpg)

仕事でも（すこし）関わっているから
日本語版:
https://www.twilio.com/quest/ja
English Ver: https://www.twilio.com/quest/
#burikaigi #burikaigi_s


# Page. 10

![Page Image](https://bcdn.docswell.com/page/2EVMRQNMEQ.jpg)

Phaserの種類
Phaserのバージョンは2つ
● Phaser 3
開発チームが開発を主導している最新バージョン
● Phaser 2 / CE (Community Edition)
コミュニティに開発が委ねられた旧バージョン
#burikaigi #burikaigi_s


# Page. 11

![Page Image](https://bcdn.docswell.com/page/57GGMWKX7L.jpg)

セッションでカバーする内容
チュートリアルを自分なりに理解したものを共有する
自分は「Phaser完全に理解した」状態
●
●
●
●
●
●
Phaserの導入方法
ゲームの実行方法
アセットのロードと画面への配置方法
物理エンジンの利用方法
キーボードナビゲーションの設定方法
オブジェクト同士が衝突した際の処理方法
#burikaigi #burikaigi_s


# Page. 12

![Page Image](https://bcdn.docswell.com/page/4EQXR3N57P.jpg)

今日の題材
https://phaser.io/learn
#burikaigi #burikaigi_s
https://phaser.io/tutorials/making-your-ﬁrst-phaser-3-game/part1


# Page. 13

![Page Image](https://bcdn.docswell.com/page/KJ4681GV71.jpg)

完成品
#burikaigi #burikaigi_s


# Page. 14

![Page Image](https://bcdn.docswell.com/page/LE1V2GD47G.jpg)

Phaserの導入
#burikaigi #burikaigi_s


# Page. 15

![Page Image](https://bcdn.docswell.com/page/GEWLRKYZ72.jpg)

利用するもの
参考: https://phaser.io/tutorials/getting-started-phaser3
● JavaScript
● Webサーバー
● コードエディター
#burikaigi #burikaigi_s


# Page. 16

![Page Image](https://bcdn.docswell.com/page/47ZMRZXLE3.jpg)

参照方法 - https://phaser.io/download/stable
● ローカルjsファイル
● npm
npm install phaser@3.55.2
● CDN
&lt;script src=&quot;//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.min.js&quot;&gt;&lt;/script&gt;
#burikaigi #burikaigi_s


# Page. 17

![Page Image](https://bcdn.docswell.com/page/YJ6NRZ4MJV.jpg)

参照
&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot; /&gt;
&lt;title&gt;Making your first Phaser 3 Game&lt;/title&gt;
&lt;script src=&quot;//cdn.jsdelivr.net/npm/phaser@3.11.0/dist/phaser.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
…ロジックの実装
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
#burikaigi #burikaigi_s


# Page. 18

![Page Image](https://bcdn.docswell.com/page/GJ558WQQJ4.jpg)

ゲームの起動
#burikaigi #burikaigi_s


# Page. 19

![Page Image](https://bcdn.docswell.com/page/LE3N84VZE5.jpg)

基本構造
&lt;script type=&quot;text/javascript&quot;&gt;
// 設定を定義
let config = {
type: Phaser.AUTO, // レンダリングコンテキストの指定 - AUTO, CANVAS, WEBGL
width: 800, // ゲーム画面のキャンバス幅
height: 600, // ゲーム画面のキャンバス高さ
scene: { // 画面設定
preload: preload, // 画面ロード前に実行されるロジック
create: create, // 画面作成時に実行されるロジック
update: update // 更新時に実行されるロジック
}
};
// ゲームを作成
let game = new Phaser.Game(config);
#burikaigi #burikaigi_s
&lt;/script&gt;


# Page. 20

![Page Image](https://bcdn.docswell.com/page/8EDWMQ847G.jpg)

画像の読み込み方法
#burikaigi #burikaigi_s


# Page. 21

![Page Image](https://bcdn.docswell.com/page/V7P9RL8VJ8.jpg)

画像たち
#burikaigi #burikaigi_s


# Page. 22

![Page Image](https://bcdn.docswell.com/page/2JVMRQNRJQ.jpg)

画面作成前に画像アセットをロード
// 画面作成前に実行。呼び出し元はPhase.Sceneクラス
function preload ()
{
// Sceneに組み込まれているPhaser.Loader.LoaderPluginを使用し、アセットを読み込み
// 画像の読み込み（key, source）
this.load.image(&#039;sky&#039;, &#039;assets/sky.png&#039;);
this.load.image(&#039;ground&#039;, &#039;assets/platform.png&#039;);
this.load.image(&#039;star&#039;, &#039;assets/star.png&#039;);
this.load.image(&#039;bomb&#039;, &#039;assets/bomb.png&#039;);
}
#burikaigi #burikaigi_s


# Page. 23

![Page Image](https://bcdn.docswell.com/page/5EGGMWK6EL.jpg)

画面作成時にアセットを配置
// シーン開始時にScene Managerによって呼び出される。
// ScenePlugin.add()、ScenePlugin.start()、Scene.settings.dataでデータを渡せる
// 呼び出し元はPhaser.Scene
function create ()
{
// 画像を追加
// Phaserはアセットの中心を (0,0)に設置してしまうので座標計算が必要
this.add.image(400, 300, &#039;sky&#039;);
// あるいはsetOriginを使用
this.add.image(0,0, &#039;sky&#039;).setOrigin(0,0);
// 画像は下から順にスタックされていく
this.add.image(400, 300, &#039;star&#039;);
}
#burikaigi #burikaigi_s


# Page. 24

![Page Image](https://bcdn.docswell.com/page/4JQXR3N2EP.jpg)

ゲームオブジェクトの
設置方法
#burikaigi #burikaigi_s


# Page. 25

![Page Image](https://bcdn.docswell.com/page/K74681GPE1.jpg)

物理演算エンジンの指定
let config = {
type: Phaser.AUTO, width: 800, height: 600,
// 物理演算エンジンを指定
physics: {
default: &#039;arcade&#039;, //デフォルト物理演算システム arcade, impact, matter
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: { // 省略
}
#burikaigi #burikaigi_s
};


# Page. 26

![Page Image](https://bcdn.docswell.com/page/LJ1V2GDXEG.jpg)

動的オブジェクト
（動かしたい）
静的オブジェクト
（動かさない）
#burikaigi #burikaigi_s


# Page. 27

![Page Image](https://bcdn.docswell.com/page/GJWLRKYKE2.jpg)

静的オブジェクト
（動かさない）
#burikaigi #burikaigi_s


# Page. 28

![Page Image](https://bcdn.docswell.com/page/4EZMRZXNJ3.jpg)

静的オブジェクト（動かないもの）の作成
let platforms;
function create ()
{
// 静的な物理オブジェクトグループの作成
platforms = this.physics.add.staticGroup();
// Phaser.Physics.Arcade.StaticGroup.create(x,y, key)
// スケーリングをする場合は再描画を指示
platforms.create(400, 568, &#039;ground&#039;).setScale(2).refreshBody();
platforms.create(600, 400, &#039;ground&#039;);
platforms.create(50, 250, &#039;ground&#039;);
platforms.create(750, 220, &#039;ground&#039;);
}
#burikaigi
#burikaigi_s


# Page. 29

![Page Image](https://bcdn.docswell.com/page/Y76NRZ497V.jpg)

動的オブジェクト
（動かしたい）
#burikaigi #burikaigi_s


# Page. 30

![Page Image](https://bcdn.docswell.com/page/G7558WQD74.jpg)

動的オブジェクトを追加
function preload ()
{
// スプライトシート（ key, source, オプション )
this.load.spritesheet(&#039;dude&#039;, &#039;assets/dude.png&#039;, { frameWidth: 32, frameHeight: 48 });
}
let player;
function create ()
{
// 動的なオブジェクトを追加。 this.physics.add - Dynamics Physics / 左下から 100 x 450ピクセルにスプライトを配置
player = this.physics.add.sprite(100, 450, &#039;dude&#039;);
// オブジェクトの弾み方
player.setBounce(0.2);
// 世界の境界線と衝突させるかどうか
player.setCollideWorldBounds(true);
// プレイヤースプライトと静的オブジェクトの間に衝突を追加
this.physics.add.collider(player, platforms);
}
#burikaigi
#burikaigi_s


# Page. 31

![Page Image](https://bcdn.docswell.com/page/9J2NKQWMER.jpg)

スプライトシートとは？
複数の画像を1枚の画像にまとめたもの
0
1
#burikaigi #burikaigi_s
2
3
4
5
6
7
8


# Page. 32

![Page Image](https://bcdn.docswell.com/page/DEYPNWLPEM.jpg)

スプライトシートからアニメーションを定義
function create ()
{
this.anims.create({
this.anims.create({
key: &#039;left&#039;,
key: &#039;turn&#039;,
frames: this.anims.generateFrameNumbers(
frames: [ { key: &#039;dude&#039;, frame: 4 } ],
frameRate: 20
&#039;dude&#039;, { start: 0, end: 3 }),
});
frameRate: 10,
repeat: -1
this.anims.create({
});
key: &#039;right&#039;,
frames: this.anims.generateFrameNumbers(
this.anims.create({
&#039;dude&#039;, { start: 5, end: 8 }),
key: &#039;turn&#039;,
frameRate: 10,
frames: [ { key: &#039;dude&#039;, frame: 4 } ],
repeat: -1
frameRate: 20
});
#burikaigi #burikaigi_s
});
}


# Page. 33

![Page Image](https://bcdn.docswell.com/page/VJN5X94M78.jpg)

オブジェクトを
操作できるようにする
#burikaigi #burikaigi_s


# Page. 34

![Page Image](https://bcdn.docswell.com/page/YE9Y82QWJ3.jpg)

キーボードの入力を検知し、
指定の方向に移動させる
#burikaigi #burikaigi_s


# Page. 35

![Page Image](https://bcdn.docswell.com/page/GE8685GR7D.jpg)

オブジェクトの移動に利用できそうなもの
Phaser . Physics . Arcade . Sprite - https://newdocs.phaser.io/docs/3.55.2/Phaser.Physics.Arcade.Sprite
●
●
●
●
●
setVelocity, setVelocityX, setVelocityY - 速度を設定
setAcceleration, setAccelerationX, setAccelerationY - 加速度を設定
setAngle - 角度を設定
setAngularAcceleration - 角速度を設定
setPosition - 位置を設定
#burikaigi #burikaigi_s


# Page. 36

![Page Image](https://bcdn.docswell.com/page/LEL9RYG2JR.jpg)

キーボード入力の定義
else if (cursors.right.isDown)
{
let player;
// X軸（右方向）に対して160の加速度を付与 = 右
let cursors;
player.setVelocityX(160);
// プレイヤーオブジェクトの外観を変更
player.anims.play(&#039;right&#039;, true);
function create ()
}
{
// カーソルキー（Up, Down, Left, Right）を作成
else
cursors = this.input.keyboard.createCursorKeys();
{
}
// その他のキーの場合は左右移動を停止させる
function update ()
player.setVelocityX(0);
{
player.anims.play(&#039;turn&#039;);
// キーが押された方向を感知し、処理を追加
}
if (cursors.left.isDown)
if (cursors.up.isDown &amp;&amp; player.body.touching.down)
{
// X軸（右方向）に対して-160の加速度を付与 = 左移動
{
player.setVelocityX(-160);
// Y軸（下方向）に対して-330の加速度を付与 = 上移動
// プレイヤーオブジェクトの外観を変更
player.setVelocityY(-330);
#burikaigi #burikaigi_s
}
player.anims.play(&#039;left&#039;, true);
}
}


# Page. 37

![Page Image](https://bcdn.docswell.com/page/4JMZRNQ9EW.jpg)

オブジェクト同士の
衝突制御
#burikaigi #burikaigi_s


# Page. 38

![Page Image](https://bcdn.docswell.com/page/PJR6RD8979.jpg)

別のオブジェクトに衝突した
場合をどう検知する？
#burikaigi #burikaigi_s


# Page. 39

![Page Image](https://bcdn.docswell.com/page/PEXMR1837X.jpg)

プレイヤーと別の動的オブジェクト
let starts;
function create ()
{
// 指定のオブジェクトの衝突判定をおこなわせる
this.physics.add.collider(player, platforms);
this.physics.add.collider(stars, platforms);
// playerとstartsが重なりあった（衝突した）際の処理を定義
this.physics.add.overlap(player, stars, collectStar, null, this);
}
function collectStar (player, star)
{
// スターの表示を無効化させる
star.disableBody(true, true);
#burikaigi #burikaigi_s
}


# Page. 40

![Page Image](https://bcdn.docswell.com/page/3EKGR2KNJD.jpg)

スコアを画面に表示
#burikaigi #burikaigi_s


# Page. 41

![Page Image](https://bcdn.docswell.com/page/L73N84ZZ75.jpg)

スターに触れた際に
得点を追加したい
#burikaigi #burikaigi_s


# Page. 42

![Page Image](https://bcdn.docswell.com/page/87DWMQR4JG.jpg)

スコアを画面に追加し、加算する
let score = 0;
let scoreText;
function create ()
{
// スコアテキストの追加
scoreText = this.add.text(16, 16, &#039;score: 0&#039;, { fontSize: &#039;32px&#039;, fill: &#039;#000&#039; });
}
function collectStar (player, star)
{
// スターの表示を無効化させる
star.disableBody(true, true);
// スコアを増加させ、テキストを更新
score += 10;
scoreText.setText(&#039;Score: &#039; + score);
}
#burikaigi
#burikaigi_s


# Page. 43

![Page Image](https://bcdn.docswell.com/page/VJP9RLWVE8.jpg)

ゲームを停止させる
#burikaigi #burikaigi_s


# Page. 44

![Page Image](https://bcdn.docswell.com/page/2EVMRQ8REQ.jpg)

爆弾に触れた際に
ゲームを停止
#burikaigi #burikaigi_s


# Page. 45

![Page Image](https://bcdn.docswell.com/page/57GGMW567L.jpg)

爆弾を追加し、衝突時にゲームを停止させる
let bombs;
let gameOver = false;
function create ()
{
// 爆弾を追加
bombs = this.physics.add.group();
//
Collide the player and the stars with the platforms
this.physics.add.collider(bombs, platforms);
//
プレーヤーと星が重なった際のイベントハンドリング（また使う）
this.physics.add.overlap(player, stars, collectStar, null, this);
// プレイヤーと爆弾が衝突した際のイベントをハンドリング
#burikaigi
#burikaigi_s
}
this.physics.add.collider(player, bombs, hitBomb, null, this);


# Page. 46

![Page Image](https://bcdn.docswell.com/page/4EQXR3Z27P.jpg)

爆弾の生成と衝突時の処理
function collectStar (player, star)
function hitBomb (player, bomb)
{
{
// 星が全てなくなった時点で星を再生成し、爆弾を生成する
// 物理エンジンを一時停止
if (stars.countActive(true) === 0)
this.physics.pause();
{
// プレイヤーの色合いを追加で設定
stars.children.iterate(function (child) {
player.setTint(0xff0000);
child.enableBody(true, child.x, 0, true, true); });
// turnアニメーションを実行
player.anims.play(&#039;turn&#039;);
let x = (player.x &lt; 400) ? Phaser.Math.Between(400, 800) :
// flag
Phaser.Math.Between(0, 400);
gameOver = true;
let bomb = bombs.create(x, 16, &#039;bomb&#039;);
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
bomb.allowGravity = false;
#burikaigi #burikaigi_s
}
}
}


# Page. 47

![Page Image](https://bcdn.docswell.com/page/KJ46813P71.jpg)

まとめ・リソース
#burikaigi #burikaigi_s


# Page. 48

![Page Image](https://bcdn.docswell.com/page/LE1V2G1X7G.jpg)

まとめ
JavaScriptでゲームを作成できる
物理演算エンジンを提供
慣れるまで大変そう
（デモできなかった）別のツールで作成した
タイルをロードすることもできる
● スポンサーLTで追加のデモをする予定！
●
●
●
●
#burikaigi #burikaigi_s


# Page. 49

![Page Image](https://bcdn.docswell.com/page/GEWLRK8K72.jpg)

ありがとうございました！
#burikaigi #burikaigi_s


