Phaser3でボタンクラスを作る

## あらすじ
Phaser3でUIコンポーネントを別クラスに自作する方法をボタンクラスを例に書いていこうと思います。UIコンポーネントを別クラスに記述できると複数人での作業の分担などが行いやすくなるので、役に立つのではないのでしょうか？
(あと、Atomic Designのようなコンポーネントをファイル等で分ける前提の手法もとれるようになりますね)
## やり方
### プログラム全文
``` TypeScript
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受け取り
```TypeScript
        this.scene = scene;
        this.scene.add.existing(this);

        this.setSize(width, height).setInteractive();
```

シーンを受け取り、```this.scene```に詰め込むことでどこでも扱えるようにします。```setInteractive```は呼び出さないと後述する```this.on```が使えなくなるので気を付けましょう。

###### パーツ宣言
```TypeScript
		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等の作成
```TypeScript
		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```はクリック時の処理を行っています。

### ボタンクラス呼出し
```TypeScript
this.button = new Button(scene, x, y, text, {
	onClick: () =>{
		console.log("Click!!");
	}
})
```

ボタンクラスを```Phaser.Scene```クラス内で呼び出す場合、```scene```は```this```になります。あとはx座標, y座標,　ボタンに表示したいテキスト、その他もろもろ(今回はクリックされたときのイベント)を引数として渡します。

## 実行結果
![2020_0803_2016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323150/a7addd06-1ef9-12ed-693f-3e7d15ecdc9a.png)

背景色が #cccccc の所にボタンを置いてみました！

## まとめ
文字色、ボーダーなどをいろいろ触ればより良いボタンが作れると思います。これを応用すればボタン以外のUIコンポーネントも作成可能です。よりよくするアイデアがある方はコメントをお願いします！

Phaser3で遊ぶ用のリポジトリに実例を挙げているので、分かりにくかった方はこちらもご参照ください！
[phaser-game : Github](https://github.com/S-Kaito/phaser-games)

## 参考
Web屋がJavaScriptでゲームを作ってSteamで配信するまでの道のり
https://qiita.com/laineus/items/0bb62f58910ccdfa1d34
https://github.com/laineus/unsung-kingdom