テキストを1文字ずつ表示させる ノベルゲームのようにテキストを1文字ずつ表示させるためのクラスDisplayTextByCharを紹介します。

DisplayTextByChar クラス

DisplayTextByCharは、PhaserのTextオブジェクトを拡張し、1文字ずつ表示する機能を追加したクラスです。

クラスのコンストラクタ

このクラスのコンストラクタは以下のパラメータを受け取ります:

  • scene: テキストを表示するPhaserのシーンオブジェクト。
  • x, y: テキストを表示する位置のX座標とY座標。
  • text: 表示するテキスト。
  • style: テキストのスタイルを定義するオブジェクト(フォントサイズや色など)。
  • delayDef: 各文字の表示間隔をミリ秒で指定します(デフォルトは100ミリ秒)。

クラスの実装

import Phaser from "phaser";

/**
 * 文字ごとにテキストを表示するクラス
 */
class DisplayTextByChar extends Phaser.GameObjects.Text {
  delayDef: number;
  timerEvent: Phaser.Time.TimerEvent;

  /**
   * コンストラクタ
   */
  constructor(
    scene: Phaser.Scene,
    x: number,
    y: number,
    text: string,
    style: Phaser.Types.GameObjects.Text.TextStyle,
    delayDef: number = 100
  ) {
    super(scene, x, y, "", style);
    this.delayDef = delayDef;
    this.timerEvent = scene.time.addEvent({});
    this.setStyle(style);
    scene.add.existing(this);
    this.startTextAnimation(text);
  }

  /**
   * テキスト表示の遅延時間を更新する
   */
  updateDelay(delay: number) {
    this.timerEvent.reset({
      delay: delay,
      repeat: this.timerEvent.repeatCount,
      callback: this.timerEvent.callback,
    });
  }

  /**
   * 次のテキストを設定する
   */
  setNextText(text: string) {
    this.text = "";
    this.timerEvent.remove();
    this.startTextAnimation(text);
  }

  /**
   * テキストをスキップする
   */
  skipText() {
    this.timerEvent.reset({
      delay: 0.1,
      repeat: this.timerEvent.repeatCount,
      callback: this.timerEvent.callback,
    });
  }

  /**
   * テキスト表示が完了したかを確認
   */
  isComplete(): boolean {
    return this.timerEvent.repeatCount === 0;
  }

  /**
   * テキストアニメーションを開始する
   */
  private startTextAnimation(text: string) {
    let i = 0;
    this.timerEvent = this.scene.time.addEvent({
      delay: this.delayDef,
      repeat: text.length - 1,
      callback: () => {
        if (i >= text.length) {
          return;
        }
        this.text += text[i];
        i++;
      },
    });
  }
}

export { DisplayTextByChar };

機能の説明

  • テキストオブジェクトの作成: Textオブジェクトを拡張し、指定されたスタイルでテキストを表示します。
  • テキストを1文字ずつ表示: Phaserのタイマーイベントを利用し、指定された遅延ごとに1文字ずつ追加します。
  • テキストの更新: setNextTextメソッドで新しいテキストをセットし、アニメーションを再開できます。
  • スキップ機能: skipTextメソッドで表示速度を最速にして、すぐに全文を表示できます。
  • 表示完了の判定: isCompleteメソッドでテキストの表示が終わったかどうかを確認できます。

使用例

以下のコードでDisplayTextByCharを使用してテキストを1文字ずつ表示できます。

import Phaser from 'phaser';
import { DisplayTextByChar } from './DisplayTextByChar';

class MyScene extends Phaser.Scene {
    constructor() {
        super('MyScene');
    }

    create() {
        const style = { fontSize: '32px', color: '#fff' };
        const textObj = new DisplayTextByChar(this, 100, 100, 'Hello, World!', style);
    }
}

ページ上部の画像は以下のコードで動いています。

import Phaser from 'phaser';
import { DisplayTextByChar } from './DisplayTextByChar';

const DEFAULT_WIDTH = 640;
const DEFAULT_HEIGHT = 480;

class MyScene extends Phaser.Scene {
    constructor() {
        super('MyScene');
    }

    create() {
        const style = { fontFamily: 'Arial', fontSize: '32px', color: '#ffffff' };
        new DisplayTextByChar(this, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2, 'Hello World!', style).setOrigin(0.5, 0.5);
    }
}

このクラスを利用することで、Phaser3で簡単にノベルゲームのようなテキストアニメーションを実装できます。