Ich habe so wenig Mathe, dass es weh tut, aber für einige von euch sollte dies ein Kinderspiel sein. Ich möchte ein Objekt entlang seines Alters oder Umfangs auf einer einfachen Kreisbahn um ein anderes bewegen. Im Moment weiß mein Spielalgorithmus, wie man ein Sprite direkt am Rand eines Hindernisses bewegt und positioniert, und wartet nun darauf, dass sich der nächste Punkt abhängig von verschiedenen Bedingungen bewegt.
Das mathematische Problem hier ist also, wie man (aX, aY) und (bX, bY) Positionen erhält , wenn ich das Zentrum (cX, cY), die Objektposition (oX, oY) und die Entfernung kenne, die erforderlich ist, um sich zu bewegen (d)
java
mathematics
Lumis
quelle
quelle
d
ein linearer Abstand oder ein Bogen?Antworten:
( CAVEAT: Ich verwende hier zwei Näherungen: Die erste nimmt d als Bogenlänge und die zweite als orthogonale Länge. Beide Näherungen sollten für relativ kleine Werte von d gut sein, aber sie erfüllen nicht die genaue Frage, wie in den Kommentaren geklärt.)
Die Mathematik dazu ist glücklicherweise relativ einfach. Zunächst können wir den relativen Vektor von unserer Mittelposition zu unserer aktuellen Position finden:
Und sobald wir diesen relativen Vektor haben, können wir den Radius des Kreises, an dem wir arbeiten, ermitteln, indem wir dessen Länge ermitteln:
Darüber hinaus können wir anhand unseres relativen Vektors den genauen Winkel ermitteln, in dem sich die Linie von cX nach oX befindet:
Jetzt wird es etwas schwieriger. Verstehen Sie zunächst, dass der Umfang eines Kreises - dh die 'Bogenlänge' eines Bogens mit einem Winkelmaß von 2π - 2πr beträgt. Im Allgemeinen beträgt die Bogenlänge eines Bogens mit einem Winkelmaß von θ entlang eines Kreises mit dem Radius r nur θr. Wenn wir das d in Ihrem Diagramm als Bogenlänge verwenden und den Radius kennen, können wir die Änderung in Theta finden, um an die neue Position zu gelangen, indem wir einfach teilen:
Für den Fall, dass d ein linearer Abstand sein muss, sind die Dinge etwas komplizierter, aber zum Glück nicht viel. Dort ist d eine Seite eines Isozelendreiecks, dessen andere zwei Seiten der Radius des Kreises sind (von cX / cY zu oX / oY bzw. aX / aY), und die Halbierung dieses Isozelendreiecks ergibt zwei rechtwinklige Dreiecke, von denen jedes hat d / 2 als eine Seite und Radius als Hypotenuse; Dies bedeutet, dass der Sinus der Hälfte unseres Winkels (d / 2) / Radius ist und der volle Winkel nur doppelt so groß ist:
Beachten Sie, dass wenn Sie das Asin aus dieser Formel herausnehmen und die 2s stornieren würden, dies dasselbe wäre wie die letzte Formel. Dies ist dasselbe wie zu sagen, dass sin (x) für kleine Werte von x ungefähr x ist, was eine nützliche Annäherung ist, um zu wissen.
Jetzt können wir den neuen Winkel finden, indem wir einfach addieren oder subtrahieren:
Sobald wir den neuen Winkel haben, können wir einen grundlegenden Trigger verwenden, um unseren aktualisierten relativen Vektor zu finden:
und von unserer Mittelposition und unserem relativen Vektor können wir (endlich) den Zielpunkt finden:
Bei alledem sind einige große Vorbehalte zu beachten. Zum einen werden Sie feststellen, dass diese Mathematik meistens Gleitkomma ist, und tatsächlich muss es fast so sein; Wenn Sie versuchen, diese Methode zum Aktualisieren in einer Schleife zu verwenden und bei jedem Schritt auf ganzzahlige Werte zurückzurunden, kann dies dazu führen, dass Ihr Kreis nicht geschlossen wird (entweder jedes Mal, wenn Sie die Schleife umrunden, nach innen oder außen spiralförmig), bis er im ersten Schritt nicht gestartet wird Platz! (Wenn Ihr d zu klein ist, stellen Sie möglicherweise fest, dass die gerundeten Versionen von aX / aY oder bX / bY genau dort sind, wo Ihre Startposition oX / oY war.) Zum anderen ist dies sehr teuer, insbesondere für das, was es versucht tun; Wenn Sie wissen, dass sich Ihr Charakter in einem Kreisbogen bewegen wird, sollten Sie im Allgemeinen den gesamten Bogen im Voraus planen und nichtKreuzen Sie es so von Bild zu Bild an, da viele der teuersten Berechnungen hier vorab geladen werden können, um die Kosten zu senken. Eine andere gute Möglichkeit, die Kosten zu senken, wenn Sie wirklich schrittweise aktualisieren möchten, besteht darin, Trigger überhaupt nicht zu verwenden. Wenn d klein ist und Sie es nicht benötigen, um genau zu sein, sondern nur sehr nahe, können Sie einen 'Trick' ausführen, indem Sie einen Vektor der Länge d zu oX / oY hinzufügen, orthogonal zum Vektor in Richtung Ihrer Mitte (beachten Sie, dass a Der zu (dX, dY) orthogonale Vektor ist durch (-dY, dX) gegeben und wird dann auf die richtige Länge verkleinert. Ich werde diesen Code nicht so Schritt für Schritt erklären, aber hoffentlich macht er angesichts dessen, was Sie bisher gesehen haben, Sinn. Beachten Sie, dass wir den neuen Delta-Vektor im letzten Schritt implizit verkleinern.
quelle
Bilden Sie ein Dreieck mit den beiden Seiten, die Sie bereits haben (eine Seite ist von 'c' bis 'o', die andere von 'o' bis 'a'), und die dritte Seite geht von 'a' bis 'c'. Sie wissen noch nicht, wo 'a' ist. Stellen Sie sich vor, es gibt vorerst einen Punkt. Sie benötigen Trigonometrie, um den Winkel des Winkels zu berechnen, der der Seite 'd' entgegengesetzt ist. Sie haben die Länge der Seiten c <-> o und c <-> a, weil beide der Radius des Kreises sind.
Nachdem Sie die Länge der drei Seiten dieses Dreiecks haben, die Sie noch nicht sehen können, können Sie den Winkel bestimmen, der der 'd'-Seite des Dreiecks entgegengesetzt ist. Hier ist die SSS-Formel (Side-Side-Side), falls erforderlich: http://www.teacherschoice.com.au/maths_library/trigonometry/solve_trig_sss.htm
Mit der SSS-Formel haben Sie den Winkel (den wir 'j' nennen), der der Seite 'd' entgegengesetzt ist. Jetzt können wir also berechnen (aX, aY).
Stellen Sie sicher, dass die Winkel, die Sie berechnen, immer im Bogenmaß sind.
Wenn Sie den Radius des Kreises berechnen müssen, können Sie die Vektorsubtraktion verwenden, den Punkt 'c' vom Punkt 'o' subtrahieren und dann die Länge des resultierenden Vektors ermitteln.
So etwas sollte reichen, glaube ich. Ich kenne Java nicht, daher habe ich die genaue Syntax erraten.
Hier ist das vom Benutzer gegebene Bild, um
Byte56
zu veranschaulichen, wie dieses Dreieck aussehen könnte:quelle
Um obj2 um obj1 drehen zu lassen, versuchen Sie vielleicht:
quelle