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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|