Javascript 任意多边形内球到墙碰撞的检测和响应

Javascript 任意多边形内球到墙碰撞的检测和响应,javascript,canvas,html5-canvas,Javascript,Canvas,Html5 Canvas,需要为检测和响应任意多边形内的球到墙碰撞的良好方法编写代码 例如,我有一个方法,画一个在矩形内飞行的球 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) {

需要为检测和响应任意多边形内的球到墙碰撞的良好方法编写代码

例如,我有一个方法,画一个在矩形内飞行的球

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;
}
])

以及绘制多边形的函数:

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();

我可能误解了你的问题,我将很快更新我的答案


因为它是一个多边形,所以只有有限数量的顶点(角点),如果与屏幕边缘发生碰撞,至少有一个角点会接触。这意味着您只需循环浏览Polygone点列表,并检查[任何]是否在屏幕之外

这是一个广泛的问题。有许多方法可以计算二维碰撞。 幸运的是,圆碰撞非常简单,因为每个大小上的大小完全相同

您很可能希望使用运动矢量(dx/dy)和线矢量。尝试在每次迭代前一步计算后续运动,并查看向量相交的位置。然后计算必要的力

不用说,数学和三角计算是必要的。这并不难,只是人们在需要使用鼻窦和余弦时通常会感到害怕


N物理引擎制造商在这方面有一篇非常好的解释文章这是如何测试圆(球)与多边形中任何直线的碰撞。

首先,计算一条线上相对于球的闭合点:

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) });
}

我真的很喜欢你在这方面所做的努力,但我认为这对他来说不是必要的,他需要碰撞响应我已经编辑了我的答案以返回[x,y]碰撞点以及一个
isColliding
boolean谢谢,但我需要响应检测到的碰撞。哦,我有点不明白如何使用找到的入射角度将球从墙上弹起。你能帮助我吗?在函数
resolveCollision()
中,我检查球是否与墙碰撞,如果是,我通过
Math.atan2
计算角度。接下来怎么办?我用简化的碰撞测试代码编辑了我的答案,并举例说明了如何计算球的弹跳角度。祝你的项目好运。
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