86 lines
3.1 KiB
TypeScript
86 lines
3.1 KiB
TypeScript
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();
|
|
}
|
|
}
|