篮球物理碰撞检测与弹跳物理

时间:2017-08-19 20:18:28

标签: javascript html5 math canvas

我正在制作篮球物理模拟器。我正在使用参数方程来计算球的路径。我很难与前缘,篮板,杆子和球场(画布底部)进行碰撞检测。另外我想在击中这些物体时使球反弹,但我很难过。任何人都可以提供这方面的帮助吗?

以下是代码段:



var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.transform(1, 0, 0, -1, 0, canvas.height)
ctx.translate(canvas.width / 2, canvas.height / 2);

var speed = 5;
var gravity = 16;
var bounce = 10;

var mouseX = 0;
var mouseY = 0;

var stage = 1;

var x = 0;
var y = 0;
var xOrgn = 0;
var yOrgn = 0;
var xClk = 175;
var yClk = 100;
var mag = 0;
var ang = 0;
var xVel = 0;
var yVel = 0;
var time = 0;

function drawBall() {
  ctx.beginPath();
  ctx.arc(x, y, 12, 0, Math.PI * 2);
  ctx.fillStyle = "#FF8C00";
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(x, y + 12);
  ctx.lineTo(x, y - 12);
  ctx.strokeStyle = 'black';
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(x - 12, y);
  ctx.lineTo(x + 12, y);
  ctx.strokeStyle = 'black';
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(x - 8, y - 8);
  ctx.bezierCurveTo(x - 2, y - 4, x - 2, y + 4, x - 8, y + 8);
  ctx.strokeStyle = 'black';
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(x + 8, y - 8);
  ctx.bezierCurveTo(x + 2, y - 4, x + 2, y + 4, x + 8, y + 8);
  ctx.strokeStyle = 'black';
  ctx.stroke();
}

function drawHoop() {
  ctx.beginPath();
  ctx.rect(228, -160, 12, 172);
  ctx.fillStyle = "#191919";
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.rect(222, -12, 6, 80);
  ctx.fillStyle = "#666666";
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.rect(171, -6, 51, 6);
  ctx.fillStyle = "#e50000";
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.arc(171, -3, 3, 0, Math.PI * 2);
  ctx.fillStyle = "#e50000";
  ctx.fill();
  ctx.closePath();
}

function drawCursor() {
  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(mouseX - 12, mouseY);
  ctx.lineTo(mouseX + 12, mouseY);
  ctx.strokeStyle = '#00cd00';
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(mouseX, mouseY - 12);
  ctx.lineTo(mouseX, mouseY + 12);
  ctx.strokeStyle = '#00cd00';
  ctx.stroke();
  ctx.closePath();
}

function calcVel() {
  mag = Math.sqrt((Math.pow(xClk - xOrgn, 2) + Math.pow(yClk - yOrgn, 2)) / 4);
  ang = Math.atan((yClk - yOrgn) / (xClk - xOrgn));
  xVel = mag * Math.cos(ang);
  yVel = mag * Math.sin(ang);
}

function draw() {
  ctx.clearRect(-(canvas.width / 2), -(canvas.height / 2), canvas.width, canvas.height);
  ctx.canvas.addEventListener('mousemove', function(event) {
    mouseX = event.clientX - ctx.canvas.offsetLeft - canvas.width / 2;
    mouseY = -event.clientY + ctx.canvas.offsetTop + canvas.height / 2;
  });
  drawBall();
  drawHoop();
  if (stage === 1) {
    x = mouseX;
    y = mouseY;
    ctx.canvas.addEventListener('click', function(event) {
      xOrgn = x;
      yOrgn = y;
      stage = 2;
    });
  } else if (stage === 2) {
    drawCursor();
    ctx.canvas.addEventListener('click', function(event) {
      xClk = mouseX;
      yclk = mouseY;
      calcVel();
      time = 0;
      stage = 3;
    });
  } else if (stage === 3) {
    x = xVel * time + xOrgn;
    y = -gravity * Math.pow(time, 2) + yVel * time + yOrgn;
    time = time + speed * 0.01;
  }
}

setInterval(draw, 10);

canvas {
  background: white;
}

<canvas id="myCanvas" width="480" height="320"></canvas>
&#13;
&#13;
&#13;

以下是jsfiddle中的代码:JSfiddle

1 个答案:

答案 0 :(得分:0)

您必须仅在“阶段3”中添加碰撞检测。由于所有内容的位置和大小都是硬编码的,因此逐项添加碰撞检测非常简单简单。 (但是如果你把这个变得更加复杂,我会添加一些变量或对象,以便很容易将事物的位置作为变量等)。

当球击中篮板时,我在水平弹跳中加入,并且垂直弹跳离开地板。其他任何人都很相似。

(注意,使这些成为可能的是迭代地更新x和y(和xVel,yVel)而不是从确定的等式中更新。结果是相同的,但计算和动态行为更容易)。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.transform(1, 0, 0, -1, 0, canvas.height)
ctx.translate(canvas.width / 2, canvas.height / 2);

var speed = 5;
var gravity = 16;
var bounce = 10;

var mouseX = 0;
var mouseY = 0;

var stage = 1;

var x = 0;
var y = 0;
var xOrgn = 0;
var yOrgn = 0;
var xClk = 175;
var yClk = 100;
var mag = 0;
var ang = 0;
var xVel = 0;
var yVel = 0;
var time = 0;

function drawBall() {
  ctx.beginPath();
  ctx.arc(x, y, 12, 0, Math.PI * 2);
  ctx.fillStyle = "#FF8C00";
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(x, y + 12);
  ctx.lineTo(x, y - 12);
  ctx.strokeStyle = 'black';
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(x - 12, y);
  ctx.lineTo(x + 12, y);
  ctx.strokeStyle = 'black';
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(x - 8, y - 8);
  ctx.bezierCurveTo(x - 2, y - 4, x - 2, y + 4, x - 8, y + 8);
  ctx.strokeStyle = 'black';
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(x + 8, y - 8);
  ctx.bezierCurveTo(x + 2, y - 4, x + 2, y + 4, x + 8, y + 8);
  ctx.strokeStyle = 'black';
  ctx.stroke();
}

function drawHoop() {
  ctx.beginPath();
  ctx.rect(228, -160, 12, 172);
  ctx.fillStyle = "#191919";
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.rect(222, -12, 6, 80);
  ctx.fillStyle = "#666666";
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.rect(171, -6, 51, 6);
  ctx.fillStyle = "#e50000";
  ctx.fill();
  ctx.closePath();

  ctx.beginPath();
  ctx.arc(171, -3, 3, 0, Math.PI * 2);
  ctx.fillStyle = "#e50000";
  ctx.fill();
  ctx.closePath();
}

function drawCursor() {
  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(mouseX - 12, mouseY);
  ctx.lineTo(mouseX + 12, mouseY);
  ctx.strokeStyle = '#00cd00';
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.moveTo(mouseX, mouseY - 12);
  ctx.lineTo(mouseX, mouseY + 12);
  ctx.strokeStyle = '#00cd00';
  ctx.stroke();
  ctx.closePath();
}

function calcVel() {
  mag = Math.sqrt((Math.pow(xClk - xOrgn, 2) + Math.pow(yClk - yOrgn, 2)) / 4);
  ang = Math.atan((yClk - yOrgn) / (xClk - xOrgn));
  xVel = mag * Math.cos(ang);
  yVel = mag * Math.sin(ang);
}

function draw() {
  ctx.clearRect(-(canvas.width / 2), -(canvas.height / 2), canvas.width, canvas.height);
  ctx.canvas.addEventListener('mousemove', function(event) {
    mouseX = event.clientX - ctx.canvas.offsetLeft - canvas.width / 2;
    mouseY = -event.clientY + ctx.canvas.offsetTop + canvas.height / 2;
  });
  drawBall();
  drawHoop();
  if (stage === 1) {
    x = mouseX;
    y = mouseY;
    ctx.canvas.addEventListener('click', function(event) {
      xOrgn = x;
      yOrgn = y;
      stage = 2;
    });
  } else if (stage === 2) {
    drawCursor();
    ctx.canvas.addEventListener('click', function(event) {
      xClk = mouseX;
      yclk = mouseY;
      calcVel();
      time = 0;
      stage = 3;
    });
  } else if (stage === 3) {
    //x = xVel * time + xOrgn;
    // update x from it's own value so we can vary the xVel.
    x += xVel * speed * 0.01;

    //y = -gravity * Math.pow(time, 2) + yVel * time + yOrgn;
    // update yVel and y iteratively instead of this determined calculation
    //y = -gravity * Math.pow(time, 2) + yVel * time + yOrgn;
    yVel -= gravity * 0.1;
    y += yVel * speed * 0.01;

    // do a collision check: the backboard.
    if (x > 222 - 12 && y > -12 && y < 62) {
	    xVel *= -1;
    }
    // with floor
    if(y <= -142) {
        y = -142;
        yVel *= -1;
    }
    time = time + speed * 0.01;
  }
}

setInterval(draw, 10);
canvas {
  background: white;
}
<canvas id="myCanvas" width="480" height="320"></canvas>

您可以处理任何其他类似的碰撞