2016-06-20 4 views
0

Ziel ist es, die Position eines Kreises in Richtung der Position des Mauszeigers zu zeichnen, alles relativ zur Welt, die durch die Leinwand betrachtet wird. Um die Geschwindigkeit, mit der sich der Kreis bewegt, im Griff zu behalten, entschied ich mich, eine Grenze größer als der Kreis zu machen. Wenn die Maus außerhalb der Grenze ist, wird die "Position" der Maus an die Grenze gebracht Wenn sie nicht weit von der Position des Kreises entfernt sind, bewegt sie sich nicht mit verrückten Geschwindigkeiten. Ich habe diese Arbeit, und das ist der Code, der es tut:Lichtbogenkoordinaten von A bis 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; 
     } 
    } 

Die Magie für ‚außerhalb der Grenze‘ liegt das do während withing. Dies ist die beste Lösung, die ich mir vorstellen konnte, und ich kann das nicht als eine elegante oder schnelle Lösung betrachten und frage mich, was die richtige Vorgehensweise sein sollte.

Ich bin kein Künstler, aber hoffentlich hilft dieses Bild zu veranschaulichen, was ich zu erreichen versuche. Der schwarze Punkt ist die Mausposition, der schwarze Kreis ist der Kreis und der rote Kreis ist die Grenze, die ich angegeben habe. Ich mag die coords durch die X markiert bekommen enter image description here

+0

Nur eine Randnotiz, die ich vergessen zu erwähnen, ist dies vollständig in Javascript erfolgt. – Rhexis

+0

Müssen Sie eine Koordinate eines Punktes im Kreis mit gegebenem Radius (gegebener Mittelpunkt und Mauskoordinate) finden? – MBo

Antwort

3

Ihre Frage ist ein Spezialfall von Circle line-segment collision detection algorithm?, in diesem Fall mit B und C die gleichen Punkte zu sein, so dass Sie Ihren Mittelpunkt für beide verwenden können.

Diese Lösung in C gegeben ist, aber es übersetzt JavaScript sehr leicht, ersetzen Sie einfach float mit var verwenden Math.sqrt() und so weiter ...

Ach ja, und dann gibt es eine JvaScript Version hier ist: Calculate the point of intersection of circle and line through the center, das ist besser geeignet :-)

+0

Das sieht so aus, als könnte es perfekt sein, ich muss es nur ändern, um ein Punkt anstelle einer Linie zu werden, oder? (setze Anfang und Ende der Zeile auf den gleichen Wert, in diesem Fall die Mausposition) – Rhexis

+1

Nein, du verstehst das falsch. Die Endpunkte der Linie sind der Kreismittelpunkt und die Maus. Ihr Kreuz ist der Schnittpunkt zwischen dieser Linie und dem roten Kreis. –

+0

Ah richtig! Mein Fehler, ich verstehe jetzt. Ich habe es funktioniert, vielen Dank! Ich bin ein bisschen langsam im Moment, es ist fast 5 Uhr morgens. – Rhexis

0

wenn der schwarze Kreis in der Mitte des roten Kreises ist, und Sie haben den Radius des roten Kreises

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

und wenn die t Der Start der Linie ist nicht der Mittelpunkt, dann löst eine Allzweck-Kreisfangfunktion das Problem. Wenn die Linie innerhalb des Kreises beginnt, gibt die Funktion nur einen Punkt zurück. Wenn die Zeile nicht lang genug ist, wird ein leeres Array zurückgegeben.

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