import { _decorator, Component, Node, Animation, Vec3 } from "cc"; const { ccclass, property } = _decorator; @ccclass('HeroMoveComp') export class HeroMoveComp extends Component { @property({ type: Node }) hero1: Node = null!; @property({ type: Node }) hero2: Node = null!; @property({ type: Node }) hero3: Node = null!; @property({ type: Node }) hero4: Node = null!; @property({ type: Node }) hero5: Node = null!; // 控制移动速度的基础参数 private baseSpeed: number = 20; // 每秒向右移动的基础像素速度 private timer: number = 0; // 为每个英雄保存其对应的 Animation 和随机参数 private heroDatas: { node: Node, anim: Animation | null, startX: number, phase: number }[] = []; onLoad() { const heroes = [this.hero1, this.hero2, this.hero3, this.hero4, this.hero5]; heroes.forEach(heroNode => { if (heroNode) { // 查找名为 "h" 的子节点 const hNode = heroNode.getChildByName("h"); let anim: Animation | null = null; if (hNode) { anim = hNode.getComponent(Animation); // 确保有动画组件才尝试播放 if (anim && anim.clips && anim.clips.length > 0) { anim.play("move"); } } this.heroDatas.push({ node: heroNode, anim: anim, startX: heroNode.position.x, // 记录初始X位置 phase: Math.random() * Math.PI * 2 // 随机初始相位 }); } }); } update(dt: number) { this.timer += dt; this.heroDatas.forEach(data => { if (!data.node) return; // 设置周期为 4 秒 (例如:1秒加速向右,1秒减速回原点,1秒减速向左,1秒加速回原点) // 使用正弦波控制速度,余弦波控制位移(因为速度是位移的导数) const cycleDuration = 4; const frequency = (Math.PI * 2) / cycleDuration; // 速度倍率,范围在 0.9 ~ 1.1 之间波动 // sin 波形在 4秒周期内,正负各占 2秒 const speedMultiplier = 1.0 + Math.sin(this.timer * frequency + data.phase) * 0.1; // 调整动画的播放速度 if (data.anim) { // 检查状态是否存在,以避免没有播放动画时的错误 const state = data.anim.getState("move"); if (state && state.isPlaying) { state.speed = speedMultiplier; } else if (data.anim.clips && data.anim.clips.length > 0) { // 如果停止了,尝试重新播放 data.anim.play("move"); } } // 根据时间计算位置偏移量 // 使用 -cos 函数,使得当速度(sin)为最大时,位置在原点, // 积分关系:速度 v = A * sin(wt),位移 s = - (A/w) * cos(wt) // 这样能保证在一个周期内它始终围绕原点往复运动,最终回到原始点 const maxOffset = 30; // 左右偏离原点的最大像素距离 const currentOffset = -Math.cos(this.timer * frequency + data.phase) * maxOffset; const pos = data.node.position; // 相对于初始点进行位置设置,确保周期性回到原始点 data.node.setPosition(new Vec3(data.startX + currentOffset, pos.y, pos.z)); }); } }