import * as Phaser from "phaser"; /** * 用于绘制 LED / 七段数码管风格数字、冒号和百分号的工具类。 */ export class DigitRenderer { /** * 在给定的 Graphics 对象上绘制单个七段数码管数字。 * 传入 digit = -1 绘制空白(所有段关闭)。 * @param graphics 图形对象 * @param digit 要绘制的数字(0-9,-1为空白) * @param color 颜色值 * @param width 数字宽度 * @param height 数字高度 */ static drawDigit( graphics: Phaser.GameObjects.Graphics, digit: number, color: number, width: number, height: number, ): void { graphics.clear(); // 七段定义:a(顶部), b(右上), c(右下), d(底部), e(左下), f(左上), g(中间) const segments: { [key: number]: boolean[] } = { [-1]: [false, false, false, false, false, false, false], 0: [true, true, true, true, true, true, false], 1: [false, true, true, false, false, false, false], 2: [true, true, false, true, true, false, true], 3: [true, true, true, true, false, false, true], 4: [false, true, true, false, false, true, true], 5: [true, false, true, true, false, true, true], 6: [true, false, true, true, true, true, true], 7: [true, true, true, false, false, false, false], 8: [true, true, true, true, true, true, true], 9: [true, true, true, true, false, true, true], }; const segs = segments[digit] || segments[0]; const segW = width * 0.7; // 水平段宽度 const segH = height * 0.12; // 水平段高度 const segVW = segH; // 垂直段宽度 const segVH = (height - segH * 3) / 2; // 垂直段高度 const gap = 2; // 段之间的间隔 const glowAlpha = 0.1; // 发光效果透明度 /** * 绘制单个梯形段。 * @param cx 中心X坐标 * @param cy 中心Y坐标 * @param w 宽度 * @param h 高度 * @param isHorizontal 是否为水平段 * @param isOn 是否点亮 */ const drawSegment = ( cx: number, cy: number, w: number, h: number, isHorizontal: boolean, isOn: boolean, ) => { if (!isOn) { return; } // 发光效果 graphics.fillStyle(color, glowAlpha); if (isHorizontal) { graphics.fillRect(cx - w / 2 - 2, cy - h / 2 - 2, w + 4, h + 4); } else { graphics.fillRect(cx - h / 2 - 2, cy - w / 2 - 2, h + 4, w + 4); } graphics.fillStyle(color, 1); if (isHorizontal) { // 水平梯形段 const points = [ { x: cx - w / 2 + h / 2, y: cy - h / 2 }, { x: cx + w / 2 - h / 2, y: cy - h / 2 }, { x: cx + w / 2, y: cy }, { x: cx + w / 2 - h / 2, y: cy + h / 2 }, { x: cx - w / 2 + h / 2, y: cy + h / 2 }, { x: cx - w / 2, y: cy }, ]; graphics.beginPath(); graphics.moveTo(points[0].x, points[0].y); for (let i = 1; i < points.length; i++) { graphics.lineTo(points[i].x, points[i].y); } graphics.closePath(); graphics.fillPath(); } else { // 垂直梯形段 const points = [ { x: cx, y: cy - w / 2 }, { x: cx + h / 2, y: cy - w / 2 + h / 2 }, { x: cx + h / 2, y: cy + w / 2 - h / 2 }, { x: cx, y: cy + w / 2 }, { x: cx - h / 2, y: cy + w / 2 - h / 2 }, { x: cx - h / 2, y: cy - w / 2 + h / 2 }, ]; graphics.beginPath(); graphics.moveTo(points[0].x, points[0].y); for (let i = 1; i < points.length; i++) { graphics.lineTo(points[i].x, points[i].y); } graphics.closePath(); graphics.fillPath(); } }; const halfW = width / 2; const halfH = height / 2; // a - 顶部水平段 drawSegment(0, -halfH + segH / 2 + gap, segW, segH, true, segs[0]); // b - 右上垂直段 drawSegment( halfW - segVW / 2 - gap, -halfH / 2, segVH, segVW, false, segs[1], ); // c - 右下垂直段 drawSegment( halfW - segVW / 2 - gap, halfH / 2, segVH, segVW, false, segs[2], ); // d - 底部水平段 drawSegment(0, halfH - segH / 2 - gap, segW, segH, true, segs[3]); // e - 左下垂直段 drawSegment( -halfW + segVW / 2 + gap, halfH / 2, segVH, segVW, false, segs[4], ); // f - 左上垂直段 drawSegment( -halfW + segVW / 2 + gap, -halfH / 2, segVH, segVW, false, segs[5], ); // g - 中间水平段 drawSegment(0, 0, segW, segH, true, segs[6]); } /** * 绘制冒号(两个点),用于分钟和秒钟数字之间。 * @param graphics 图形对象 * @param color 颜色值 * @param digitWidth 数字宽度(用于计算缩放) */ static drawColon( graphics: Phaser.GameObjects.Graphics, color: number, digitWidth: number, ): void { graphics.clear(); const scale = digitWidth > 0 ? digitWidth / 20 : 1; const dotSize = 3 * scale; const spacing = 8 * scale; // 发光效果 graphics.fillStyle(color, 0.1); graphics.fillCircle(0, -spacing, dotSize + 2 * scale); graphics.fillCircle(0, spacing, dotSize + 2 * scale); // 主体 graphics.fillStyle(color, 1); graphics.fillCircle(0, -spacing, dotSize); graphics.fillCircle(0, spacing, dotSize); } /** * 绘制百分号(%),用于进度显示。 * @param graphics 图形对象 * @param color 颜色值 * @param digitHeight 数字高度(用于计算缩放) */ static drawPercentSign( graphics: Phaser.GameObjects.Graphics, color: number, digitHeight: number, ): void { graphics.clear(); const scale = digitHeight > 0 ? digitHeight / 36 : 1; const dotR = 3 * scale; const x = 4; const yTop = -10 * scale; const yBottom = 10 * scale; const dotOffsetX = 6 * scale; // 点与斜线之间的间隔 const dotLineGap = 4 * scale; // 发光效果 graphics.lineStyle(4.5 * scale, color, 0.25); graphics.beginPath(); graphics.moveTo(x - dotOffsetX, yBottom + dotLineGap); graphics.lineTo(x + dotOffsetX, yTop - dotLineGap); graphics.strokePath(); graphics.fillStyle(color, 0.25); graphics.fillCircle(x - dotOffsetX, yTop, dotR + 1.5 * scale); graphics.fillCircle(x + dotOffsetX, yBottom, dotR + 1.5 * scale); // 主体 graphics.lineStyle(3.2 * scale, color, 1); graphics.beginPath(); graphics.moveTo(x - dotOffsetX, yBottom + dotLineGap); graphics.lineTo(x + dotOffsetX, yTop - dotLineGap); graphics.strokePath(); graphics.fillStyle(color, 1); graphics.fillCircle(x - dotOffsetX, yTop, dotR); graphics.fillCircle(x + dotOffsetX, yBottom, dotR); } }