2017-08-19 159 views
1

我正在製作一個籃球物理模擬器。我正在使用參數方程來計算球的路徑。我很難與邊緣,籃板,杆和球場(球場底部)的前部進行碰撞檢測。另外我想在擊球時讓球反彈,但我很難。任何人都可以提供這個問題的一些幫助?籃球物理碰撞檢測和彈跳物理

這裏是代碼片段:

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>

這裏是的jsfiddle代碼:JSfiddle

+0

可能的幫助:跟蹤新老X,Y值,然後看如果球移動通過」」的籃筐或籃板,因爲你將x,y的值增加了1以上,所以你不能檢查是否相等:球可能在一個平局之上,而在下一個平局之下。 – barrycarter

回答

0

您必須添加僅在 「第三階段」 的碰撞檢測。由於所有東西的位置和大小都是硬編碼的,所以簡單的可以逐項添加碰撞檢測。 (但是如果你做得更復雜,我會添加一些變量或對象,這些變量或對象可以很容易地將事物的位置作爲變量等)。

當球擊中籃板時,我加入了水平反彈,垂直反彈離開了地板。其他任何人都是相似的(注意,是什麼使得這些可能是迭代地更新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) { 
 
\t  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>

您可以處理任何其他衝突,你想同樣

+0

謝謝你的幫助。我將使用變量來表示對象的位置。這對我來說非常有用! –

+0

G1廣告它的工作!我的意思是變量是,如果你可以輸入類似'if(x> backboard.x)'或者更好的'if(backboard.intersects(x,y))',那將是非常好的。您可以像所有變量一樣使用變量(並且這是一個好的第一步!),但是如果可以這樣做的話,它會更具可讀性並具有更少的「幻數」。 – arbuthnott