1
\$\begingroup\$

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("myCanvas");
      canvas.width = 500;
      canvas.height = 500;
      let w = canvas.width;
      let h = canvas.height;
      document.body.appendChild(canvas);
      var ctx = canvas.getContext("2d");
      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 = "yellow";
        ctx.fillRect(cannon.x, cannon.y, cannon.width, cannon.height);
        ctx.fillRect(target.x, target.y, target.width, target.height);
        ctx.fillStyle = "red";
        ctx.fillRect(ball.cx, ball.cy, 4, 4);
      }

      var state = "ready";

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

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

        draw();
      }

      setInterval(update, 10);
      var vx = 0;
      var vy = 0;
      document.addEventListener("click", 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 = "flying";
      });
    </script>
  </body>
</html>
\$\endgroup\$
1

1 Answer 1

1
\$\begingroup\$

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 < 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;
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .