Ik ben momenteel bezig met het ontwikkelen van een eenvoudig 2D-spel voor Android. Ik heb een stilstaand object in het midden van het scherm en ik probeer dat object te laten draaien en naar het gebied op het scherm te wijzen dat de gebruiker aanraakt. Ik heb de constante coördinaten die het midden van het scherm vertegenwoordigen en ik kan de coördinaten krijgen van het punt waarop de gebruiker tikt. Ik gebruik de formule die in dit forum wordt beschreven: Hoe krijg ik een hoek tussen twee punten?
-
Er staat het volgende: “Als u de hoek wilt tussen de lijn die wordt gedefinieerd door deze twee punten en de horizontale as:
double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;".
-
Ik heb dit geïmplementeerd, maar ik denk dat het feit dat ik in schermcoördinaten werk een misrekening veroorzaakt, aangezien de Y-coördinaat omgekeerd is. Ik weet niet zeker of dit de juiste manier is om het aan te pakken, andere gedachten of suggesties worden op prijs gesteld.
Antwoord 1, autoriteit 100%
Aannames: X
is de horizontale as, en neemt toe bij beweging van links naar rechts.
Y
is de verticale as en neemt toe van onder naar boven. (touch_x, touch_y)
is de
door de gebruiker gekozen punt. (center_x, center_y)
is het punt in het midden van de
scherm. theta
wordt tegen de klok in gemeten vanaf de as +x
. Dan:
delta_x = touch_x - center_x
delta_y = touch_y - center_y
theta_radians = atan2(delta_y, delta_x)
Bewerken: je hebt in een opmerking vermeld dat y van boven naar beneden toeneemt. In dat
geval,
delta_y = center_y - touch_y
Maar het zou juister zijn om dit te omschrijven als (touch_x, touch_y)
in poolcoördinaten ten opzichte van (center_x, center_y)
. Zoals ChrisF al zei,
het idee om een “hoek tussen twee punten” te nemen is niet goed gedefinieerd.
Antwoord 2, autoriteit 36%
Ik had zelf behoefte aan vergelijkbare functionaliteit, dus na veel haren trekken kwam ik op de onderstaande functie
/**
* Fetches angle relative to screen centre point
* where 3 O'Clock is 0 and 12 O'Clock is 270 degrees
*
* @param screenPoint
* @return angle in degress from 0-360.
*/
public double getAngle(Point screenPoint) {
double dx = screenPoint.getX() - mCentreX;
// Minus to correct for coord re-mapping
double dy = -(screenPoint.getY() - mCentreY);
double inRads = Math.atan2(dy, dx);
// We need to map to coord system when 0 degree is at 3 O'clock, 270 at 12 O'clock
if (inRads < 0)
inRads = Math.abs(inRads);
else
inRads = 2 * Math.PI - inRads;
return Math.toDegrees(inRads);
}
Antwoord 3, autoriteit 26%
Een paar antwoorden hier hebben geprobeerd het “scherm”-probleem uit te leggen waarbij top left
0,0
is en bottom right
is (positief ) screen width, screen height
. De meeste rasters hebben de Y
-as als positief boven X
en niet onder.
De volgende methode werkt met schermwaarden in plaats van “raster”-waarden. Het enige verschil met het uitgezonderde antwoord is dat de Y
-waarden worden omgekeerd.
/**
* Work out the angle from the x horizontal winding anti-clockwise
* in screen space.
*
* The value returned from the following should be 315.
* <pre>
* x,y -------------
* | 1,1
* | \
* | \
* | 2,2
* </pre>
* @param p1
* @param p2
* @return - a double from 0 to 360
*/
public static double angleOf(PointF p1, PointF p2) {
// NOTE: Remember that most math has the Y axis as positive above the X.
// However, for screens we have Y as positive below. For this reason,
// the Y values are inverted to get the expected results.
final double deltaY = (p1.y - p2.y);
final double deltaX = (p2.x - p1.x);
final double result = Math.toDegrees(Math.atan2(deltaY, deltaX));
return (result < 0) ? (360d + result) : result;
}
Antwoord 4
“de oorsprong bevindt zich in de linkerbovenhoek van het scherm en de Y-coördinaat neemt toe naar beneden, terwijl de X-coördinaat naar rechts toeneemt zoals normaal. Ik denk dat mijn vraag wordt, moet ik de schermcoördinaten omrekenen naar cartesiaanse coördinaten voordat u de bovenstaande formule toepast?”
Als u de hoek zou berekenen met behulp van cartesiaanse coördinaten en beide punten in kwadrant 1 zouden zijn (waarbij x>0 en y>0), zou de situatie identiek zijn aan de pixelcoördinaten op het scherm (behalve het omgekeerde Y-ding Als je Y negeert om het met de goede kant naar boven te krijgen, wordt het kwadrant 4…). Het converteren van schermpixelcoördinaten naar Cartesiaans verandert de hoek niet echt.
Antwoord 5
in Android deed ik dit met kotlin:
private fun angleBetweenPoints(a: PointF, b: PointF): Double {
val deltaY = abs(b.y - a.y)
val deltaX = abs(b.x - a.x)
return Math.toDegrees(atan2(deltaY.toDouble(), deltaX.toDouble()))
}
Antwoord 6
met pygame:
dy = p1.y - p2.y
dX = p2.x - p1.x
rads = atan2(dy,dx)
degs = degrees(rads)
if degs < 0 :
degs +=90
het werkt voor mij
Antwoord 7
fun calculateAngle(
touchX: Float,
touchY: Float,
centerX: Float,
centerY: Float
): Float {
val deltaX = centerX - touchX
val deltaY = centerY - touchY
return Math.toDegrees(atan2(deltaY.toDouble(), deltaX.toDouble())).toFloat()
}
Deze functie retourneert een waarde zoals
Als we + 180
naar de retourwaarde gaan, krijgen we de waarde van rechts naar linkszoals
360(<=> 0) -> 45 -> 90 -> 135 -> 180 -> 225 -> 270 -> 315
vergelijkbaar met de hoek wanneer we drawArc