160.1K Views
January 21, 23
スライド概要
2023/01/21に開催されたBurikaigi 2023で発表したセッション資料の公開版です。
こちらのチュートリアルについての理解をお話しさせていただきました。
https://phaser.io/tutorials/making-your-first-phaser-3-game/part1
Developer Advocate for Auth0 by Okta
Phaserで始める ゲーム開発入門 2023/01/21 池原大然 (@Neri78) #burikaigi #burikaigi_s
自己紹介 池原 大然 Twilio デベロッパーエバンジェリスト Twitter: @neri78 趣味はゲーム(エンジョイ勢) #burikaigi #burikaigi_s
あらためて #burikaigi #burikaigi_s
エンジョイ勢です #burikaigi #burikaigi_s
Phaserとは? オープンソースで開発されているHTML5ゲームフレームワーク https://phaser.io/ #burikaigi #burikaigi_s
Q.なぜこの話をするのか? #burikaigi #burikaigi_s
A. ゲーマーだから #burikaigi #burikaigi_s
ではなく #burikaigi #burikaigi_s
仕事でも(すこし)関わっているから 日本語版: https://www.twilio.com/quest/ja English Ver: https://www.twilio.com/quest/ #burikaigi #burikaigi_s
Phaserの種類 Phaserのバージョンは2つ ● Phaser 3 開発チームが開発を主導している最新バージョン ● Phaser 2 / CE (Community Edition) コミュニティに開発が委ねられた旧バージョン #burikaigi #burikaigi_s
セッションでカバーする内容 チュートリアルを自分なりに理解したものを共有する 自分は「Phaser完全に理解した」状態 ● ● ● ● ● ● Phaserの導入方法 ゲームの実行方法 アセットのロードと画面への配置方法 物理エンジンの利用方法 キーボードナビゲーションの設定方法 オブジェクト同士が衝突した際の処理方法 #burikaigi #burikaigi_s
今日の題材 https://phaser.io/learn #burikaigi #burikaigi_s https://phaser.io/tutorials/making-your-first-phaser-3-game/part1
完成品 #burikaigi #burikaigi_s
Phaserの導入 #burikaigi #burikaigi_s
利用するもの 参考: https://phaser.io/tutorials/getting-started-phaser3 ● JavaScript ● Webサーバー ● コードエディター #burikaigi #burikaigi_s
参照方法 - https://phaser.io/download/stable ● ローカルjsファイル ● npm npm install [email protected] ● CDN <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script> <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/phaser.min.js"></script> #burikaigi #burikaigi_s
参照 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Making your first Phaser 3 Game</title> <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script> </head> <body> <script type="text/javascript"> …ロジックの実装 </script> </body> </html> #burikaigi #burikaigi_s
ゲームの起動 #burikaigi #burikaigi_s
基本構造
<script type="text/javascript">
// 設定を定義
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
</script>
画像の読み込み方法 #burikaigi #burikaigi_s
画像たち #burikaigi #burikaigi_s
画面作成前に画像アセットをロード // 画面作成前に実行。呼び出し元はPhase.Sceneクラス function preload () { // Sceneに組み込まれているPhaser.Loader.LoaderPluginを使用し、アセットを読み込み // 画像の読み込み(key, source) this.load.image('sky', 'assets/sky.png'); this.load.image('ground', 'assets/platform.png'); this.load.image('star', 'assets/star.png'); this.load.image('bomb', 'assets/bomb.png'); } #burikaigi #burikaigi_s
画面作成時にアセットを配置 // シーン開始時にScene Managerによって呼び出される。 // ScenePlugin.add()、ScenePlugin.start()、Scene.settings.dataでデータを渡せる // 呼び出し元はPhaser.Scene function create () { // 画像を追加 // Phaserはアセットの中心を (0,0)に設置してしまうので座標計算が必要 this.add.image(400, 300, 'sky'); // あるいはsetOriginを使用 this.add.image(0,0, 'sky').setOrigin(0,0); // 画像は下から順にスタックされていく this.add.image(400, 300, 'star'); } #burikaigi #burikaigi_s
ゲームオブジェクトの 設置方法 #burikaigi #burikaigi_s
物理演算エンジンの指定
let config = {
type: Phaser.AUTO, width: 800, height: 600,
// 物理演算エンジンを指定
physics: {
default: 'arcade', //デフォルト物理演算システム arcade, impact, matter
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: { // 省略
}
#burikaigi #burikaigi_s
};
動的オブジェクト (動かしたい) 静的オブジェクト (動かさない) #burikaigi #burikaigi_s
静的オブジェクト (動かさない) #burikaigi #burikaigi_s
静的オブジェクト(動かないもの)の作成 let platforms; function create () { // 静的な物理オブジェクトグループの作成 platforms = this.physics.add.staticGroup(); // Phaser.Physics.Arcade.StaticGroup.create(x,y, key) // スケーリングをする場合は再描画を指示 platforms.create(400, 568, 'ground').setScale(2).refreshBody(); platforms.create(600, 400, 'ground'); platforms.create(50, 250, 'ground'); platforms.create(750, 220, 'ground'); } #burikaigi #burikaigi_s
動的オブジェクト (動かしたい) #burikaigi #burikaigi_s
動的オブジェクトを追加
function preload ()
{
// スプライトシート( key, source, オプション )
this.load.spritesheet('dude', 'assets/dude.png', { frameWidth: 32, frameHeight: 48 });
}
let player;
function create ()
{
// 動的なオブジェクトを追加。 this.physics.add - Dynamics Physics / 左下から 100 x 450ピクセルにスプライトを配置
player = this.physics.add.sprite(100, 450, 'dude');
// オブジェクトの弾み方
player.setBounce(0.2);
// 世界の境界線と衝突させるかどうか
player.setCollideWorldBounds(true);
// プレイヤースプライトと静的オブジェクトの間に衝突を追加
this.physics.add.collider(player, platforms);
}
#burikaigi
#burikaigi_s
スプライトシートとは? 複数の画像を1枚の画像にまとめたもの 0 1 #burikaigi #burikaigi_s 2 3 4 5 6 7 8
スプライトシートからアニメーションを定義
function create ()
{
this.anims.create({
this.anims.create({
key: 'left',
key: 'turn',
frames: this.anims.generateFrameNumbers(
frames: [ { key: 'dude', frame: 4 } ],
frameRate: 20
'dude', { start: 0, end: 3 }),
});
frameRate: 10,
repeat: -1
this.anims.create({
});
key: 'right',
frames: this.anims.generateFrameNumbers(
this.anims.create({
'dude', { start: 5, end: 8 }),
key: 'turn',
frameRate: 10,
frames: [ { key: 'dude', frame: 4 } ],
repeat: -1
frameRate: 20
});
#burikaigi #burikaigi_s
});
}
オブジェクトを 操作できるようにする #burikaigi #burikaigi_s
キーボードの入力を検知し、 指定の方向に移動させる #burikaigi #burikaigi_s
オブジェクトの移動に利用できそうなもの 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
キーボード入力の定義
else if (cursors.right.isDown)
{
let player;
// X軸(右方向)に対して160の加速度を付与 = 右
let cursors;
player.setVelocityX(160);
// プレイヤーオブジェクトの外観を変更
player.anims.play('right', true);
function create ()
}
{
// カーソルキー(Up, Down, Left, Right)を作成
else
cursors = this.input.keyboard.createCursorKeys();
{
}
// その他のキーの場合は左右移動を停止させる
function update ()
player.setVelocityX(0);
{
player.anims.play('turn');
// キーが押された方向を感知し、処理を追加
}
if (cursors.left.isDown)
if (cursors.up.isDown && player.body.touching.down)
{
// X軸(右方向)に対して-160の加速度を付与 = 左移動
{
player.setVelocityX(-160);
// Y軸(下方向)に対して-330の加速度を付与 = 上移動
// プレイヤーオブジェクトの外観を変更
player.setVelocityY(-330);
#burikaigi #burikaigi_s
}
player.anims.play('left', true);
}
}
オブジェクト同士の 衝突制御 #burikaigi #burikaigi_s
別のオブジェクトに衝突した 場合をどう検知する? #burikaigi #burikaigi_s
プレイヤーと別の動的オブジェクト 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 }
スコアを画面に表示 #burikaigi #burikaigi_s
スターに触れた際に 得点を追加したい #burikaigi #burikaigi_s
スコアを画面に追加し、加算する
let score = 0;
let scoreText;
function create ()
{
// スコアテキストの追加
scoreText = this.add.text(16, 16, 'score: 0', { fontSize: '32px', fill: '#000' });
}
function collectStar (player, star)
{
// スターの表示を無効化させる
star.disableBody(true, true);
// スコアを増加させ、テキストを更新
score += 10;
scoreText.setText('Score: ' + score);
}
#burikaigi
#burikaigi_s
ゲームを停止させる #burikaigi #burikaigi_s
爆弾に触れた際に ゲームを停止 #burikaigi #burikaigi_s
爆弾を追加し、衝突時にゲームを停止させる 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);
爆弾の生成と衝突時の処理
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('turn');
let x = (player.x < 400) ? Phaser.Math.Between(400, 800) :
// flag
Phaser.Math.Between(0, 400);
gameOver = true;
let bomb = bombs.create(x, 16, 'bomb');
bomb.setBounce(1);
bomb.setCollideWorldBounds(true);
bomb.setVelocity(Phaser.Math.Between(-200, 200), 20);
bomb.allowGravity = false;
#burikaigi #burikaigi_s
}
}
}
まとめ・リソース #burikaigi #burikaigi_s
まとめ JavaScriptでゲームを作成できる 物理演算エンジンを提供 慣れるまで大変そう (デモできなかった)別のツールで作成した タイルをロードすることもできる ● スポンサーLTで追加のデモをする予定! ● ● ● ● #burikaigi #burikaigi_s
ありがとうございました! #burikaigi #burikaigi_s