76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
import { _decorator, Component, Node, tween, Vec3, Sprite, UITransform } from "cc";
|
||
const { ccclass, property } = _decorator;
|
||
|
||
@ccclass("HintManager")
|
||
export class HintManager extends Component {
|
||
@property(Node)
|
||
handNode: Node | null = null; // 编辑器里拖一只手的 sprite 节点
|
||
|
||
private runningTween: any = null;
|
||
|
||
// 传入 getHint 的结果
|
||
showHint(hint: any, getPos: (r: number, c: number) => Vec3) {
|
||
if (!this.handNode) return;
|
||
|
||
// 清理之前的动画
|
||
if (this.runningTween) {
|
||
this.runningTween.stop();
|
||
this.runningTween = null;
|
||
}
|
||
|
||
if (!hint.from || !hint.dir || hint.steps == null) return;
|
||
|
||
const { from, dir, steps } = hint;
|
||
const dr = dir.dr;
|
||
const dc = dir.dc;
|
||
|
||
// 生成路径格子(起点 + dir * step)
|
||
const pathCells: { r: number; c: number }[] = [];
|
||
for (let s = 0; s <= steps; s++) {
|
||
pathCells.push({ r: from.r + dr * s, c: from.c + dc * s });
|
||
}
|
||
|
||
// 转换成 UI 坐标
|
||
const positions: Vec3[] = pathCells.map(cell => getPos(cell.r, cell.c));
|
||
|
||
const startPos = positions[0];
|
||
this.handNode.active = true;
|
||
this.handNode.setSiblingIndex(this.handNode.parent.children.length - 1);
|
||
this.handNode.setPosition(startPos);
|
||
|
||
// 构建单向滑动动画(格子之间平均时间)
|
||
const durationPerCell = 1 / steps;
|
||
let tw = tween(this.handNode);
|
||
for (let i = 1; i < positions.length; i++) {
|
||
tw = tw.to(durationPerCell, { position: positions[i] });
|
||
}
|
||
|
||
// 到终点瞬间回起点
|
||
tw = tw.call(() => this.handNode.setPosition(startPos));
|
||
|
||
// 重复 3 次
|
||
this.runningTween = tween(this.handNode)
|
||
.repeat(3, tw)
|
||
.call(() => {
|
||
this.handNode.active = false;
|
||
this.runningTween = null;
|
||
})
|
||
.start();
|
||
}
|
||
|
||
cancelHint() {
|
||
if (this.runningTween) {
|
||
try {
|
||
this.runningTween.stop();
|
||
} catch (e) {
|
||
console.warn("停止手势动画失败", e);
|
||
}
|
||
this.runningTween = null;
|
||
}
|
||
if (this.handNode) {
|
||
this.handNode.active = false;
|
||
}
|
||
}
|
||
|
||
}
|