- 玩法一 数字一笔:规则库、求解器、26 关、竖屏触摸 Web 原型、测试 - 玩法二 连连气球:连消畅玩版核心、Web 原型、Cocos 球槽组件与导出脚本 - 玩法三 六边一笔:规则库、求解器、10 关 + 转墙实验包、Web 原型、测试 - 产品文档、UI 设计规范、各玩法 GDD / HANDOFF - 文档移除全部外部参考作引用;删除玩法二 v0 旧稿
81 lines
2.4 KiB
TypeScript
81 lines
2.4 KiB
TypeScript
// Painter 的 Canvas 2D 实现。Cocos 版本换成 Graphics + Label 即可,HexBoardView 不用改。
|
|
import type { Point } from '../src/geom';
|
|
import type { Painter } from '../src/painter';
|
|
|
|
export class CanvasPainter implements Painter {
|
|
private readonly ctx: CanvasRenderingContext2D;
|
|
private readonly fontFamily =
|
|
'"SF Pro Rounded", "PingFang SC", "Helvetica Neue", "Segoe UI", system-ui, -apple-system, sans-serif';
|
|
|
|
constructor(ctx: CanvasRenderingContext2D) {
|
|
this.ctx = ctx;
|
|
}
|
|
|
|
private path(pts: Point[]): void {
|
|
const ctx = this.ctx;
|
|
ctx.beginPath();
|
|
ctx.moveTo(pts[0].x, pts[0].y);
|
|
for (let i = 1; i < pts.length; i++) ctx.lineTo(pts[i].x, pts[i].y);
|
|
ctx.closePath();
|
|
}
|
|
|
|
fillPolygon(pts: Point[], color: string, alpha = 1): void {
|
|
if (alpha <= 0 || pts.length < 3) return;
|
|
const ctx = this.ctx;
|
|
ctx.globalAlpha = alpha;
|
|
ctx.fillStyle = color;
|
|
this.path(pts);
|
|
ctx.fill();
|
|
ctx.globalAlpha = 1;
|
|
}
|
|
|
|
strokePolygon(pts: Point[], color: string, lineWidth: number, alpha = 1): void {
|
|
if (alpha <= 0 || pts.length < 2) return;
|
|
const ctx = this.ctx;
|
|
ctx.globalAlpha = alpha;
|
|
ctx.strokeStyle = color;
|
|
ctx.lineWidth = lineWidth;
|
|
ctx.lineJoin = 'round';
|
|
this.path(pts);
|
|
ctx.stroke();
|
|
ctx.globalAlpha = 1;
|
|
}
|
|
|
|
line(x1: number, y1: number, x2: number, y2: number, width: number, color: string, alpha = 1): void {
|
|
if (alpha <= 0) return;
|
|
const ctx = this.ctx;
|
|
ctx.globalAlpha = alpha;
|
|
ctx.strokeStyle = color;
|
|
ctx.lineWidth = width;
|
|
ctx.lineCap = 'round';
|
|
ctx.beginPath();
|
|
ctx.moveTo(x1, y1);
|
|
ctx.lineTo(x2, y2);
|
|
ctx.stroke();
|
|
ctx.globalAlpha = 1;
|
|
}
|
|
|
|
fillCircle(cx: number, cy: number, radius: number, color: string, alpha = 1): void {
|
|
if (alpha <= 0) return;
|
|
const ctx = this.ctx;
|
|
ctx.globalAlpha = alpha;
|
|
ctx.fillStyle = color;
|
|
ctx.beginPath();
|
|
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
|
|
ctx.fill();
|
|
ctx.globalAlpha = 1;
|
|
}
|
|
|
|
text(s: string, cx: number, cy: number, size: number, color: string, bold = false, alpha = 1): void {
|
|
if (alpha <= 0) return;
|
|
const ctx = this.ctx;
|
|
ctx.globalAlpha = alpha;
|
|
ctx.fillStyle = color;
|
|
ctx.font = `${bold ? '700' : '500'} ${size}px ${this.fontFamily}`;
|
|
ctx.textAlign = 'center';
|
|
ctx.textBaseline = 'middle';
|
|
ctx.fillText(s, cx, cy + size * 0.04);
|
|
ctx.globalAlpha = 1;
|
|
}
|
|
}
|