LoginSignup
3
0

More than 3 years have passed since last update.

Phaser3でボタンクラスを作る

Posted at

あらすじ

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クラス内で呼び出す場合、scenethisになります。あとはx座標, y座標, ボタンに表示したいテキスト、その他もろもろ(今回はクリックされたときのイベント)を引数として渡します。

実行結果

2020_0803_2016.png

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

まとめ

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

Phaser3で遊ぶ用のリポジトリに実例を挙げているので、分かりにくかった方はこちらもご参照ください!
phaser-game : Github

参考

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

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0