【Phaser3入門】メッセージウィンドウ
環境
Phaser 3.55.2
メッセージウィンドウとは
主人公や語り部、登場人物が文字を使用して物語を進めるために必要なテキストエリアのこと
誰が話しているか、何を話しているかが伝わることが大事
種類
二種類あって
語り部の上に現れるタイプ
固定で(主に下半分に)表示されるタイプ
頭上タイプ
- 誰が話しているか分かりやすい
- 動きがあって面白い
- 移動するため内容が頭に入りにくい
固定タイプ
- 見る位置が変わらないので頭に入りやすい
- 絵や名前がないと誰が話しているか分かりにくい
- 単調なので飽きやすい
スタイル
文字
Phser3で決められるのはTextStyleで設定できる項目のみ
設定したい項目は設定されていたので嬉しい
公式サンプル
TextStyle
Property | Type | Sample | About |
---|---|---|---|
fontFamily | string | "yusei, sans-serif" | this.load.scripts("yusei ", ["assets/scripts/webfont.js"]); Webフォントなどロードした名前で呼ぶ, フォントの種類 |
fontSize | string | "32" | CSSと同じだけど文字列, 文字の大きさ |
fontStyle | string | "strong" | CSSと同じ文字列, 文字の太さ |
backgroundColor | string | "#95A69C" | CSSと同じ, 文字の背景色 |
color | string | "#B7BF8E" , "rgb(218, 193, 137)" | CSSと同じ, 文字の色 |
stroke | string | "#222A00" , "rgb(59, 44, 0)" | CSSと同じ, 文字の縁の色 |
strokeThickness | number | 3 | CSSと同じ, 文字の縁の太さ |
shadow | TextShadow | {offsetX: 2, offsetY: 1, color: "#000", blur: 2, stroke: true, fill: true} | 公式 TextShadow |
padding | TextPadding | { x: 10, y: 5 } | 公式 TextPadding |
align | string | left ,right ,center ,justify | 文字をどちらに寄せるか |
maxLines | number | 3 | 何行目まで表示させるか |
rtl | boolean | false | falseだと右から、trueだと左から |
baseLineX | number | 1.2 | ベースライン, CSSと同じ |
baseLineY | number | 1.4 | ベースライン, CSSと同じ |
wordWrap | TextWordWrap | TextWordWrap |
枠
枠として使うのであれば上記のものから選ぶのが良いかと考えた
実装
一番難易度の低いものから実装するため、下記を選択した
固定表示
Rectangleの枠
windowクラスを用意して、話すオブジェクト(キャラクター)のクラス内に持たせる
文字と四角を含むため、Containerの中に入れる
import Phaser from "phaser";
export class Window extends Phaser.GameObjects.Container {
private _width: integer;
private _height: integer;
private _margin: integer;
private _padding: integer;
private _msg: string;
private box: Phaser.GameObjects.Graphics;
private text: Phaser.GameObjects.Text;
constructor(scene: Phaser.Scene, x = 0, y = 0, width = 0, height = 0) {
super(scene, x, y);
if (width) {
this._width = width;
} else {
this._width = typeof scene.game.config.width == "string" ? parseInt(scene.game.config.width): scene.game.config.width;
}
if (height) {
this._height = height;
} else {
this._height = typeof scene.game.config.height == "string" ? parseInt(scene.game.config.height): scene.game.config.height;
}
this._margin = 10;
this._padding = 10;
this.box = new Phaser.GameObjects.Graphics(scene);
this.box.fillStyle(0x0000ff, 1);
this.box.fillRoundedRect(this._margin, this._margin, this._width - this._margin * 2, this._height - this._margin * 2, this._padding / 2);
this.box.lineStyle(2, 0xffffff, 1);
this.box.strokeRoundedRect(this._margin, this._margin, this._width - this._margin * 2, this._height - this._margin * 2, this._padding / 2);
this.add(this.box);
this._msg = "";
this.text = new Phaser.GameObjects.Text(scene, this._padding + this._margin, this._padding + this._margin, this._msg, { fontSize: "20px", color: "#fff" });
this.add(this.text);
scene.add.existing(this);
}
setMessage(text: string) {
this._msg = text;
this.text.text = this._msg;
}
getMessage() {
return this._msg;
}
}
問題
Phaser3にはwordWrap
というものが用意されていて、簡単に実装するとWidthで改行
なのだけれど、日本語にはスペースが無いせいでうまく改行されないので, wordWrapのcallback内で改行する必要がある
公式 wordwrap callback
new Phaser,GameObject.Text(scene, 0, 0, "これはサンプルのテキストでなんの意味もありませんがとても長いため改行が必要です。", {
wordWrap: { callback: callbackWordWrap, scope: this });
function callbackWordWrap(text) {
let windowWidth = 400;
let sizeOfString = 24;
let numOfString = windowWidth / sizeOfString;
let words = [];
for (let i = 0, max = Math.ceil(text.length / numOfString); i < max; i++) {
words[i] = text.substr(i * numOfString, numOfString);
}
if (text.length - numOfString * words.length > 0) {
words[words.length] = text.substr(numOfString * words.length, text.length - numOfString * words.length);
}
return words;
}
});
おまけ
テキスト送りを実装したのですが、UIでキー操作するのを目指して作っていたらかなりめんどくさかった(時間かかった)ので またまとめて行こうかなと思っています
そのときはnoteとかになるかも