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

抛体运动模拟器速度>10m/s时无限移动异常问题求助

抛体运动模拟器问题修复方案

问题1:速度>10m/s时抛体无限移动、不受重力影响

核心原因

  1. 角度赋值顺序错误:计算水平/竖直分速度vx、vy之后才设置angle,首次运行时angle为undefined,导致vx、vy为NaN;后续运行时虽有角度值,但位置计算依赖总时间t累加,位移公式逻辑完全错误。
  2. 位移计算逻辑错误:用总时间t计算位置,而非时间增量dt更新速度和位置,导致每次迭代的位移量随t无限增大,无法模拟匀变速下落过程。
  3. 语法错误:t =+ dt 应为 t += dt(即使修正此语法,总时间计算方式仍不符合物理模拟逻辑)。

修复步骤

  • 调整launchProjectile中角度赋值与分速度计算的顺序,先设置angle再计算vx、vy。
  • 改用增量式物理更新:每次迭代更新竖直速度vy(受重力影响),再用dt更新x、y位置,符合匀变速运动规律。
  • 修正y轴位置计算逻辑,匹配Canvas坐标系(y轴向下为正,重力使竖直速度逐渐减小并反向)。

问题2:Launch按钮需双击触发

核心原因

首次点击时angle未赋值,导致vx、vy为NaN,抛体无动作;第二次点击时angle已被上一次运行赋值,才会正常触发。修复角度赋值顺序后即可解决此问题。

修改后的完整代码

JavaScript部分

var theCanvas = document.getElementById("theCanvas");
var theContext = theCanvas.getContext("2d");
var theImage = document.getElementById("frog");
var ay = 9.81; // 重力加速度(SI单位)
var dt = 0.2; // 时间步长(秒)
var timer, vel, yo, xo, angle, vx, vy, x, y, colDiam;
var velSlider = document.getElementById("velSlider");
var collagenSlider = document.getElementById("collagenSlider");
var velReadout = document.getElementById("velReadout");
var collagenReadout = document.getElementById("collagenReadout");

function launchProjectile() {
  if (timer) {
    window.clearTimeout(timer);
    timer = null;
  }
  vel = Number(velSlider.value);
  colDiam = Number(collagenSlider.value);
  yo = 479; // 初始y位置(距顶部像素)
  xo = 6; // 初始x位置(距左侧像素)
  angle = 10 * Math.PI / 180; // 先设置角度(转换为弧度)
  vx = vel * Math.cos(angle); // 再计算水平分速度
  vy = vel * Math.sin(angle); // 再计算竖直分速度(向上为正)
  x = xo;
  y = yo;
  moveProjectile();
}

function drawProjectile() {
  theContext.clearRect(0, 0, theCanvas.width, theCanvas.height);
  theContext.drawImage(theImage, x, y, 100, 100);
}

function moveProjectile() {
  // 检查抛体是否在Canvas范围内(未落到地面下方)
  if (y < theCanvas.height - 100) { // 减去抛体高度,避免完全超出后才停止
    // 更新竖直速度:重力向下,所以vy减少(因为y轴向下为正)
    vy -= ay * dt;
    // 更新位置:水平匀速,竖直匀变速
    x += vx * dt + colDiam * 0.0109;
    y -= vy * dt; // vy向上为正,y减少表示向上,y增加表示向下(vy会逐渐变为负)
    
    // 计算射程并更新显示
    var range = (x - xo) * 0.00086805544619423;
    document.getElementById("rangeprint").innerHTML = `Range: ${range.toFixed(2)}`; 
    
    drawProjectile();
    timer = window.setTimeout(moveProjectile, 100 * dt);
  }
}

function showVel() {
  velReadout.innerHTML = velSlider.value;
}

function showCollagen() {
  collagenReadout.innerHTML = collagenSlider.value;
}

HTML部分

<div style="width:1000px; float:left; margin-left:auto; margin-right:auto;">
  <img src="https://static.wikia.nocookie.net/uncharted/images/2/26/Amazon_rainforest_1.png/revision/latest?cb=20200519083419" width="1224" height="572" style="position:absolute;">
  <canvas id="theCanvas" width="1224" height="572" style="position:relative;">
    Canvas not supported; please update your browser.
  </canvas>
  <div style="text-align:center">
    <input type="button" value="Launch!" onclick="launchProjectile();">
  </div>
  <p>
    <input type="range" id="velSlider" min="0" max="30" step="10" value="10" oninput="showVel();" onchange="showVel();">
    Initial velocity = <span id="velReadout">10</span> m/s
  </p>
  <p>
    <input type="range" id="collagenSlider" min="50" max="500" step="50" value="100" oninput="showCollagen();" onchange="showCollagen();">
    Collagen diameter = <span id="collagenReadout">100</span> nanometers
  </p>
  <p style="text-align:center" id="rangeprint">Range:</p>
</div>

<img id="frog" src="https://static.scientificamerican.com/sciam/cache/file/41DF7DA0-EE58-4259-AA815A390FB37C55_source.jpg" width="100" height="100" style="display:none;">

额外优化说明

  • 将青蛙图片设置为display:none,避免默认显示在页面上。
  • 射程显示保留两位小数,提升可读性。
  • 停止条件改为检查抛体是否超出Canvas底部(减去抛体高度),避免抛体完全消失后才停止模拟。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:44:55