我正在制作篮球物理模拟器。我正在使用参数方程来计算球的路径。我很难与前缘,篮板,杆子和球场(画布底部)进行碰撞检测。另外我想在击中这些物体时使球反弹,但我很难过。任何人都可以提供这方面的帮助吗?
以下是代码段:
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;
以下是jsfiddle中的代码:JSfiddle
答案 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>
您可以处理任何其他类似的碰撞