MatchMaster/assets/Script/GuideHand.ts
2026-09-16 18:13:28 +08:00

86 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { ccclass, property } = cc._decorator;
@ccclass
export default class GuideHand extends cc.Component {
@property(cc.Material)
rippleMaterial: cc.Material = null;
@property
swingAngle: number = 8;
@property
ringWidth: number = 0.1;
@property(cc.Vec2)
tipPosition: cc.Vec2 = cc.v2(-58, 148);
private baseAngle: number = 0;
private elapsed: number = 0;
private rippleDuration: number = 0;
private ripple: cc.Node = null;
private material: cc.Material = null;
onLoad() {
this.baseAngle = this.node.angle;
const ripple = this.ripple = new cc.Node("handRipple");
ripple.active = false;
ripple.parent = this.node.parent;
// 光圈放在手的后面,独立于手旋转,点击位置保持不动。
ripple.setSiblingIndex(this.node.getSiblingIndex());
const sprite = ripple.addComponent(cc.Sprite);
sprite.spriteFrame = this.node.getComponent(cc.Sprite).spriteFrame;
sprite.sizeMode = cc.Sprite.SizeMode.CUSTOM;
ripple.setContentSize(220, 220);
sprite.setMaterial(0, this.rippleMaterial);
this.material = sprite.getMaterial(0);
this.material.setProperty("ringWidth", this.ringWidth);
this.material.setProperty("center", [0.5, 0.5]);
// 对齐 ripple_shrink:第三圈延后 0.6 秒,扩散到半径 0.475 时完全淡出。
this.rippleDuration = 0.6 + 0.475 / Number(this.material.getProperty("waveSpeed", 0));
}
onEnable() {
this.elapsed = 0;
this.node.angle = this.baseAngle;
this.ripple.active = false;
this.material.setProperty("time", 0);
}
update(dt: number) {
const pressDuration = 0.24;
const releaseDuration = 0.32;
const cycleDuration = pressDuration + this.rippleDuration;
const previousTime = this.elapsed;
this.elapsed = (this.elapsed + dt) % cycleDuration;
if (this.elapsed < previousTime) this.ripple.active = false;
const progress = this.elapsed < pressDuration
? this.elapsed / pressDuration
: Math.max(0, 1 - (this.elapsed - pressDuration) / releaseDuration);
this.node.angle = this.baseAngle + this.swingAngle * (1 - Math.cos(progress * Math.PI)) / 2;
if (this.elapsed < pressDuration) {
this.ripple.active = false;
return;
}
if (!this.ripple.active) {
// 按下瞬间的指尖坐标;松手时光圈不跟着移动。
const angle = this.node.angle;
this.node.angle = this.baseAngle + this.swingAngle;
const tip = this.node.convertToWorldSpaceAR(this.tipPosition);
this.ripple.setPosition(this.node.parent.convertToNodeSpaceAR(tip));
this.node.angle = angle;
this.ripple.active = true;
}
this.material.setProperty("time", this.elapsed - pressDuration);
}
onDisable() {
this.node.angle = this.baseAngle;
if (cc.isValid(this.ripple)) this.ripple.active = false;
}
onDestroy() {
if (cc.isValid(this.ripple)) this.ripple.destroy();
}
}