あらすじ
Phaser3でUIコンポーネントを別クラスに自作する方法をボタンクラスを例に書いていこうと思います。UIコンポーネントを別クラスに記述できると複数人での作業の分担などが行いやすくなるので、役に立つのではないのでしょうか?
(あと、Atomic Designのようなコンポーネントをファイル等で分ける前提の手法もとれるようになりますね)
やり方
プログラム全文
import * as Phaser from "phaser"
interface Props{
width?: number;
height?: number;
onClick?: Function;
}
export default class Button extends Phaser.GameObjects.Container {
seKey: string = "";
text: Phaser.GameObjects.Text = null;
container: Phaser.GameObjects.Rectangle = null;
constructor (scene: Phaser.Scene, x, y, text, props: Props, { align = 'center', fontSize = 15, color = "black" } = {}) {
super(scene, x, y)
const {
width = 200,
height = 40,
onClick
} = props
this.scene = scene;
this.scene.add.existing(this);
this.setSize(width, height).setInteractive();
const alignLeft = align === 'left';
this.text = scene.add.text(alignLeft ? -width / 2 + 0 : 0, -1, text, { align, fontSize , color}).setOrigin(alignLeft ? 0 : 0.5, 0.5).setPadding(0, 2, 0, 0)
this.text.setColor("black");
this.container = scene.add.rectangle(0, 0, width / 2, height / 2);
this.container.setStrokeStyle(1, 0xffffff).setOrigin(alignLeft ? 0 : 0.5, 0.5)
this.add([this.container, this.text])
this.on('pointerover', () => {
this.text.setColor("white");
})
this.on('pointerout', () => {
console.log("aaa");
this.text.setColor("black");
})
this.on('pointerup', p => {
onClick && onClick(p);
})
}
setSeKey(key){
this.seKey = key
return this
}
setText (text) {
this.text.setText(text)
return this
}
}
これは一例です。書き方に多少の癖や慣れ、宗派などはあると思います。私はReactをよく使うので、Reactに記法を寄せたいなと頑張ってみました。プログラムの流れとしてはPhaser.GameObject.Container
を継承したクラスを作成し、そこにいろいろなものを詰め込んでいくという手法を取ればできると思います。これから詳細を解説します。
詳細解説
scene受け取り
this.scene = scene;
this.scene.add.existing(this);
this.setSize(width, height).setInteractive();
シーンを受け取り、this.scene
に詰め込むことでどこでも扱えるようにします。setInteractive
は呼び出さないと後述するthis.on
が使えなくなるので気を付けましょう。
パーツ宣言
const alignLeft = align === 'left';
this.text = scene.add.text(alignLeft ? -width / 2 + 0 : 0, -1, text, { align, fontSize , color}).setOrigin(alignLeft ? 0 : 0.5, 0.5).setPadding(0, 2, 0, 0)
this.text.setColor("black");
this.container = scene.add.rectangle(0, 0, width / 2, height / 2);
this.container.setStrokeStyle(1, 0xffffff).setOrigin(alignLeft ? 0 : 0.5, 0.5)
this.add([this.container, this.text])
ボタンに表示するテキストとボーダーラインを作成し、画面と自身に追加します。ここで色や線の太さなどを設定しています。setOrigin
を0.5に設定することで中央ぞろえにすることが出来ます。
hover等の作成
this.on('pointerover', () => {
this.text.setColor("white");
})
this.on('pointerout', () => {
console.log("aaa");
this.text.setColor("black");
})
this.on('pointerup', p => {
onClick && onClick(p);
})
「マウスを乗せたときに色が変わる」などの小技はここで行います。一番下のpointerup
はクリック時の処理を行っています。
ボタンクラス呼出し
this.button = new Button(scene, x, y, text, {
onClick: () =>{
console.log("Click!!");
}
})
ボタンクラスをPhaser.Scene
クラス内で呼び出す場合、scene
はthis
になります。あとはx座標, y座標, ボタンに表示したいテキスト、その他もろもろ(今回はクリックされたときのイベント)を引数として渡します。
実行結果
背景色が #cccccc の所にボタンを置いてみました!
まとめ
文字色、ボーダーなどをいろいろ触ればより良いボタンが作れると思います。これを応用すればボタン以外のUIコンポーネントも作成可能です。よりよくするアイデアがある方はコメントをお願いします!
Phaser3で遊ぶ用のリポジトリに実例を挙げているので、分かりにくかった方はこちらもご参照ください!
phaser-game : Github
参考
Web屋がJavaScriptでゲームを作ってSteamで配信するまでの道のり
https://qiita.com/laineus/items/0bb62f58910ccdfa1d34
https://github.com/laineus/unsung-kingdom