[英]Detection and response ball-to-wall collision inside any polygon
需要編寫好的方法來檢測和響應任何多邊形內的球壁碰撞。
例如,我有一個方法可以繪制一個在矩形內飛行的球。
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
檢測和響應該碰撞非常簡單。
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
}
但是我有一個多邊形:每個點的位置(x和y)是變量。
var polygonPoints = [
{
x: 240,
y: 30
},
{
x: 140,
y: 100
},
{
x: 180,
y: 250
},
{
x: 320,
y: 280
},
{
x: 400,
y: 50
}
]。
和函數來繪制我的多邊形:
ctx.beginPath();
ctx.strokeStyle = '#333';
ctx.moveTo(polygonPoints[0].x, polygonPoints[0].y);
for (var i = 1, n = polygonPoints.length; i < n; i++) {
ctx.lineTo(polygonPoints[i].x, polygonPoints[i].y);
}
ctx.lineTo(polygonPoints[0].x, polygonPoints[0].y);
ctx.stroke();
ctx.closePath();
如何檢測和響應多邊形內部的碰撞?
jsfiddle上的演示。
var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); var ballRadius = 10; var x = canvas.width/2; var y = canvas.height-30; var dx = 2; var dy = -2; var polygonPoints = [ { x: 240, y: 30 }, { x: 140, y: 100 }, { x: 180, y: 250 }, { x: 320, y: 280 }, { x: 400, y: 50 } ]; function drawBall() { ctx.beginPath(); ctx.arc(x, y, ballRadius, 0, Math.PI*2); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); } function drawPolygon() { ctx.beginPath(); ctx.strokeStyle = '#333'; ctx.moveTo(polygonPoints[0].x, polygonPoints[0].y); for (var i = 1, n = polygonPoints.length; i < n; i++) { ctx.lineTo(polygonPoints[i].x, polygonPoints[i].y); } ctx.lineTo(polygonPoints[0].x, polygonPoints[0].y); ctx.stroke(); ctx.closePath(); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawBall(); drawPolygon(); if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { dx = -dx; } if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) { dy = -dy; } x += dx; y += dy; window.requestAnimationFrame(draw); } draw();
canvas { border: 1px solid #333; }
<canvas id="myCanvas" width="480" height="320"></canvas>
這是測試多邊形中任何線與圓(球)碰撞的方法。
首先,計算相對於您的球的直線上的閉合點:
function calcClosestPtOnSegment(x0,y0,x1,y1,cx,cy){
// calc delta distance: source point to line start
var dx=cx-x0;
var dy=cy-y0;
// calc delta distance: line start to end
var dxx=x1-x0;
var dyy=y1-y0;
// Calc position on line normalized between 0.00 & 1.00
// == dot product divided by delta line distances squared
var t=(dx*dxx+dy*dyy)/(dxx*dxx+dyy*dyy);
// calc nearest pt on line
var x=x0+dxx*t;
var y=y0+dyy*t;
// clamp results to being on the segment
if(t<0){x=x0;y=y0;}
if(t>1){x=x1;y=y1;}
return({ x:x, y:y, isOnSegment:(t>=0 && t<=1) });
}
其次,測試球是否足夠靠近以與該直線碰撞,如下所示:
var dx=ballX-nearestX;
var dy=ballY-nearestY
var isColliding=(dx*dx+dy*dy<ballRadius*ballRadius);
最后,如果球與該側碰撞,請計算球的反射角(==它的出射角):
這是計算中涉及的角度的說明:
這是一些偽代碼,顯示了如何進行計算:
var wallNormalAngle = wallAngle-PI/2; // assuming clockwise angle calculations
var differenceAngle = incidenceAngle - wallNormalAngle;
var reflectionAngle = incidenceAngle + 2 * differenceAngle
我可能誤解了您的問題,我會盡快更新答案。
由於它是多邊形,因此您只有有限數量的頂點(角),並且在與屏幕邊緣發生碰撞的情況下,至少有一個角會接觸。 這意味着您只需要遍歷Polygone點列表並檢查[any]是否在屏幕之外。
這是一個廣泛的問題。 有很多計算2d碰撞的方法。 幸運的是,圓形碰撞非常簡單,因為每種尺寸的碰撞尺寸都完全相同
您很可能希望使用運動矢量(dx / dy)和線矢量。 嘗試在每次迭代中向前計算一步,然后查看向量相交的位置。 然后計算必要的力量
不用說,數學和三角學計算是必要的。 這並不困難,只是人們通常在需要使用鼻竇和余弦時會感到害怕
N物理引擎的制造商對此主題有很好的解釋文章, 網址為http://www.metanetsoftware.com/technique/tutorialA.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.