1

First off I must admit I'm really not good at math and am trying to learn but have had a hard time finding examples someone like myself can follow. I'm trying to figure out how to draw and calculate the parabolic arch from one point to hit a target.

I really appreciate any help on this, I have been struggling to figure out a this for the past 2 days and still am unable to come up with anything that works.

The best visual depiction I found was something like this but I am looking for a 2D solution.

enter image description here

<html>
  <body>
    <canvas id="myCanvas"></canvas>
    <script>
      function ranInt(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
      }
 var canvas = document.getElementById(&quot;myCanvas&quot;);
  canvas.width = 500;
  canvas.height = 500;
  let w = canvas.width;
  let h = canvas.height;
  document.body.appendChild(canvas);
  var ctx = canvas.getContext(&quot;2d&quot;);
  var ox = 20;
  var oy = h - 20;
  var cannon = { x: ox - 12, y: oy - 12, width: 50, height: 24 };
  var target = { x: w - 150, y: h - 350, width: 42, height: 42 };
  var ball = { x: ox, y: oy, r: 10, cx: ox, cy: oy };

  function draw() {
    ctx.fillStyle = &quot;yellow&quot;;
    ctx.fillRect(cannon.x, cannon.y, cannon.width, cannon.height);
    ctx.fillRect(target.x, target.y, target.width, target.height);
    ctx.fillStyle = &quot;red&quot;;
    ctx.fillRect(ball.cx, ball.cy, 4, 4);
  }

  var state = &quot;ready&quot;;

  function update() {
    if (state === &quot;flying&quot;) {
      var x = ball.cx;
      var y = ball.cy;
      x += vx;
      y += vy;
      vy += 0.1;
      ball.cx = x;
      ball.cy = y;
      ctx.fillStyle = &quot;black&quot;;
      ctx.fillRect(ball.cx, ball.cy, 4, 4);

      if (ball.cy &gt; h || ball.cx &gt; w) {
        state = &quot;ready&quot;;
        ball = { x: ox, y: oy, r: 10, cx: ox, cy: oy };
      }
    }

    draw();
  }

  setInterval(update, 10);
  var vx = 0;
  var vy = 0;
  document.addEventListener(&quot;click&quot;, function (e) {
    ball = { x: ox, y: oy, r: 10, cx: ox, cy: oy };
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    vy = -9.22;    
    vx =  (e.pageX - ox) / 50;

    state = &quot;flying&quot;;
  });
&lt;/script&gt;

</body> </html>

Pikalek
  • 12,372
  • 5
  • 43
  • 51

1 Answers1

1

One way is to predetermine the point shooting to, and also pre plot each point used to get from point a to z. I've used an open source library to simplify this example;

(function() {
var canvasObject = new tabageos.CanvasObject(null,250,250);

document.getElementById("theBody").appendChild(canvasObject.canvas);

var cannon = new tabageos.MoverPoint(20,100);

var ball = new tabageos.MoverPoint(20,100);

var ballTarget = new tabageos.MoverPoint(230,100);

var ballPath = tabageos.GeometricMath.getRawArcCurvePath(cannon.x,cannon.y, 150,4, ballTarget.x,ballTarget.y,100);

canvasObject.drawCircle(cannon.x,cannon.y,16,"#c8c8c8");

canvasObject.drawCircle(ballTarget.x, ballTarget.y, 16,"#c80000");

canvasObject.drawCircle(ball.x, ball.y,8,"#000000");

var currentBallPathIndex = 0;

var loop = function() {
   canvasObject.clear();
   canvasObject.drawCircle(cannon.x,cannon.y,16,"#c8c8c8");
   canvasObject.drawCircle(ballTarget.x, ballTarget.y, 16,"#c80000");

   ball.x = ballPath[currentBallPathIndex];
   ball.y = ballPath[currentBallPathIndex+1];
   canvasObject.drawCircle(ball.x,ball.y,8,"#000000");

   if(currentBallPathIndex &lt; ballPath.length-1) {
       currentBallPathIndex += 2;
   } else { currentBallPathIndex = 0; }

   requestAnimationFrame(loop);
};
loop();


})();

<script src="https://cdn.jsdelivr.net/gh/tabageos/tabageos/tbgs_min.js"></script>

<div id="theBody"> </div>

This is what getRawArcCurvePath would look like;

getRawArcCurvePath = function(p0x, p0y, p1x, p1y, p2x, p2y, amountOfPoints) {
    var i = 0;
    var added = (100 / amountOfPoints) / 100;
    var path = [];
    while(i < 1) {
       var a = (1 - i) * (1 - i);
       var t = i * i;
       path[path.length] = a * p0x + 2 * (1-i) * i * p1x + t * p2x;
       path[path.length] = a * p0y + 2 * (1-i) * i * p1y + t * p2y;
       i += added;
    }
    return path;
}
mrall
  • 27
  • 3