Javascript线和点角度碰撞

时间:2017-03-19 13:51:59

标签: javascript html5-canvas physics collision angle

当蝙蝠与蝙蝠碰撞时,我想以正确的方向移动球,就像this example

一样

尽管如此,它并不一定非常好。正确的工作是这里的目标。

到目前为止,我可以在以下网址中看到我所拥有的内容: https://jsfiddle.net/qphqvntx/4/

当蝙蝠击球时,问题出在碰撞上。它表现得非常奇怪。

//Canvas Variable
var mainCanvas = document.getElementById("mainCanvas");
var ctx = mainCanvas.getContext("2d");

var canvasHeight = mainCanvas.height;
var canvasWidth = mainCanvas.width;

var borderRadius = 10;
var bottomRadius = 120;
var gravity = 0.2;

var animate = false;
//Ball Object related variable
var balls = [];
var ballObj = {
  x: 0,
  y: 0,
  velocity: {x: 0, y: 0},
};

var ball = '';
var debugBall = '';
var ballRadius = 10;
var dumping = 0.99;
var ballSpeed = 6;
var force = 1.8;
var setBallTimer = 150;
var updateBallTimer = 0;

var target;
var distanceX;
var distancey;

var j, balls2;

//Bat related variable

var batXPos = 200;
var batYPos = canvasHeight - bottomRadius - 120;

var batHeight = 100;
var batWidth = 10;

var mouse = [0, 0];
var point = [170, 175];

var dx, dy;

//run related variable
var oneRunLine = 60;
var twoRunLine = 90;
var fourRunLine = 100;

var outTopLine = 450;

var oneRunChain = canvasHeight - bottomRadius;
var twoRunChain = canvasHeight - bottomRadius - oneRunLine;
var fourRunChain = canvasHeight - bottomRadius - oneRunLine - twoRunLine;
var sixRunChain = canvasHeight - bottomRadius - oneRunLine - twoRunLine - fourRunLine;

var circleUnderMouse;
var mouse = {
  x: 0,
  y: 0,
  down: false
}

var res;
var previousEvent = false;

function executeFrame() {
  if (animate) {
    requestAnimFrame(executeFrame);
  }

  ctx.lineWidth = "3";
  ctx.strokeRect(0, 0, mainCanvas.width, mainCanvas.height);
  ctx.strokeRect(0, 0, mainCanvas.width, mainCanvas.height - bottomRadius);

  ctx.fillStyle = 'rgba(255,255,255,0.3)';
  ctx.fillRect(0, 0, mainCanvas.width, mainCanvas.height);


  update();
  if (balls.length != '0') {
    balls.forEach(function (ball, j, i) {
      drawBall(ball);
      createBat();
    });
  }
}

initializeGame();

function update() {

  if (balls.length != '0') {
    balls.forEach(function (ball, balli, ballj) {

      ball.addGravity();

      ball.velocity.y *= dumping;
      ball.velocity.x *= dumping;

      ball.y += ball.velocity.y;
      ball.x += ball.velocity.x * force;

      if (hitGround(ball) == true) {
        ball.y = mainCanvas.height - bottomRadius;
        ball.velocity.y = -Math.abs(ball.velocity.y);
      }
      if (hitLeft(ball) == true) {
        ball.velocity.x = Math.abs(ball.velocity.x);
      }

      var hit = linePoint(point[0], point[1], mouse[0], mouse[1], ball.x, ball.y, ball);
      if (hit == true) {
        //console.log("hit");
      } else {
        //console.log("not yet");
      }

      for (j = balli + 1; j < balls.length; j++) {

        balls2 = ballj[j];
        var dx = balls2.x - ball.x;
        var dy = balls2.y - ball.y;
        var d = Math.sqrt(dx * dx + dy * dy);

        if (d < 2 * ballRadius) {
          if (d === 0) {
            d = 0.1;
          }
          var unitX = dx / d;
          var unitY = dy / d;

          var newForce = -1;

          var forceX = unitX * newForce;
          var forceY = unitY * newForce;

          ball.velocity.x += forceX;
          ball.velocity.y += forceY;

          balls2.velocity.x -= forceX;
          balls2.velocity.y -= forceY;
        }
      }
    });
  }
  updateBallTimer++;
  if (updateBallTimer >= setBallTimer) {
    createBall();
    updateBallTimer = 0;
  }
}

function initializeGame() {
  createBall();
  createBat();
}

function createBall() {

  randomPoint(50, 150);
  ball = instantiateBall(canvasWidth, target.y, ballObj);
  ball.velocity.x -= getRandomNumber(4, 6);
}

function instantiateBall(xPos, yPos, ball) {
  ball = {
    x: xPos,
    y: yPos,
    velocity: {x: 0, y: 0},
    addGravity: function () {
      return this.velocity.y += gravity;
    },
    onCanvas: false
  };
  balls.push(ball);
  drawBall(ball);
  return ball;
}

function drawBall(ball) {
  if (ball != '') {
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, ballRadius, 0, 2 * Math.PI, false);
    ctx.fillStyle = "#000";
    ctx.fill();
  }
}

function createBat() {

//  ctx.clearRect(0, 0, width, height)

  dx = mouse[0] - point[0],
          dy = mouse[1] - point[1];
  rot = Math.atan2(dy, dx);

  ctx.fillStyle = 'red';
  ctx.fillRect(point[0], point[1], 10, 10);

  ctx.fillStyle = 'gray';
  ctx.save();
  ctx.translate(point[0], point[1]);

  ctx.rotate(rot);

  ctx.fillRect(0, 0, batHeight, batWidth);
  ctx.moveTo(point[0], point[1]);
  ctx.lineTo(point[0] + (mouse[0] - point[0]) + 0.5, point[1] + (mouse[1] - point[1]) * 0.5);
  //ctx.stroke();
  ctx.restore();
}

function  linePoint(x1, y1, x2, y2, px, py, ball) {

var d1 = dist(px, py, x1, y1);
var d2 = dist(px, py, x2, y2);

var lineLen = dist(x1, y1, x2, y2);

var buffer = 3;

var batAngle = Math.atan2(d2, d1);
var batAngleX = Math.sin(batAngle);
var batAngleY = -Math.cos(batAngle);

if (d1 + d2 >= lineLen - buffer && d1 + d2 <= lineLen + buffer) {

    var d = 2 * (ball.velocity.x * batAngleX + ball.velocity.y * batAngleY);
    
    ball.x -= d * batAngleX;
    ball.x -= d * batAngleY;

    ball.velocity.x -= d * batAngleX + res;
    ball.velocity.y -= d * batAngleY + res;

    return true;
}
return false;
}

function dist(x1, y1, x2, y2) {
  var xs = x2 - x1,
          ys = y2 - y1;

  xs *= xs;
  ys *= ys;

  return Math.sqrt(xs + ys);
}

function getRandomNumber(min, max) {
  return Math.random() * (max - min) + min;
}

function randomPoint(min, max) {
  var rndNum = Math.random() * (max - min) + min;
  target = {
    x: canvasWidth,
    y: rndNum
  };
//    ctx.beginPath();
//    ctx.arc(rndNum, canvasHeight, ballRadius, 0, 2 * Math.PI, false);
//    ctx.fillStyle = "#ff0";
//    ctx.fill();
}

function isOnCanvas(obj) {

  if (obj.x <= mainCanvas.width && obj.y <= mainCanvas.height - bottomRadius) {
    return true;
  }
  return false;
}

function hitGround(obj) {
  if (obj.y >= mainCanvas.height - bottomRadius) {
    //console.log("hit the ground");
    return true;
  }
  return false;
}

function hitTop(obj) {
  if (obj.y <= borderRadius) {
    //console.log("hit the top");
    return true;
  }
  return false;
}

function hitLeft(obj) {
  if (obj.x <= borderRadius) {
    //console.log("hit the left");
    return true;
  }
  return false;
}

function hitRight(obj) {
  if (obj.x >= mainCanvas.width - borderRadius) {
    //console.log("hit the left");
    return true;
  }
  return false;
}

function drawLineRandomPoint(moveX, moveY, lineX, lineY, strColor) {
  ctx.beginPath();
  ctx.moveTo(moveX, moveY);
  ctx.lineTo(lineX, lineY);
  ctx.strokeStyle = strColor;
  ctx.stroke();
}

mainCanvas.addEventListener('mousemove', function (e) {

  e.time = Date.now();
  res = makeVelocityCalculator(e, previousEvent);
  previousEvent = e;

  mouse[0] = e.clientX;
  mouse[1] = e.clientY;
});

function makeVelocityCalculator(e_init, e) {
  var x = e_init.clientX, new_x, new_y, new_t,
          x_dist, y_dist, interval, velocity,
          y = e_init.clientY,
          t;
  if (e === false) {
    return 0;
  }
  t = e.time;
  new_x = e.clientX;
  new_y = e.clientY;
  new_t = Date.now();
  x_dist = new_x - x;
  y_dist = new_y - y;
  interval = new_t - t;
  // update values:
  x = new_x;
  y = new_y;
  velocity = Math.sqrt(x_dist * x_dist + y_dist * y_dist) / interval;
  return velocity;
}

mainCanvas.addEventListener('mouseover', function (e) {
  animate = true;
  executeFrame();
});

mainCanvas.addEventListener("mouseout", function (e) {
  animate = false;
});

executeFrame();

window.requestAnimFrame = (function () {
  return  window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.oRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function (callback) {
            window.setTimeout(callback, 1000 / 60);
          };
})();
<body>
      <canvas id="mainCanvas" height="400" width="600"></canvas>
      <script src="main.js" type="text/javascript"></script>
</body>

0 个答案:

没有答案