簡體   English   中英

弧線從A到B

[英]Arcing coords from A to B

我的目標是將圓弧的位置朝向鼠標光標的位置,這都是相對於通過畫布查看的世界而言的。 為了控制圓的移動速度,我決定使邊界大於圓,如果鼠標位於邊界之外,則將鼠標的“位置”移至邊界處,以便當我向圓弧方向移動時坐標,如果它們不在圓的位置以外,則不會以瘋狂的速度移動。 我有這個工作,這是做到這一點的代碼:

    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的坐標。 在此處輸入圖片說明

您的問題是Circle線段碰撞檢測算法的特例 ,在這種情況下,B和C是相同的點,因此您可以將它們的中心點都使用。

該解決方案是用C語言給出的,但是它很容易轉換為JavaScript,只需將float替換為var ,使用Math.sqrt()等等。

哦,這里有一個JvaScript版本: 計算通過中心的圓和線的交點 ,這更合適:-)

如果黑色圓圈在紅色圓圈的中心,並且您具有紅色圓圈的半徑

// 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;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM