60pxの市松模様で10行、10列(縦横600px)の画像があったとします。

これを中心に配置すると以下のようになります。
./src/main.js

import Phaser from "phaser";
import GameScene from "./scenes/GameScene";

const config = {
    type: Phaser.AUTO,
    width: 1200,
    height: 600,
    parent: 'game-container',
    backgroundColor: '#fff',
    scale: {
        mode: Phaser.Scale.NONE,
        autoCenter: Phaser.Scale.CENTER_BOTH
    },
    dom: {
        createContainer: true
    },
    scene: [
        GameScene
    ]
};

export default new Phaser.Game(config);

./src/scenes/GameScene.js

import { Scene } from 'phaser';

export default class GameScene extends Phaser.Scene {
    constructor() {
        super('GameScene');
    }

    preload() {
        this.load.image("bg", "./assets/bg.png");
    }

    create() {
        const centerX = this.scale.width / 2;
        const centerY = this.scale.height / 2;
        const bg = this.add.image(centerX, centerY, "bg");
        bg.setOrigin(0.5);
    }

    update() {
    }
}

そのうち、左上を基準に、2行、4列(縦120px × 横240px)を表示しようとしてcropを使うと
./src/scenes/GameScene.js

import { Scene } from 'phaser';

export default class GameScene extends Phaser.Scene {
    constructor() {
        super('GameScene');
    }

    preload() {
        this.load.image("bg", "./assets/bg.png");
    }

    create() {
        const centerX = this.scale.width / 2;
        const centerY = this.scale.height / 2;
        const bg = this.add.image(centerX, centerY, "bg");
        bg.setOrigin(0.5);

        const cropX = 0;
        const cropY = 0;
        const cropWidth = 240;
        const cropHeight = 120;
        bg.setCrop(cropX, cropY, cropWidth, cropHeight);
    }

    update() {
    }
}

setOriginはあくまでも全体のサイズにおけるセンターのため、
切り取った部分をセンターにもっていくためには、調整が必要。

./src/scenes/GameScene.js

import { Scene } from 'phaser';

export default class GameScene extends Phaser.Scene {
    constructor() {
        super('GameScene');
    }

    preload() {
        this.load.image("bg", "./assets/bg.png");
    }

    create() {
        const centerX = this.scale.width / 2;
        const centerY = this.scale.height / 2;
        const width = 600;
        const height = 600;

        // 切り取り領域
        const cropX = 0;
        const cropY = 0;
        const cropWidth = 240;
        const cropHeight = 120;

        const bg = this.add.image(centerX + (width - cropWidth) / 2, centerY + (height - cropHeight) / 2, "bg");
        bg.setOrigin(0.5);
        bg.setCrop(cropX, cropY, cropWidth, cropHeight);
    }

    update() {
    }
}

どちらかというと、原点をセンターにするより、左上の位置から調整した方が楽ですね。

    create() {
        const centerX = this.scale.width / 2;
        const centerY = this.scale.height / 2;

        // 切り取り領域
        const cropX = 0;
        const cropY = 0;
        const cropWidth = 240;
        const cropHeight = 120;

        const bg = this.add.image(centerX - cropWidth / 2, centerY - cropHeight / 2, "bg");
        bg.setOrigin(0);
        bg.setCrop(cropX, cropY, cropWidth, cropHeight);
    }

1つの画像に同一サイズの画像をまとめているのであれば、SpriteSheetを使って切り出してつかうことができます。
↓縦横20pxのデータが8つある。

./src/scenes/GameScene.js

import { Scene } from 'phaser';

export default class GameScene extends Phaser.Scene {
    constructor() {
        super('GameScene');
    }

    preload() {
        this.load.spritesheet("charList", "./assets/CharList.png", { frameWidth: 20, frameHeight: 20 });
    }

    create() {
        const charList = [];

        for (let n = 0; n < 8; n++) {
            const row = 20 * Math.trunc(n / 4);
            const col = 20 * (n % 4);
            const char = this.add.image(col, row, "charList", n);
            char.setOrigin(0); // 原点は左上
            charList.push(char);
        }
    }

    update() {
    }
}

↓左上から2行4列で表示

投稿日時: 2024-08-14 15:34:14
更新日時: 2024-08-14 16:17:14

ボタンや、表といったものは、Phaserでは用意していないのでHTMLを追加することになります。
例えば、タイトル画面でゲーム開始ボタンを用意し、ゲーム画面に遷移するとします。

button要素一つ追加する例

DOMを追加する場合、configに dom : { createContainer : true } を追加する必要があります。
./src/main.js

import { AUTO, Scale, Game } from 'phaser';
import GameScene from './scenes/GameScene';
import TitleScene from './scenes/TitleScene';

//  Find out more information about the Game Config at:
//  https://newdocs.phaser.io/docs/3.70.0/Phaser.Types.Core.GameConfig
const config = {
    type: AUTO,
    width: 960,
    height: 540,
    parent: 'game-container',
    backgroundColor: '#FFF',
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH
    },
    scene: [
        TitleScene,
        GameScene
    ],
    dom: {
        createContainer: true
    },
};

export default new Game(config);

./src/scenes/TitleScene.js

import { Scene } from 'phaser';

export default class TitleScene extends Scene {
    constructor() {
        super('TitleScene');
    }

    preload() {
    }

    create() {
        const centerX = this.scale.width / 2;
        const centerY = this.scale.height / 2;

        const btnStartNode = document.createElement("button");
        btnStartNode.className = "btnStart btnStart--royalblue";
        btnStartNode.innerText = "ゲーム開始";
        btnStartNode.addEventListener("click", () => { this.scene.start("GameScene"); });

        const btnStart = this.add.dom(centerX, centerY, btnStartNode);
    }

    update() {
    }
}

./src/scenes/GameScene.js

import { Scene } from 'phaser';

export default class GameScene extends Scene {
    constructor() {
        super('GameScene');
    }

    preload() {
    }

    create() {
    }

    update() {
    }
}

./public/phaser.css


.btnStart {
    border: none;
    border-radius: 5px;
    color: white;
    font-size: 200%;
    padding: 10px 30px;
    text-align: center;
}

.btnStart--royalblue{
    background-color: royalblue;
    border-bottom: 5px solid rgb(48, 66, 133);
}

.btnStart--royalblue:hover {
    background: rgb(85, 125, 245);
    border-bottom: 2px solid rgb(48, 66, 133);
    margin-top: 2px;
}
DOMを追加しているので、イベントは通常のaddEventListenerで追加する。 追加した要素は、画面遷移とともに、消えています。

タイトル画面で、ゲームの種類を選択して画面遷移させたい場合など、複数の同一のボタンを用意したい場合

複数のボタンを追加する例

今度は、ボタンのクラスを作って配置してみます。
./src/main.js

import { Scene } from 'phaser';
import GameTypeButton from '../objects/GameTypeButton'

export default class TitleScene extends Scene {
    constructor() {
        super('TitleScene');
    }

    preload() {
    }

    create() {
        const centerX = this.scale.width / 2;
        const centerY = this.scale.height / 2;

        new GameTypeButton(this, centerX - 90, centerY, "Game1", () => { this.scene.start("GameScene"); });
        new GameTypeButton(this, centerX + 0, centerY, "Game2", () => { this.scene.start("GameScene2"); });
        new GameTypeButton(this, centerX + 90, centerY, "Game3", () => { this.scene.start("GameScene3"); });
    }

    update() {
    }
}

./scenes/TitleScene.js

import { Scene } from 'phaser';
import GameTypeButton from '../objects/GameTypeButton'

export default class TitleScene extends Scene {
    constructor() {
        super('TitleScene');
    }

    preload() {
    }

    create() {
        const centerX = this.scale.width / 2;
        const centerY = this.scale.height / 2;

        new GameTypeButton(this, centerX - 90, centerY, "Game1", () => { this.scene.start("GameScene"); });
        new GameTypeButton(this, centerX + 0, centerY, "Game2", () => { this.scene.start("GameScene2"); });
        new GameTypeButton(this, centerX + 90, centerY, "Game3", () => { this.scene.start("GameScene3"); });
    }

    update() {
    }
}

DOMを追加するクラスは、Phaser.GameObjects.DOMElementを継承します。
ここでは、親クラスには、scene, x, y, HTML要素を渡しています。
./src/objects/GameTypeButton.js

export default class GameTypeButton extends Phaser.GameObjects.DOMElement {
    constructor(scene, x, y, text, callback) {
        // HTML要素を作成
        const element = document.createElement('button');
        element.innerText = text;
        element.className = "btnStart btnStart--royalblue";

        super(scene, x, y, element);

        // シーンに追加
        scene.add.existing(this);

        // ボタンクリック時のコールバックを設定
        this.node.addEventListener('click', callback);
    }
}

./public/phaser.css


.btnStart {
    border: none;
    border-radius: 5px;
    color: white;
    font-size: 100%;
    padding: 5px 15px;
    text-align: center;
}

.btnStart--royalblue{
    background-color: royalblue;
    border-bottom: 5px solid rgb(48, 66, 133);
}

.btnStart--royalblue:hover {
    background: rgb(85, 125, 245);
    border-bottom: 2px solid rgb(48, 66, 133);
    margin-top: 2px;
}

./srcscenes/GameScene.js

import { Scene } from 'phaser';

export default class GameScene extends Scene {
    constructor() {
        super('GameScene');
    }

    preload() {
    }

    create() {
    }

    update() {
    }
}

./srcscenes/GameScene2.js

import { Scene } from 'phaser';

export default class GameScene2 extends Scene {
    constructor() {
        super('GameScene2');
    }

    preload() {
    }

    create() {
    }

    update() {
    }
}

./srcscenes/GameScene3.js

import { Scene } from 'phaser';

export default class GameScene3 extends Scene {
    constructor() {
        super('GameScene3');
    }

    preload() {
    }

    create() {
    }

    update() {
    }
}
それぞれクリックすると、画面遷移します。

大した、Styleじゃないので、CSSファイルにわけるのではなく、ソースとStyle一か所でまとめて管理したいというのであれば・・・

親クラスにStyleも渡す場合

cssに記載していた内容をクラス内にまとめるとすると・・・
./src/objects/GameTypeButton.js

export default class GameTypeButton extends Phaser.GameObjects.DOMElement {
    constructor(scene, x, y, text, callback) {

        const style = {
            backgroundColor: "royalblue",
            border: "none",
            borderBottom: "5px solid rgb(48, 66, 133)",
            borderRadius: "5px",
            color: "white",
            fontSize: "100%",
            marginTop: "0px",
            padding: "5px 15px",
            textAlign: "center",
        };

        super(scene, x, y, "button", style, text);

        this.setOrigin(0.5);
        scene.add.existing(this);

        // ボタンクリック時のコールバックを設定
        this.node.addEventListener('click', callback);

        // ホバー設定(over/outで代用)
        this.node.addEventListener('mouseover', () => {
            this.node.style.background = "rgb(85, 125, 245)";
            this.node.style.borderBottom = "2px solid rgb(48, 66, 133)";
            this.node.style.marginTop = "2px";
        });
        this.node.addEventListener('mouseout', () => {
            this.node.style.background = style.backgroundColor
            this.node.style.borderBottom = style.borderBottom;
            this.node.style.marginTop = style.marginTop;
        });
    }
}

ランキングのようなものとかなら、templateタグで用意しておいてゲーム画面外の要素として表示とかでよい気がする。

投稿日時: 2024-08-12 15:05:12
更新日時: 2024-08-13 06:13:13

ハッキングAPIにまとめてあったサイト
あとでよむ。


・脅威のモデル化のセキュリティの基礎
https://learn.microsoft.com/ja-jp/training/paths/tm-threat-modeling-fundamentals/

・メルカリの脅威モデリングプロセス
https://engineering.mercari.com/blog/entry/20220426-threat-modeling-at-mercari/

・機器のサイバーセキュリティ確保のためのセキュリティ検証の手引きを取りまとめました
https://www.meti.go.jp/press/2021/04/20210419003/20210419003.html

・セキュリティ・バイ・デザイン導入指南書
https://www.ipa.go.jp/jinzai/ics/core_human_resource/final_project/2022/ngi93u0000002kef-att/000100451.pdf

・Microsoft Threat Modeling Tool
https://learn.microsoft.com/ja-jp/azure/security/develop/threat-modeling-tool

・OWASP Threat Dragon
https://owasp.org/www-project-threat-dragon/

投稿日時: 2024-08-07 11:29:07

最近の投稿

タグ

アーカイブ

その他