Files
cocos-hehe/assets/Scripts/Block.ts
leiyuwei 1342dfb078 fix: 所有 Graphics 节点添加 UITransform,修复 CC 3.8.8 空白问题
CC 3.8.8 中 UI 渲染管线要求 Graphics 节点自身必须有 UITransform 组件,
否则不会提交渲染。所有 Graphics 节点(方块/棋盘/UI)均已补充。
2026-06-16 13:46:05 +08:00

124 lines
3.0 KiB
TypeScript

/**
* 方块组件 — Graphics 绘制色块,不依赖外部纹理
*/
import { _decorator, Component, Node, Graphics, Color, UITransform, Label, tween, v3 } from 'cc';
import { CELL, conf } from './BlockConfig';
const { ccclass } = _decorator;
@ccclass('Block')
export class Block extends Component {
public row = -1;
public col = -1;
public level = 1;
public isMerging = false;
private _gfx!: Graphics;
private _label!: Label;
private _selected = false;
onLoad() {
this.node.addComponent(UITransform).setContentSize(CELL, CELL);
// 用 Graphics 画圆角矩形色块
const g = new Node('gfx');
this._gfx = g.addComponent(Graphics);
g.addComponent(UITransform).setContentSize(CELL, CELL);
this.node.addChild(g);
// 等级文字
const lb = new Node('lb');
this._label = lb.addComponent(Label);
this._label.fontSize = 24;
this._label.lineHeight = 28;
this._label.color = Color.WHITE.clone();
lb.addComponent(UITransform).setContentSize(CELL, CELL);
this.node.addChild(lb);
this.draw();
}
/** 初始化 */
init(row: number, col: number, level: number) {
this.row = row;
this.col = col;
this.level = level;
this.isMerging = false;
this._selected = false;
this.draw();
this.playSpawnAnim();
}
/** 合并升级 */
upgradeTo(lv: number) {
this.level = lv;
this.isMerging = false;
this.draw();
this.playMergeAnim();
}
/** 高亮/取消高亮 */
setHighlight(on: boolean) {
this._selected = on;
this.draw();
}
private draw() {
const c = conf(this.level).color;
const col = this._hexToColor(c);
this._gfx.clear();
const s = CELL - 4;
const h = s / 2;
const r = 6;
// 填充
this._gfx.fillColor = col;
this._gfx.roundRect(-h, -h, s, s, r);
this._gfx.fill();
// 选中高亮边框
if (this._selected) {
this._gfx.strokeColor = Color.WHITE;
this._gfx.lineWidth = 3;
this._gfx.roundRect(-h - 1, -h - 1, s + 2, s + 2, r + 1);
this._gfx.stroke();
}
this._gfx.fillColor = new Color(255, 255, 255, 50);
this._gfx.roundRect(-h + 4, -h + 4, s - 8, s / 3, 4);
this._gfx.fill();
this._label.string = `${this.level}`;
this._label.fontSize = 24 + Math.min(this.level * 2, 10);
}
// ---- 动画 ----
private playSpawnAnim() {
this.node.setScale(v3(0, 0, 1));
tween(this.node).to(0.2, { scale: v3(1, 1, 1) }, { easing: 'backOut' }).start();
}
private playMergeAnim() {
this.node.setScale(v3(1.4, 1.4, 1));
tween(this.node).to(0.35, { scale: v3(1, 1, 1) }, { easing: 'elasticOut' }).start();
}
playSnapBack(from: { x: number; y: number }, to: { x: number; y: number }) {
this.node.setPosition(from.x, from.y, 0);
tween(this.node).to(0.18, { position: v3(to.x, to.y, 0) }, { easing: 'sineOut' }).start();
}
// ---- 工具 ----
private _hexToColor(hex: string): Color {
return new Color(
parseInt(hex.slice(1, 3), 16),
parseInt(hex.slice(3, 5), 16),
parseInt(hex.slice(5, 7), 16),
255,
);
}
}