电弧从A到B

时间:2016-06-20 17:59:17

标签: javascript jquery math canvas

我的目标是将圆圈的位置朝向鼠标光标的位置,这都是相对于通过画布观看的世界。为了控制圆移动的速度我决定使边界大于圆,如果鼠标在边界之外,那么鼠标的“位置”将被带到边界,这样当我朝向边界时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的坐标。 enter image description here

2 个答案:

答案 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;
    }