我的目标是将圆圈的位置朝向鼠标光标的位置,这都是相对于通过画布观看的世界。为了控制圆移动的速度我决定使边界大于圆,如果鼠标在边界之外,那么鼠标的“位置”将被带到边界,这样当我朝向边界时coords,如果它们离圆圈的位置不远,它就不会以疯狂的速度移动。我有这个工作,这是代码:
dx = Game.controls.mouseX - (this.x - xView); // get the distance between the x coords
dy = Game.controls.mouseY - (this.y - yView); // get the distance between the y coords
radii = this.radius + 1; // +1 because the "radius" of the mouse is 1
if((dx * dx) + (dy * dy) > radii * radii) // is the mouse not over the player?
{
if((dx * dx) + (dy * dy) < 301 * 301)
{
this.x += ((Game.controls.mouseX - (this.x - xView)) * 2 / (this.mass)) + step;
this.y += ((Game.controls.mouseY - (this.y - yView)) * 2 / (this.mass)) + step;
}
else
{
mx = Game.controls.mouseX;
my = Game.controls.mouseY;
do
{
dx = mx - (this.x - xView);
dy = my - (this.y - yView);
mx += (((this.x - xView) - mx) * 2 / (this.mass)) + step;
my += (((this.y - yView) - my) * 2 / (this.mass)) + step;
} while((dx * dx) + (dy * dy) > 301 * 301)
this.x += ((mx - (this.x - xView)) * 2 / (this.mass)) + step;
this.y += ((my - (this.y - yView)) * 2 / (this.mass)) + step;
}
}
“边界之外”的魔力在于同时。这是我能想到的最好的解决方案,我不能认为这是一个优雅或快速的解决方案,我想知道应该采取什么样的行动。
我不是艺术家,但希望这张图片有助于说明我想要实现的目标。黑点是鼠标pos,黑圈是圆圈,红圈是我指定的边界。我想得到标有X的坐标。
答案 0 :(得分:3)
您的问题是Circle line-segment collision detection algorithm?的一个特例,在这种情况下,B和C是相同的点,因此您可以使用它们的中心点。
该解决方案在C中提供,但它很容易转换为JavaScript,只需将float
替换为var
,使用Math.sqrt()
等等......
哦,然后这里有一个JvaScript版本:Calculate the point of intersection of circle and line through the center,这更合适: - )
答案 1 :(得分:0)
如果黑色圆圈位于红色圆圈的中心,并且您具有红色圆圈的半径
// c is circle center
// mouse is the mouse position. Should have properties x,y
// radius is the circle radius;
// returns the point on the line where the circle intercepts it else it returns undefined.
function findX(c, mouse, radius)
var v = {};
// get the vector to the mouse
v.x = mouse.x - c.x;
v.y = mouse.y - c.y;
var scale = radius / Math.hypot(v.x,v.y);
if(scale < 1){ // is it outside the circle
return {
x : c.x + v.x * scale,
y : c.y + v.y * scale
};
}
return;
}
如果行开头不是中心,那么通用线圈截取函数将解决问题。如果线在圆圈内开始,则该函数将仅返回一个点。如果行不够长,它将返回一个空数组..
// p1,p2 are the start and end points of a line
// returns an array empty if no points found or one or two points depending on the number of intercepts found
// If two points found the first point in the array is the point closest to the line start (p1)
function circleLineIntercept(circle,radius,p1,p2){
var v1 = {};
var v2 = {};
var ret = [];
var u1,u2,b,c,d;
// line as vector
v1.x = p2.x - p1.x;
v1.y = p2.y - p1.y;
// vector to circle center
v2.x = p1.x - circle.x;
v2.y = p1.y - circle.y;
// dot of line and circle
b = (v1.x * v2.x + v1.y * v2.y) * -2;
// length of line squared * 2
c = 2 * (v1.x * v1.x + v1.y * v1.y);
// some math to solve the two triangles made by the intercept points, the circle center and the perpendicular line to the line.
d = Math.sqrt(b * b - 2 * c * (v2.x * v2.x + v2.y * v2.y - radius * radius));
// will give a NaN if no solution
if(isNaN(d)){ // no intercept
return ret;
}
// get the unit distance of each intercept to the line
u1 = (b - d) / c;
u2 = (b + d) / c;
// check the intercept is on the line segment
if(u1 <= 1 && u1 >= 0){
ret.push({x:line.p1.x + v1.x * u1, y : line.p1.y + v1.y * u1 });
}
// check the intercept is on the line segment
if(u2 <= 1 && u2 >= 0){
ret.push({x:line.p1.x + v1.x * u2, y : line.p1.y + v1.y * u2});
}
return ret;
}