You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:将子弹正弦轨迹动画从基于速度改为基于时间

基于时间控制的子弹正弦轨迹动画解决方案

我明白你想要的效果:让子弹在指定时长内沿正弦轨迹从起点飞到终点,不再依赖固定的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的时间精度问题,导致子弹在到达后还会有微小移动。

额外优化建议

  1. 移除不再需要的speed参数:既然已经用时间控制,this.speed可以删掉了,减少冗余。
  2. 调整正弦轨迹参数:如果觉得正弦波的频率或幅度不合适,可以修改this.period和this.amplitude,比如把this.period = this.total / 2改成this.total / 3可以让正弦波更密集。

完整测试效果

你可以修改this.time的值(比如设为1000就是1秒,3000就是3秒),测试子弹是否在指定时间内精准到达终点,轨迹保持原来的正弦曲线。

内容的提问来源于stack exchange,提问作者Mevia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:06:43