再次开始处理我的Agar.io克隆。两个圆之间的基本碰撞检测是容易的(距离<半径=碰撞)。然而,琼脂的碰撞检测有点复杂。它似乎检测到圆A包含圆圈B的多少,但由于它不是开源的,我无法弄清楚它们是如何做到的。我在GitHub上看到了这个Agar clone,但看起来他们采取了更简单的路线并且只是定期进行碰撞检测。
这就是我现在正在做的事情。
collision: function(circle) {
var xx = circle.x - this.x;
var yy = circle.y - this.y;
var distance = Math.sqrt(xx * xx + yy * yy);
return distance < this.radius + circle.radius;
},
如何检查另一个圈内有多少圆圈?
答案 0 :(得分:4)
您可以通过添加2个相交圆圈部分的区域来计算2个圆圈之间的交点区域:
示例代码和演示
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
// define 2 circles
var c1={x:100,y:100,r:100};
var c2={x:200,y:200,r:150};
// get points where 2 circles' perimeters intersect
var pts=intersection(c1.x,c1.y,c1.r,c2.x,c2.y,c2.r);
// get the angle formed by one intersection point
// and the circle's centerpoint
// and the other intersection point
var centralAngle1=centralAngle({x:pts.x1,y:pts.y1},{x:c1.x,y:c1.y},{x:pts.x2,y:pts.y2});
var centralAngle2=centralAngle({x:pts.x1,y:pts.y1},{x:c2.x,y:c2.y},{x:pts.x2,y:pts.y2});
// calculate the area of the two circle sectors
var sector1area=parseInt(sectorArea(c1.r,centralAngle1));
var sector2area=parseInt(sectorArea(c2.r,centralAngle2));
draw();
function draw(){
// stroke circles
ctx.beginPath();
ctx.arc(c1.x,c1.y,c1.r,0,Math.PI*2);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(c2.x,c2.y,c2.r,0,Math.PI*2);
ctx.closePath();
ctx.stroke();
// intersecting chord
ctx.beginPath();
ctx.moveTo(pts.x1,pts.y1);
ctx.lineTo(pts.x2,pts.y2);
ctx.stroke();
// intersection points
ctx.fillStyle='red';
ctx.beginPath();
ctx.arc(pts.x1,pts.y1,5,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.arc(pts.x2,pts.y2,5,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.fillStyle='black';
// sector labels
ctx.fillText('sector2',100,100);
ctx.fillText('sector1',135,135);
// report sector areas
ctx.fillText(sector2area,100,112);
ctx.fillText(sector1area+'px',135,147);
ctx.fillText('px',100,124);
//
ctx.fillText('circle#1',c1.x-35,c1.y-35);
ctx.fillText('circle#2',c2.x,c2.y);
}
// calc area of circle section
function sectorArea(radius,radianSweep){
var PI=Math.PI;
var PI2=PI*2;
// area of wedge with specified sweep angle
var wedgeArea=(PI*radius*radius)*radianSweep/PI2;
// area of triangle formed by 2 radii & radianSweep
// == side angle side method
var triangleArea=0.50*radius*radius*Math.sin(radianSweep);
// subtract triangle area from wedge area
// leaving the sector area
return(wedgeArea-triangleArea);
}
// return angle between 3 points
function centralAngle(p0,p1,p2) {
var dx1=p1.x-p0.x;
var dy1=p1.y-p0.y;
var dx2=p1.x-p2.x;
var dy2=p1.y-p2.y;
var dx3=p2.x-p0.x;
var dy3=p2.y-p0.y;
var a=dx1*dx1+dy1*dy1;
var b=dx2*dx2+dy2*dy2;
var c=dx3*dx3+dy3*dy3;
return(Math.acos((a+b-c)/Math.sqrt(4*a*b)));
}
function centralAngleX(x1,y1,x2,y2){
var dx=x2-x1;
var dy=y2-y1;
return(Math.abs(Math.atan2(dy,dx)));
}
function intersection(x0, y0, r0, x1, y1, r1) {
var a, dx, dy, d, h, rx, ry;
var x2, y2;
/* dx and dy are the vertical and horizontal distances between
* the circle centers.
*/
dx = x1 - x0;
dy = y1 - y0;
/* Determine the straight-line distance between the centers. */
d = Math.sqrt((dy*dy) + (dx*dx));
/* Check for solvability. */
if (d > (r0 + r1)) {
/* no solution. circles do not intersect. */
return false;
}
if (d < Math.abs(r0 - r1)) {
/* no solution. one circle is contained in the other */
return false;
}
/* 'point 2' is the point where the line through the circle
* intersection points crosses the line between the circle
* centers.
*/
/* Determine the distance from point 0 to point 2. */
a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
/* Determine the coordinates of point 2. */
x2 = x0 + (dx * a/d);
y2 = y0 + (dy * a/d);
/* Determine the distance from point 2 to either of the
* intersection points.
*/
h = Math.sqrt((r0*r0) - (a*a));
/* Now determine the offsets of the intersection points from
* point 2.
*/
rx = -dy * (h/d);
ry = dx * (h/d);
/* Determine the absolute intersection points. */
var xi = x2 + rx;
var xi_prime = x2 - rx;
var yi = y2 + ry;
var yi_prime = y2 - ry;
return({x1:xi, y1:yi, x2:xi_prime, y2:yi_prime});
}
&#13;
<canvas id="canvas" width=350 height=350></canvas>
&#13;