Search code examples
javascripthtmlsimulationsimulator

My projectile motion simulator seems to be gradually increasing without the affect of gravity if velocity > 10 m/s


var theCanvas = document.getElementById("theCanvas");
  var theContext = theCanvas.getContext("2d");
  var theImage = document.getElementById("frog");
  var ay = 9.81; //gravity constant in SI units
  var dt = 0.2; //time step in seconds
  var timer, vel, yo, xo, a, angle, vx, vy, x, y, colDiam;
  var t = 0; //initial time
  var velSlider = document.getElementById("velSlider"); //intial speed in meters per second
  var collagenSlider = document.getElementById("collagenSlider");
  var velReadout = document.getElementById("velReadout"); //intial speed in meters per second
  var collagenReadout = document.getElementById("collagenReadout");

  function launchProjectile() {
    if (timer)  {
      window.clearTimeout(timer);
      timer=null;
    }
    t = 0;
    vel = Number(velSlider.value);
    colDiam = Number(collagenSlider.value);
    yo = 479; //pixels from top to start 
    xo = 6; //pixels from left to start
    vx = vel * Math.cos(angle);
    vy = vel * Math.sin(angle);
    angle = 10*Math.PI/180; // 45 degrees converted to radians
    x = xo; //position at t=0
    y = yo; //position at t=0
    moveProjectile();
  }
  function drawProjectile() {
    theContext.clearRect(0, 0, theCanvas.width, theCanvas.height);
    theContext.drawImage(theImage,x,y,100,100);
  }
  function moveProjectile() {
    if (y<480) {
      t =+ dt;
      x = (x + vx * t) + colDiam * .0109; 
      y = y - vy * t + .5*ay*(t*t);
      range = (x - xo) * 0.00086805544619423;
      document.getElementById("rangeprint").innerHTML = range; 
      drawProjectile();
      if (timer) window.clearTimeout(timer);
      timer = window.setTimeout(moveProjectile, 100*dt);  
    }
  }
  function showVel() {
    velReadout.innerHTML = velSlider.value;
  }
  function showCollagen() {
    collagenReadout.innerHTML = collagenSlider.value;
  }
<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>
    <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="position:relative;">

The code above seems to work perfectly when the velocity is set to 0. However, if the velocity is anything above 0, the projectile seems to move infinitely, way past the expected, and if left high enough all the way into 1000+ feet. Something is wrong here but I'm not sure how to fix it. PS: You have to double-click the Launch button because of HTML shenanigans.


Solution

  • You wrote:

    t =+ dt
    

    Which just assigns dt to t. I think you meant:

    t += dt
    

    Which adds dt to t.

    You also need to initialize angle before calculating vx and vy, that will fix your double click bug.

    var theCanvas = document.getElementById("theCanvas");
      var theContext = theCanvas.getContext("2d");
      var theImage = document.getElementById("frog");
      var ay = 9.81; //gravity constant in SI units
      var dt = 0.2; //time step in seconds
      var timer, vel, yo, xo, a, angle, vx, vy, x, y, colDiam;
      var t = 0; //initial time
      var velSlider = document.getElementById("velSlider"); //intial speed in meters per second
      var collagenSlider = document.getElementById("collagenSlider");
      var velReadout = document.getElementById("velReadout"); //intial speed in meters per second
      var collagenReadout = document.getElementById("collagenReadout");
    
      function launchProjectile() {
        if (timer)  {
          window.clearTimeout(timer);
          timer=null;
        }
        t = 0;
        vel = Number(velSlider.value);
        colDiam = Number(collagenSlider.value);
        yo = 479; //pixels from top to start 
        xo = 6; //pixels from left to start
        angle = 10*Math.PI/180; // 45 degrees converted to radians
        vx = vel * Math.cos(angle);
        vy = vel * Math.sin(angle);
        x = xo; //position at t=0
        y = yo; //position at t=0
        moveProjectile();
      }
      function drawProjectile() {
        theContext.clearRect(0, 0, theCanvas.width, theCanvas.height);
        theContext.drawImage(theImage,x,y,100,100);
      }
      function moveProjectile() {
        if (y<480) {
          t += dt;
          x = (x + vx * t) + colDiam * .0109; 
          y = y - vy * t + .5*ay*(t*t);
          range = (x - xo) * 0.00086805544619423;
          document.getElementById("rangeprint").innerHTML = range; 
          drawProjectile();
          if (timer) window.clearTimeout(timer);
          timer = window.setTimeout(moveProjectile, 100*dt);  
        }
      }
      function showVel() {
        velReadout.innerHTML = velSlider.value;
      }
      function showCollagen() {
        collagenReadout.innerHTML = collagenSlider.value;
      }
    <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>
        <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="position:relative;">