共计 3507 个字符,预计需要花费 9 分钟才能阅读完成。
引子
在 Collision Detection:Line 中次要介绍了直线相干的碰撞检测,接着来看看更加简单一些的多边形的状况。
以下示例未做兼容性查看,倡议在最新的 Chrome 浏览器中查看。
- Origin
- My GitHub
Polygon/Point
这是示例页面。
多边形与点 的碰撞检测,须要每一条边与点进行检测,能力确定是否产生了碰撞:
const points = []; // 多边形顶点坐标
const pointsLen = points.length;
let collision = false; // 初始化碰撞状态
for(let index = 0; index < pointsLen; index ++) {
// checkCondition 边与检测点的判断
if (checkCondition()) {collision = !collision;}
}
假如一条边的一个端点的坐标为 [cx,cy]
,另一端点坐标为 [nx,ny]
,检测点的坐标为 [px,py]
,须要检测的条件为:
if (((cy > py) != (ny > py)) && (px < (nx-cx) * (py-cy) / (ny-cy) + cx) ) {collision = !collision;}
这里的判断条件做了两个检测,首先是查看检测点的 Y 坐标是否在两个端点的 Y 坐标范畴内:
(cy >= py && ny < py) || (cy < py && ny >= py)
// 等同于
(cy > py) != (ny > py)
而后查看监测点的 X 坐标,依赖的办法是 Jordan Curve Theorem :
px < (nx-cx) * (py-cy) / (ny-cy) + cx)
每次检测后,符合条件都须要将 collision
的布尔值取反。直到检测所有的边后,最初的 collision
值才是最终后果。
上面是残缺检测逻辑:
/*
* points 多边形顶点坐标,模式为 [[x1,y1],[x2,y2]]
* (px,py) 检测点坐标
*/
function checkPolygonPoint({points,px,py}) {
let collision = false;
const pointsLen = points.length;
for (let index = 0; index < pointsLen; index++) {const currentPoint = points[index];
const next = index === pointsLen-1 ? 0:index+1;
const nextPoint = points[next];
const [cx,cy] = currentPoint;
const [nx,ny] = nextPoint;
const judgeX = px < (nx-cx)*(py-cy) / (ny-cy)+cx;
const judgeY = (cy >= py && ny < py) || (cy < py && ny >= py);
if (judgeX && judgeY) {collision = !collision;}
}
return collision;
}
Polygon/Circle
这是示例页面。
多边形与圆 的碰撞检测,能够合成为多边形的边与圆的碰撞检测,只有有一条边产生了碰撞,就能够进行断定。这个时候能够应用之前介绍的对于 Line/Circle 检测的办法。
上面是残缺检测逻辑:
/*
* points 多边形顶点坐标,模式为 [[x1,y1],[x2,y2]]
* (cx,cy) 圆心坐标
* radius 圆半径
*/
function checkPolygonCircle({points,cx,cy,radius}) {
const pointsLen = points.length;
for (let index = 0; index < pointsLen; index++) {const currentPoint = points[index];
const next = index === pointsLen-1 ? 0:index+1;
const nextPoint = points[next];
const [x1,y1] = currentPoint;
const [x2,y2] = nextPoint;
const collision = checkLineCircle({x1,y1,x2,y2,cx,cy,radius});
if (collision) {return true;}
}
return false;
}
Polygon/Rectangle
这是示例页面。
多边形与矩形 的碰撞检测,能够合成为多边形的边与矩形的碰撞检测,只有有一条边产生了碰撞,就能够进行断定。这个时候能够应用之前介绍的对于 Line/Rectangle 检测的办法。
上面是残缺检测逻辑:
/*
* points 多边形顶点坐标,模式为 [[x1,y1],[x2,y2]]
* (rx,ry) 矩形左上角顶点坐标
* rw 矩形宽度
* rh 矩形高度
*/
function checkPolygonRectangle({points,rx,ry,rw,rh}) {
const pointsLen = points.length;
for (let index = 0; index < pointsLen; index++) {const currentPoint = points[index];
const next = index === pointsLen-1 ? 0:index+1;
const nextPoint = points[next];
const [x1,y1] = currentPoint;
const [x2,y2] = nextPoint;
const collision = checkLineRectangle({x1,y1,x2,y2,rx,ry,rw,rh});
if (collision) {return true;}
}
return false;
}
Polygon/Line
这是示例页面。
多边形与直线 的碰撞检测,能够合成为多边形的边与直线的碰撞检测,只有有一条边产生了碰撞,就能够进行断定。这个时候能够应用之前介绍的对于 Line/Line 检测的办法。
上面是残缺检测逻辑:
/*
* points 多边形顶点坐标,模式为 [[x1,y1],[x2,y2]]
* (x1,y1) 直线线端点坐标
* (x2,y2) 直线另一个端点坐标
*/
function checkPolygonLine({points,x1,y1,x2,y2}) {
const pointsLen = points.length;
for (let index = 0; index < pointsLen; index++) {const currentPoint = points[index];
const next = index === pointsLen-1 ? 0:index+1;
const nextPoint = points[next];
const [x3,y3] = currentPoint;
const [x4,y4] = nextPoint;
const collision = checkLineLine({x1,y1,x2,y2,x3,y3,x4,y4});
if (collision) {return true;}
}
return false;
}
Polygon/Polygon
这是示例页面,刷新页面,会生成随机的多边形。
多边形与多边形 的碰撞检测,思路是检测一个多边形任意边是否与另外一个多边形的任意边产生碰撞。这个时候能够应用后面介绍的对于 Polygon/Line 检测的办法。
上面是残缺检测逻辑:
/*
* points1 多边形 1 顶点坐标,模式为 [[x1,y1],[x2,y2]]
* points2 多边形 2 顶点坐标,模式为 [[x1,y1],[x2,y2]]
*/
function checkPolygonPolygon({points1,points2}) {
const pointsLen = points1.length;
for (let index = 0; index < pointsLen; index++) {const currentPoint = points1[index];
const next = index === pointsLen-1 ? 0:index+1;
const nextPoint = points1[next];
const [x1,y1] = currentPoint;
const [x2,y2] = nextPoint;
const collision = checkPolygonLine({points:points2,x1,y1,x2,y2});
if (collision) {return true;}
}
return false;
}
参考资料
- POLYGON/POINT
- POLYGON/CIRCLE
- POLYGON/RECTANGLE
- POLYGON/LINE
- POLYGON/POLYGON
- Jordan curve theorem