コンテンツにスキップ

Glitch Text (グリッチ)

サイバーパンクな世界観や、システムエラー、ホラー演出などに最適な「グリッチ(故障)」エフェクトです。 ランダムな確率で文字列を書き換えたり、位置を微妙にずらすことで、不安定な状態を表現します。

TimerEvent を使用して、一定間隔でテキストの状態をランダムに変化させるメソッドです。 強いグリッチ、弱いグリッチ、正常状態を確率で切り替えています。

/**
* テキストにグリッチエフェクトを適用する
* @param target 対象のテキストオブジェクト
* @param originalText 元のテキスト(省略時はtarget.textを使用)
*/
public startGlitch(target: Phaser.GameObjects.Text, originalText?: string) {
const baseText = originalText || target.text;
const startX = target.x;
const startY = target.y;
// グリッチ用文字セット(プライベートプロパティなどに持つと良い)
const glitchChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#@&%$';
this.time.addEvent({
delay: 100, // 0.1秒ごとにチェック
loop: true,
callback: () => {
const rand = Math.random();
if (rand < 0.05) {
// 強いグリッチ: 文字列を大幅に変える & 位置ズレ
target.setText(this.getRandomString(baseText.length, glitchChars));
target.setPosition(startX + Phaser.Math.Between(-5, 5), startY + Phaser.Math.Between(-5, 5));
target.setColor('#00ffff');
target.setAlpha(0.8);
} else if (rand < 0.2) {
// 弱いグリッチ: 1文字だけ変える
target.setText(this.replaceRandomChar(baseText, glitchChars));
target.setPosition(startX, startY);
target.setColor('#ff0000');
target.setAlpha(1);
} else {
// 正常に戻す
target.setText(baseText);
target.setPosition(startX, startY);
target.setColor('#ff0000');
target.setAlpha(1);
}
}
});
}

getRandomStringreplaceRandomChar は別途ヘルパーメソッドとして実装が必要です(完全なソースコード参照)。

create() {
const label = this.add.text(400, 200, 'SYSTEM_ERROR', {
fontSize: '64px',
color: '#ff0000',
fontStyle: 'bold'
}).setOrigin(0.5);
// グリッチ開始
this.startGlitch(label);
}
クラス全体を見る
import Phaser from 'phaser';
export class GlitchScene extends Phaser.Scene {
private glitchChars: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#@&%$';
constructor() {
super({ key: 'GlitchScene' });
}
create() {
this.add.text(10, 10, 'Glitch Demo', {
fontFamily: '"Noto Sans JP", sans-serif',
fontSize: '24px',
color: '#00ff00'
});
// 基準となるテキスト
const originalText = 'SYSTEM_ERROR';
const textObject = this.add.text(400, 200, originalText, {
fontFamily: '"Noto Sans JP", sans-serif',
fontSize: '64px',
color: '#ff0000',
fontStyle: 'bold'
}).setOrigin(0.5);
// グリッチエフェクトを開始
this.startGlitch(textObject);
}
/**
* テキストにグリッチエフェクトを適用する
* @param target 対象のテキストオブジェクト
* @param originalText 元のテキスト(省略時はtarget.textを使用)
*/
public startGlitch(target: Phaser.GameObjects.Text, originalText?: string) {
const baseText = originalText || target.text;
const startX = target.x;
const startY = target.y;
this.time.addEvent({
delay: 100, // 0.1秒ごとにチェック
loop: true,
callback: () => {
// 5%の確率で強いグリッチ、15%で弱いグリッチ
const rand = Math.random();
if (rand < 0.05) {
// 強いグリッチ: 文字列を大幅に変える & 位置ズレ
target.setText(this.getRandomString(baseText.length));
target.setPosition(startX + Phaser.Math.Between(-5, 5), startY + Phaser.Math.Between(-5, 5));
target.setColor('#00ffff');
target.setAlpha(0.8);
} else if (rand < 0.2) {
// 弱いグリッチ: 1文字だけ変える
target.setText(this.replaceRandomChar(baseText));
target.setPosition(startX, startY);
target.setColor('#ff0000');
target.setAlpha(1);
} else {
// 正常に戻す
target.setText(baseText);
target.setPosition(startX, startY);
target.setColor('#ff0000');
target.setAlpha(1);
}
}
});
}
private getRandomString(length: number): string {
let result = '';
for (let i = 0; i < length; i++) {
result += this.glitchChars.charAt(Math.floor(Math.random() * this.glitchChars.length));
}
return result;
}
private replaceRandomChar(text: string): string {
const index = Math.floor(Math.random() * text.length);
const char = this.glitchChars.charAt(Math.floor(Math.random() * this.glitchChars.length));
return text.substring(0, index) + char + text.substring(index + 1);
}
}
  1. 確率的な分岐: 常時バグっていると読みづらいため、Math.random() < 0.05 のように低い確率でのみ強い崩れを発生させ、普段は正常か軽微なノイズに留めるのがコツです。

  2. 位置ズレ (Shake): 文字を変えるだけでなく、setPosition で座標を数ピクセルずらすことで、画面の揺れや同期ズレのような不穏な空気感を演出できます。

  3. 色の変化: エラー時には赤からシアン(水色)などに色を変えることで、視覚的なインパクトを強化できます。