求助:将子弹正弦轨迹动画从基于速度改为基于时间
基于时间控制的子弹正弦轨迹动画解决方案
我明白你想要的效果:让子弹在指定时长内沿正弦轨迹从起点飞到终点,不再依赖固定的speed参数。核心思路是用时间进度比例来替代原来的距离累加逻辑,这样就能精准控制飞行时间了。
关键修改思路
原来的逻辑是通过speed不断累加飞行距离,现在我们改用「已飞行时间/总时长」得到一个0~1的进度值t,用这个t来计算当前位置和正弦偏差,这样不管总时长设成1秒还是5秒,子弹都会刚好在指定时间到达终点。
修改后的move函数代码
直接替换你原来的move方法就行,我会逐行解释:
this.move = function() { // 1. 计算已飞行时间与总时长的比例,限制在0~1之间(避免超过终点后继续移动) this.elapsed = Date.now() - this.started; const t = Math.min(this.elapsed / this.time, 1); // 2. 根据时间进度计算当前应该飞行的距离(总距离 × 进度) const progress = t * this.total; // 3. 更新剩余距离(用于判断是否移除子弹) this.remaining = this.total - progress; // 4. 计算基础直线运动的位置 this.x = this.ix + Math.cos(this.rad) * progress; this.y = this.iy + Math.sin(this.rad) * progress; // 5. 计算正弦轨迹的偏移量(和原来的逻辑一致,但用progress替代distance) const deviation = Math.sin(progress * Math.PI / this.period) * this.amplitude; this.x += Math.sin(this.rad) * deviation; this.y -= Math.cos(this.rad) * deviation; // 可选:如果已经到达终点,直接锁定位置(避免微小的时间误差) if (t >= 1) { this.x = this.dx; this.y = this.dy; } };
代码解释
- 时间进度
t:Math.min(this.elapsed / this.time, 1)确保当已飞行时间超过总时长时,进度直接设为1,子弹停在终点。 - 进度转距离
progress:用总距离乘以时间进度,保证在t=1时刚好走完所有距离。 - 正弦偏移:保持你原来的正弦曲线逻辑,只是把原来的
this.distance换成progress,这样偏移量会随时间均匀变化,轨迹和原来一致,但速度由时间控制。 - 终点锁定:最后加的判断可以避免因为
requestAnimationFrame的时间精度问题,导致子弹在到达后还会有微小移动。
额外优化建议
- 移除不再需要的
speed参数:既然已经用时间控制,this.speed可以删掉了,减少冗余。 - 调整正弦轨迹参数:如果觉得正弦波的频率或幅度不合适,可以修改
this.period和this.amplitude,比如把this.period = this.total / 2改成this.total / 3可以让正弦波更密集。
完整测试效果
你可以修改this.time的值(比如设为1000就是1秒,3000就是3秒),测试子弹是否在指定时间内精准到达终点,轨迹保持原来的正弦曲线。
内容的提问来源于stack exchange,提问作者Mevia
相关产品推荐
相关产品推荐

