Ich entwickle ein 2D-Weltraumspiel ohne Reibung und finde es sehr einfach, eine Homing Missile-Umlaufbahn zum Ziel zu machen. Ich bin neugierig auf Anti-Orbiting-Strategien.
Ein einfaches Beispiel ist eine Zielsuchrakete, die einfach direkt auf ihr Ziel zu beschleunigt. Wenn sich dieses Ziel senkrecht zur Flugbahn des Flugkörpers bewegen würde, würde die Beschleunigung des Flugkörpers in Richtung des Ziels nicht ausreichen, um seine eigene Geschwindigkeit zu überwinden, und der Flugkörper könnte in die Umlaufbahn um das Ziel gefahren werden, wie dargestellt:
- In Frame 1 steuert die Rakete problemlos direkt auf ihr Ziel zu.
- In Bild 2 hat sich das Ziel wie gezeigt an eine neue Position bewegt. Die Rakete beschleunigt weiterhin direkt auf das Ziel zu (in Rot), während sie sich aufgrund ihrer vorhandenen Geschwindigkeit immer noch auf die Position des Ziels zubewegt (in Schwarz).
- In Bild 3 trägt die Geschwindigkeit des Flugkörpers den Flugkörper weiterhin um die Seite des Ziels (schwarz), während der Beschleunigungsvektor verzweifelt versucht, den Flugkörper in Richtung des Ziels zu ziehen.
- Ab Frame 4 gerät die Rakete in eine potenziell stabile Umlaufbahn um das Ziel und erreicht das Ziel nie. Die schwarzen Pfeile zeigen einen Geschwindigkeitsvektor an, während die roten Linien Beschleunigungsvektoren zum gleichen Zeitpunkt anzeigen.
Wenn man bedenkt, dass es keine Reibung im Weltraum gibt, gibt es nichts, was die Geschwindigkeit des Flugkörpers verlangsamen und die Umlaufbahn kollabieren lässt. Eine mögliche Lösung wäre, "hinter" das Ziel zu zielen, und dies würde dazu führen, dass sich die Umlaufbahn schließt. Aber wie wird dies vom Standpunkt der Programmierung aus getan?
Wie bringe ich eine Zielsuchrakete zum Ziel?
Antworten:
Zunächst einmal sollten Sie alle Berechnungen machen Beschleunigung , was in der anzuwenden Rakete Bezugsrahmen (das ist , wo die Rakete stationär ist und alles andere bewegt sich um ihn herum, auch oft als „Objektkoordinaten“ oder „lokale Koordinaten“ in Game - Engines genannt, in unserem Fall wollen wir aber auch, dass die Geschwindigkeit genau Null ist).
Die Idee ist dann nicht, auf das Ziel zu zielen, sondern auf den Ort, an dem sich das Ziel zum geschätzten Zeitpunkt des Aufpralls befindet. Der allgemeine Algorithmus sieht also so aus:
Schätzen Sie, wie viel Zeit die Rakete benötigt, um das Ziel zu erreichen. Wenn das Ziel direkt darauf fliegt (denken Sie daran, dass die Rakete stationär ist ), kann dies so einfach wie die Berechnung der Entfernung / Geschwindigkeit sein , in anderen Fällen kann es komplizierter sein. Wenn das Ziel es versuchen und ausweichen kann, ist es ohnehin nicht möglich, eine perfekte Schätzung vorzunehmen, daher ist es in Ordnung, nicht sehr genau zu sein.
Unter der Annahme einer konstanten Geschwindigkeit (Schätzung des ersten Grades) oder einer konstanten Beschleunigung (Schätzung des zweiten Grades) des Ziels berechnen Sie, wo es sich zum obigen geschätzten Zeitpunkt befinden wird.
Berechnen Sie die Beschleunigung, die dazu führt, dass sich die Rakete ungefähr am selben Ort zur selben Zeit befindet.
Projizieren Sie die Beschleunigung vom Referenzrahmen des Flugkörpers auf den globalen zurück, verwenden Sie diesen.
Der wichtige Teil hierbei ist, die Zeitschätzung im rauen Ballpark zu erhalten und dabei die Beschleunigungsfähigkeiten des Flugkörpers nicht zu vergessen. Eine bessere Schätzung für "das Ziel ist direkt vor uns und fliegt in unsere Richtung" wäre beispielsweise, die Gleichung zu lösen.
Entfernung = Geschwindigkeit x Zeit + 1/2 x Beschleunigung x Zeit 2
... für Zeit (negative Geschwindigkeit für Objekte verwenden , gerade fliegen weg von der Rakete), mit der Lösung , die Sie suchen mit dem Standard quadratische Formel zu sein ...
Zeit = (√ ( Geschwindigkeit 2 + 2 x Beschleunigung x Distanz ) - Geschwindigkeit ) / Beschleunigung
Das Hinzufügen zusätzlicher Parameter - beispielsweise Ziehen - macht dies schnell zu Differentialgleichungen ohne algebraische Lösungen. Deshalb ist Raketenwissenschaft so schwer.
quelle
@Martin Sojka hat dir bereits gesagt, was du tun sollst. Anstatt seine Reaktion zu verbessern, möchte ich Ihnen einen weiteren einfacheren Ansatz vorschlagen: DELOCK
Wie gesagt in Projizierte Flugbahn eines Fahrzeugs? Objekte mit begrenzten Lenkfähigkeiten "projizieren" ein paar Schattenkreise: zwei Bereiche, die nicht über direkte Lenkung erreicht werden können (ein Torus und ein Hypertorus in höheren Dimensionen).
Wenn Sie sehen, dass Ihr Ziel in einen dieser Lenkschatten einfährt, können Sie die Zielsuche beenden und für eine begrenzte Zeit eine andere Richtung einhalten.
Der Delocking-Trigger kann einfach berechnet werden, indem Sie Ihre Tori mit einem (Doppel-) Kegel * approximieren:
Sie müssen einfach das Skalarprodukt zwischen Ihrem (normalisierten) Richtungsvektor und Ihrem Zielverschiebungsvektor ( Ziel - Objekt / | Ziel - Objekt |) berechnen .
Wenn das Skalarprodukt auf Null geht, wird Ihre Zielrichtung senkrecht zu Ihrer Richtung und führt zu einer kreisförmigen Flugbahn **. Wenn das Ziel in den Cyan-Bereich fällt, können Sie die Lenkrichtung umkehren, um es außerhalb des nicht erreichbaren Bereichs zu platzieren und eine neue Referenzfahrt durchzuführen.
* Um ehrlich zu sein, ist dies kein Kegel ... eine andere Art von Regelfläche, die durch (halbe) Umdrehung zweier nicht paralleler Linien um eine Achse erzeugt wird, die durch den Schnittpunkt verläuft und senkrecht zur Winkelhalbierenden verläuft. Die Projektion in einer 2D-Ebene entspricht der des Doppelkegels, die Rotationsachse verläuft jedoch senkrecht zu der Achse, die den Kegel erzeugt.
** Es ist unwahrscheinlich, dass diese Flugbahn kreisförmig oder elliptisch oder gar geschlossen ist. Es besteht die Möglichkeit, dass die Flugbahn in 2D einem spirographenähnlichen Pfad (einer Hypotrochoide) oder sogar anderen Monstern in 3 oder mehr Dimensionen folgt. Sie können den Mittelpunkt solcher Kurven ohnehin nicht erreichen und sie sehen aus wie Kreise, also "kreisförmige" Flugbahn.
quelle
Ihr Leitsystem basiert auf der Annahme, dass eine Beschleunigung direkt auf das Ziel zu einer Kollision der Objekte führen kann. Da diese Annahme falsch ist, ist die auf dieser Annahme basierende Leit-KI ebenfalls erfolglos.
Hören Sie also auf, direkt auf das Ziel zu beschleunigen . Fügen Sie eine Logik hinzu, um festzustellen, ob die Position des Ziels etwas senkrecht zur Bewegungsrichtung des Flugkörpers ist. Wenn ja, muss die Rakete auf das Ziel zu beschleunigen, aber auch ihre Vorwärtsbewegung verlangsamen. Anstatt direkt auf das Ziel zuzugehen, spannt es die Richtung seiner Beschleunigung vor, so dass die aktuelle Geschwindigkeit in seiner Bewegungsrichtung verlangsamt wird.
Außerdem benötigen Sie einen Auslöser, um sicherzustellen, dass Sie nicht zu langsam fahren. Fügen Sie also eine bestimmte Schwellengeschwindigkeit hinzu, sodass Sie aufhören, die Vorspannung vorzunehmen, wenn Sie unter dieser Schwelle liegen.
Eine letzte Sache: Kein Leitsystem wird perfekt sein. Der Grund, warum Raketen Ziele im wirklichen Leben abfangen können, ist, dass sich Ziele viel langsamer bewegen als die Raketen selbst, und die Ziele sind nicht besonders wendig (relativ gesehen). Wenn Ihre Raketen nicht um ein Vielfaches schneller sind als die Ziele, die sie verfolgen, dann verfehlen sie eine Menge.
quelle
Die einfachste und fortschrittlichste Methode, um dies in Spielen (und im wirklichen Leben) zu tun, ist die proportionale Navigation.
Unter dem Constant Bearing Abnehm Range (CBDR) Logik, wenn zwei Objekte (Raketen- und Ziel) in derselben Richtung ohne Änderung zwischen sich in Ansichtsbreite reisen, sie werden kollidieren.
Die Sichtlinie oder Line of Sight (LOS) ist eine imaginäre Linie zwischen Rakete und Ziel - der Vektor zwischen Raketenposition und Zielposition. Die Winkeländerungsrate dieses LOS ist die LOS-Rotationsrate.
Wenn die LOS-Rotationsrate Null wird, ändert sich die Sichtlinie nicht mehr - die beiden Objekte befinden sich jetzt auf einem Kollisionskurs. Stellen Sie sich vor, Sie jagen jemanden, während Sie Fußball spielen. Wenn Sie ihn so führen, dass sein Körper in Ihrem Sichtfeld "eingefroren" aussieht (Sichtlinie zwischen Ihnen und ihm ändert sich nicht mehr), stoßen Sie mit ihm zusammen, solange Sie Ihre Laufbeschleunigung beibehalten, damit sein Körper eingefroren erscheint deine Ansicht.
Unter Proportional Navigation (PN) beschleunigt die Rakete "N" -mal schneller als die LOS-Rotationsrate. Dadurch wird die Rakete gezwungen, das Ziel zu führen, bis die LOS-Rotationsrate Null wird. Das heißt, Rakete und Ziel werden eingefroren angezeigt, da sich die Sichtlinie nicht mehr ändert. Sie befinden sich jetzt auf Kollisionskurs. Die Variable "N" ist als Navigationskonstante (ein konstanter Multiplikator) bekannt.
Der Lenkbefehl der Rakete sollte wie folgt gegeben werden:
Beschleunigung = Schließgeschwindigkeit * N * LOS Rate
Die LOS-Rate kann leicht abgeleitet werden, indem der LOS-Vektor (Zielposition - Raketenposition) gemessen und seine Variable gespeichert wird. Der LOS-Vektor aus dem neuen Frame (LOS1) wird vom LOS-Vektor aus dem alten Frame (LOS0) subtrahiert, um ein Delta von LOS zu erzeugen - jetzt haben Sie eine primitive LOS-Rotationsrate.
Um die Schließgeschwindigkeit zu vereinfachen, können Sie einfach den aktuellen LOS-Vektor an seiner Stelle verwenden.
Beschleunigung = (target_pos - missile_pos) * LOS_delta * N
N ist die Navigationskonstante - in der realen Welt liegt sie normalerweise zwischen 3 und 5, aber die tatsächlich realisierbare Zahl im Spiel hängt in gewissem Maße von der Abtastrate ab, bei der Sie die LOS-Rate / Delta ableiten. Versuchen Sie es mit einer Zufallszahl (ab 3) und erhöhen Sie sie auf 1500, 2000 usw., bis Sie den gewünschten Haupteffekt im Spiel sehen. Beachten Sie, dass je höher die Navigationskonstante, desto schneller die Rakete auf LOS-Ratenänderungen zu Beginn des Flugs reagiert. Wenn Ihr Homing Rocket-Simulationsmodell etwas realistisch ist, kann eine zu hohe Navigationskonstante die aerodynamischen Fähigkeiten Ihres Flugkörpers überlasten. Verwenden Sie daher eine auf Versuchen und Irrtümern basierende, ausgeglichene Zahl.
quelle
Wie die anderen Antworten von Martin und Nicol zeigen, möchten Sie Ihre Rakete wahrscheinlich nicht direkt auf das Ziel richten, sondern so, dass sie später mit dem Ziel kollidiert. Die von Martin beschriebene Methode ist jedoch kompliziert und die von Nicol beschriebene ineffizient.
Eine einfachere und dennoch sehr effiziente Möglichkeit, eine Rakete zu steuern, besteht darin, ihren Winkel entsprechend der Winkeländerung zwischen Rakete und Ziel anzupassen. Bei jedem Tick berechnen Sie den Winkel von der Rakete zum Ziel und vergleichen ihn mit dem Winkel des vorherigen Ticks. Der Unterschied ist der genaue Unterschied, den Sie in Bezug auf den Raketenwinkel machen möchten. Wenn der Winkel also 0,77 in einem Tick und 0,75 in dem nächsten Tick war, möchten Sie den Raketenwinkel um -0,02 einstellen. Diese Methode ist einfach und solange sich das Ziel "vor" der Rakete befindet, ist es in Bezug auf die gewählte Route sehr effizient. Es gilt auch für eine beliebige Anzahl von Dimensionen, nicht nur in 2d.
Beachten Sie jedoch Folgendes:
Diese Methode bricht ab, wenn Rakete und Ziel exakt gleich schnell sind und sich parallel bewegen. Nun, theoretisch zeichnet es immer noch einen Kollisionskurs für die Rakete auf, es dauert nur unendlich lange :) In der Praxis sollte die Rakete immer schneller als das Ziel sein, aber wenn sie die gleiche Geschwindigkeit haben, müssen Sie einen Eckfall hinzufügen, um festzustellen, ob sie parallel sind .
Die Methode bricht ab, wenn das Ziel und der Flugkörper genau auf der gleichen Linie fliegen, aber in entgegengesetzte Richtungen. Das kann in der realen Welt nicht wirklich passieren, ist aber in einem diskreten Spiel nicht allzu ungewöhnlich. Sie müssen dem obigen Algorithmus eine Eckfallprüfung hinzufügen, um dies zu testen.
Wenn Ihre Rakete nur eine eingeschränkte Wendefähigkeit hat, lassen Sie sie jedes Mal, wenn sie mehr als diese Wendefähigkeit benötigt, die maximale Wendefähigkeit ausführen. Solange die Rakete weit genug ist, funktioniert sie noch. Wenn es zu nah ist, sehen Sie die letzte Kugel.
Denken Sie daran, bei der Überprüfung der Kollision nachsichtig zu sein. In der realen Welt verlassen sich viele Raketen auf ihren Gefechtskopf, um eine "Abschusszone" zu erzeugen, sodass sie nur in die Nähe des Ziels gelangen müssen und nicht tatsächlich damit kollidieren.
Schließlich kann in der Praxis die Rakete noch fehlen , was uns zu Ihrer ursprünglichen Frage zurückbringt. Ich denke, ein guter Weg ist es, die Referenzfahrt für ein paar Zecken zu deaktivieren, eine gewisse Distanz zu erreichen und sie dann erneut zu starten. Ich denke, die von fxiii vorgeschlagene Methode zur Identifizierung von Totzonen ist eine großartige Möglichkeit, um zu erkennen, wann Sie die Referenzfahrt ausschalten müssen.
quelle
Einige einfache Optionen, die sich für Spiele, an denen ich in der Vergangenheit gearbeitet habe, als "gut genug" erwiesen haben:
1) Wenn die Auflösung der betrachteten Szene dies zulässt, kann das Objekt explodieren, wenn es sich in der Nähe des Ziels befindet. Wenn Ihre Umlaufbahn etwa doppelt so groß ist wie das entfernte Objekt, funktioniert dies wahrscheinlich nicht für Sie, da es nur schlecht aussehen würde.
Wenn Ihr Endziel in Ihrer Lösung einfach darin besteht, sicherzustellen, dass Ihre Rakete das Ziel trifft, dann bin ich alles dafür, nur dafür zu sorgen, dass es das Ziel trifft. Auch dies wird nur davon abhängen, wie die Lösung aussieht.
2) Wenn Sie feststellen, dass sich Ihre Rakete im rechten Winkel zu Ihrem Ziel befindet, kann dies der Punkt sein, an dem die Sperre "aufbricht" und die Rakete sich nur geradeaus bewegt, es sei denn, das Ziel befindet sich wieder "vor" der Rakete.
Ich bevorzuge immer einfache Lösungen, wann immer dies möglich ist. Wenn Sie ein Spiel machen, in dem die Zielsuchrakete nur eine der Waffen ist, die verwendet werden, können Sie wahrscheinlich mit diesen davonkommen, da die Spieler wahrscheinlich eine Salve abfeuern und dann so schnell wie möglich zu ihren Waffen mit ständigem Angriff zurückkehren. Wenn Sie jedoch eine Raketensimulation durchführen, ist eindeutig eine der anderen Antworten die bessere Wahl.
Hoffe das hilft.
quelle
Wie bereits gesagt, sollten Sie die Rakete auf den Ort richten, an dem sich das Ziel voraussichtlich befindet, wenn Sie dort ankommen, und nicht auf den Ort, an dem sich das Ziel gerade befindet. Dies verhindert, dass die meisten Raketen in die Umlaufbahn gelangen. Eine Umlaufbahn ist jedoch weiterhin möglich, wenn das Ziel genau ausweicht. Dies ist eine legitime Taktik, die von Flugzeugpiloten angewendet wird, um ankommenden Raketen auszuweichen. Da die Rakete viel schneller als Sie fährt, hat sie einen größeren Wenderadius, und ein scharfer Knick im richtigen Moment lässt sie vorbeiziehen. (Obwohl Sie immer noch durch eine Detonation in der Nähe gefährdet sein könnten.)
Da es sich um eine Rakete handelt, die immer noch verfolgen kann und immer noch einen Schub hat, kommt es zu einer Umlaufbahnsituation, wenn das Ziel in eine der Zonen ausweicht, von denen FxIIIs Posten spricht.
Ich bin jedoch nicht mit seiner Lösung des Problems einverstanden. Stattdessen würde ich die Raketen folgendermaßen programmieren:
Wenn die Rakete um 90 Grad in ihre Bewegungslinie geschoben wurde, befinden Sie sich in der Umlaufbahn. Stellen Sie den Schub auf 120 Grad von der Bewegungslinie ein. Die Umlaufbahn der Rakete wird größer, da sie sich nicht so stark dreht, aber die Rakete wird auch langsamer, so dass sie besser manövrieren kann. Wenn sich die Reichweite zum Ziel auf das 1,25-fache des Durchmessers der toten Zone öffnet (beachten Sie, dass dieser Durchmesser einfach und nur auf der Geschwindigkeit des Flugkörpers basiert, zur Laufzeit ist keine komplexe Berechnung erforderlich), kehrt der Flugkörper zu seinem normalen Verfolgungsverhalten zurück.
Verwenden Sie alternativ stumpfe Sucherköpfe - wenn die Reichweite des Ziels nicht mehr abwärts zählt, detonieren Sie.
quelle
Ich weiß, dass dies eine veraltete Frage ist, aber ich denke, dass in den bisher gegebenen Antworten etwas verpasst wurde. In der ursprünglichen Frage wurde der Rakete (oder was auch immer) befohlen, auf die Position des Ziels zu beschleunigen. In mehreren Antworten wurde darauf hingewiesen, dass dies falsch war, und Sie sollten beschleunigen, bis Sie das Ziel zu einem späteren Zeitpunkt erreicht haben. Das ist besser aber immer noch falsch.
Was Sie wirklich tun möchten, ist nicht auf das Ziel zu beschleunigen, sondern sich auf das Ziel zu bewegen . Die Art und Weise, wie Sie darüber nachdenken, besteht darin, Ihre gewünschte Geschwindigkeit auf das Ziel zu richten (oder eine Projektion des Zielorts) und dann herauszufinden, welche Beschleunigung Sie am besten anwenden können (ungeachtet der Einschränkungen, die Sie haben, dh eine Rakete kann wahrscheinlich nicht beschleunigen direkt in umgekehrter Richtung), um die gewünschte Geschwindigkeit zu erreichen (wobei zu beachten ist, dass die Geschwindigkeit ein Vektor ist).
Hier ist ein Beispiel, das ich heute Morgen umgesetzt habe, in meinem Fall für eine Spieler-KI in einem Sportsimulationsspiel, in dem der Spieler versucht, seinen Gegner zu jagen. Die Bewegung wird von einem Standardmodell für "Kick-Drift" gesteuert, bei dem zu Beginn eines Zeitschritts Beschleunigungen angewendet werden, um die Geschwindigkeiten zu aktualisieren, und Objekte dann für die Dauer des Zeitschritts mit dieser Geschwindigkeit driften.
Ich würde die Ableitung hiervon posten, aber ich habe festgestellt, dass auf dieser Site kein mathematisches Markup unterstützt wird. Boo! Sie müssen nur darauf vertrauen, dass dies die optimale Lösung ist, da ich keine Einschränkungen in Bezug auf die Beschleunigungsrichtung habe, was für ein Objekt vom Typ Rakete nicht der Fall ist und daher einige zusätzliche Einschränkungen erfordern würde.
Code ist in Python, sollte aber mit jedem Sprachhintergrund lesbar sein. Der Einfachheit halber gehe ich davon aus, dass jeder Schritt eine Länge von 1 hat, und drücke die Geschwindigkeit und Beschleunigung in geeigneten Einheiten aus, um dies widerzuspiegeln.
Beachten Sie, dass die Funktion atan2 (a, b) die Inverse tan von a / b berechnet, jedoch sicherstellt, dass die Winkel im richtigen Quadranten eines Kreises liegen, wofür das Vorzeichen von a und b bekannt sein muss.
In meinem Fall, sobald ich die Beschleunigung habe, wende ich das an, um die Geschwindigkeit durch zu aktualisieren
Ich überprüfe auch die neue Geschwindigkeit gegen eine spielerabhängige Höchstgeschwindigkeit und beschränke sie dabei. Bei einer Rakete, einem Auto oder etwas anderem mit einer maximalen Wendegeschwindigkeit (in Grad pro Tick) können Sie einfach den aktuellen Bewegungswinkel gegenüber dem berechneten Ideal betrachten. Wenn diese Änderung größer als zulässig ist, ändern Sie den Winkel einfach um as viel wie möglich in Richtung des Ideals.
Für jeden, der daran interessiert ist, habe ich die Entfernung zwischen Spieler und Ziel nach dem Timstep in Bezug auf die Ausgangsposition, die Geschwindigkeit, die Beschleunigungsrate und den Beschleunigungswinkel notiert und dann die Ableitung in Bezug auf den Beschleunigungswinkel vorgenommen. Wenn Sie diesen Wert auf Null setzen, wird das Minimum der Zielentfernung nach dem Zeitschritt als Funktion des Beschleunigungswinkels ermittelt. Genau das möchten wir wissen. Obwohl die Beschleunigungsrate ursprünglich in den Gleichungen enthalten war, hebt sie interessanterweise die Ermittlung der optimalen Richtung auf, unabhängig davon, wie viel Sie tatsächlich beschleunigen können.
quelle
Sie verwenden eine konstante Drehgeschwindigkeit. Genau das bewirkt die schöne, perfekt kreisförmige Umlaufbahn.
Ein realistischerer Ansatz für ein Leitsystem wäre, die Abbiegerate mit umgekehrtem Zielabstand zu variieren (weniger Abstand -> mehr Abbiegerate). Dies würde eher eine Spirale als eine Umlaufbahn ergeben und eine Kollision mit einem langsameren Ziel garantieren.
Es gibt auch eine viel realistischere Flugbahn. Die konstante Drehrate ist unnatürlich perfekt. Sie können auch zufällige Variationen zur Drehzahl hinzufügen, um Turbulenzen zu simulieren. Wiederum viel realistischer und kann tatsächlich stationäre Umlaufszenarien vermeiden.
Keine Notwendigkeit für Teilgleichungen.
quelle