【JS】Canvas 圆环碰撞 圆环外与圆环内与圆环上 (方式二)
咦,好像,终于有好东西了~,结合上一篇,这一篇将更简单,推荐
- 圆与多边形 圆环与多边形 其实和 点 与多边形碰撞一样,但也有几个不同之处
- 下面就来看看新实现的 圆环碰撞 列出几个重要部分
- 点的碰撞有两种常用的判断 一:射线法 、 二 转角发(这个转角叫法很多,就是点按顺序与多边形每个的角点的角度累加)
- 下面是经过测试的代码,简单,很简单,以前是我想复杂了
页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>圆环碰撞</title>
<style>
body {
overflow: hidden;
background: #000;
}
body,
html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#backs{
position: absolute;
z-index: 1;
left:0;
top:0;
background-color: #fff;
}
</style>
</head>
<body onclick="updPos();">
<canvas id="backs" width="100%" height="100%" ></canvas>
</body>
</html>
核心代码
代码看着很长 里面包含了分离轴碰撞检测 还有圆环碰撞检测的实现
var oAnim=document.getElementById('backs');
oAnim.width = window.innerWidth;
oAnim.height = window.innerHeight;
var cont = oAnim.getContext("2d");
//前面这些简单 圆环的参数 r 是半径 w 是圆环区域的宽度
var YH={
x:180,
y:200,
r:100,
w:10
}
//p 是多边形的各个点 顺序连接
var DBX = {
p:[{
x:300,
y:100
},{
x:400,
y:100
},{
x:400,
y:200,
},{
x:300,
y:200
}],
color:"rgba(255,0,0,1)"
}
//圆环的绘制方法
function YuanHuan(){
var rgbgrad =cont.createRadialGradient(YH.x, YH.y, YH.r-YH.w, YH.x, YH.y, YH.r); //渐变填充器
rgbgrad.addColorStop(0,'rgba(255,255,0,0)');
rgbgrad.addColorStop(0,'rgba(255,255,0,1)');
cont.beginPath();
//画圆
cont.arc(YH.x, YH.y, YH.r, 0, Math.PI * 2);
cont.fillStyle = rgbgrad; //填充样式 放入 渐变填充器
cont.fill(); //填充
cont.closePath();
}
//多边形的绘制方法
function DuoBianXin(){
cont.beginPath();
cont.lineCap = "square";
cont.moveTo(DBX.p[0].x,DBX.p[0].y);
for(var i=1;i<DBX.p.length;i++) {
cont.lineTo(DBX.p[i].x,DBX.p[i].y);
}
cont.lineWidth=0.1;
cont.fillStyle = DBX.color;
cont.strokeStyle = DBX.color;
cont.stroke();
cont.fill();
cont.closePath();
}
function isCollideArc(ring,rect){
// 循环多边形的每个点到圆心的距离
// 开方 是内部迭代,直到数字无限接近开方后的值
// 所以 不用开方的地方 与它对比的数用了平方
let px = ring.x,
py = ring.y,
list = rect.p,
max = 0,
min = Math.pow(px-list[0].x,2) + Math.pow(py-list[0].y,2);//不开方
//min = Math.sqrt(Math.pow(px-list[0].x,2) + Math.pow(py-list[0].y,2));
for(let r=1 ,sp ;r<list.length;r++){
//sp = Math.sqrt(Math.pow(px-list[r].x,2) + Math.pow(py-list[r].y,2));
sp = Math.pow(px-list[r].x,2) + Math.pow(py-list[r].y,2);//不开方
if(sp<min) min = sp;
else if (sp>max) max = sp;
}
//圆环内 //如果与圆对比 不需要这一行最大值的判断
if(max <( ring.r-ring.w)*( ring.r-ring.w)) return false;//最大值 小与 内圆的半径
//如果 最小值小与 半径 说明一定重叠
if(min <= ring.r*ring.r ) return true;
//以上条件不成立 使用 转角法
return zhuanjiao(px,py,list);
}
/* 转角法
通过判定点与多边形边角点 按顺序 进行角度累加
累加的角 是以上一次的角点为起点,以判定点当圆心,旋转至当前角点(忽略旋转点到角点的距离)中间的角度
如果在多边形内,角度和 等于 360 ° 否则就会不等于
*/
function zhuanjiao(px,py,list){
let i, l , j , sx , sy , tx ,ty ,sum = 0,agl = Math.PI * 2 ;
for(i = 0, l = list.length, j = l - 1; i < l; j = i, i++) {
sx = list[i].x;
sy = list[i].y;
tx = list[j].x;
ty = list[j].y;
// 点与多边形顶点重合或在多边形的边上
if((sx - px) * (px - tx) >= 0 && (sy - py) * (py - ty) >= 0 && (px - sx) * (ty - sy) === (py - sy) * (tx - sx)) {
return true;
}
// 点与相邻顶点连线的夹角
let angle = Math.atan2(sy - py, sx - px) - Math.atan2(ty - py, tx - px);
// 确保夹角不超出取值范围(-π 到 π)
if(angle >= Math.PI) {
angle = angle - agl;
} else if(angle <= -Math.PI) {
angle = angle + agl;
}
sum += angle;
}
// 计算回转数并判断点和多边形的几何关系
return Math.round(sum / Math.PI) !== 0;
}
//执行碰撞判断与绘制
function update(){
DBX.color = isCollideArc(YH,DBX)?"rgba(255,0,255,1)":"rgba(255,0,0,1)";
cont.clearRect(0, 0, window.innerWidth, window.innerHeight);
YuanHuan();
DuoBianXin();
requestAnimationFrame(update);
}
function updPos(){
//获取鼠标位置
var e = event || window.event;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
var x = e.pageX || e.clientX + scrollX;
var y = e.pageY || e.clientY + scrollY;
YH.x= x;
YH.y= y;
console.log("click X:"+x+" Y:"+y);
}
update();
点与多边形碰撞判断 详细说明看下方说明
上面文中提到的 射线法 可以查看下方给出的连接
连接:http://www.html-js.com/article/1528
上面代码中提到的 转角法 可以查看下方给出的连接
连接:http://www.html-js.com/article/1538
以上都是 判断点是否在多边形内部 的相关内容
这次总结,不亏,以前走的弯路,使我又学到了关于线段碰撞的检测,有人会问,点与线段的碰撞是不是也要写一堆,这里就直接对不懂的人简单说下,线段与点的关系:就如同三角形三边的关系,没错,三角形两边之和必定大于第三边 现在根据这个,断言:一点到线段两端点的距离之和等于线段长度就代表相交。
如有误导请联系,我会进行修正。
邮箱 hbck_gwx@qq.com