Ich sah diese Frage: Vorhersage der feindlichen Position, damit ein Objekt sein Ziel führt . Meine Situation ist allerdings etwas anders.
Mein Ziel bewegt sich und der Schütze bewegt sich. Außerdem wird die Geschwindigkeit des Schützen zu den Geschwindigkeiten der Kugeln addiert, dh Kugeln, die beim Gleiten nach rechts abgefeuert werden, haben eine größere Geschwindigkeit nach rechts.
Ich versuche, den Feind dazu zu bringen, zu bestimmen, wo er schießen muss, um den Spieler zu treffen. Bei Verwendung der verknüpften SO-Lösung führt der Geschwindigkeitsunterschied zu einem Fehlschlag, sofern der Spieler und der Feind nicht stationär sind. Wie kann ich das verhindern?
Hier ist die Lösung aus der Stapelüberlaufantwort. Es läuft darauf hinaus, eine quadratische Gleichung der Form zu lösen:
a * sqr(x) + b * x + c == 0
Beachten Sie, dass sqr
ich damit Quadrat im Gegensatz zur Quadratwurzel meine. Verwenden Sie die folgenden Werte:
a := sqr(target.velocityX) + sqr(target.velocityY) - sqr(projectile_speed)
b := 2 * (target.velocityX * (target.startX - cannon.X)
+ target.velocityY * (target.startY - cannon.Y))
c := sqr(target.startX - cannon.X) + sqr(target.startY - cannon.Y)
Jetzt können wir uns die Diskriminante ansehen, um festzustellen, ob wir eine mögliche Lösung haben.
disc := sqr(b) - 4 * a * c
Wenn die Diskriminante kleiner als 0 ist, vergessen Sie, Ihr Ziel zu treffen - Ihr Projektil kann niemals rechtzeitig dort ankommen. Ansonsten schauen Sie sich zwei mögliche Lösungen an:
t1 := (-b + sqrt(disc)) / (2 * a)
t2 := (-b - sqrt(disc)) / (2 * a)
Beachten Sie, dass wenn disc == 0 ist, t1 und t2 gleich sind.
sq()
anstelle von verwendensqr()
? Es macht es wirklich verwirrend zu lesen.Antworten:
Okay, lassen Sie uns etwas Vernunft in diese Sache stecken. Ich fürchte, Sie machen es überhaupt nicht einfach, Ihr Code wird nicht kompiliert, ist in Bezug auf Variablennamen inkonsistent (
playerVelocityX
wirdplayerXvelocity
nach ein paar Zeilen? Was istxVelocity
?) Und ist zu ausführlich. Es ist im Grunde unmöglich zu debuggen, damit Sie nicht erhebliche Anstrengungen unternehmen.Also, hier sind die Dinge zu beheben:
Geschossgeschwindigkeit
Die Geschossgeschwindigkeit muss
30
Punkt sein. Die von Ihnen durchgeführten Berechnungen sind nicht erforderlich: Die Änderung des Referenzrahmens ist genau dort, um die Komplexität zu vermeiden. Sie addieren die Geschwindigkeit des Feindes erst, nachdem Sie eine Lösung gefunden haben, wenn Sie zum Hauptreferenzrahmen zurückkehren.Gültigkeit der Lösung
Sie überprüfen nicht, ob die
time
Lösung positiv ist.Zahlreiche Codierungsfehler
Sie testen
time1
und verwendentime2
aber immertime1
die Ergebnisse.Sie tun,
playerXvelocity - yVelocity
was inkonsistent ist.Du machst
/ 2 * a
statt/ (2.f * a)
. Dies ist der schlimmste Fehler und deshalb läuft alles schief.Sie berechnen
shootx
undshooty
als Endposition der Kugel, während Sie nach der Geschwindigkeit der Kugel suchen .Code behoben
quelle
playerX += playerVelocityX*t0;
playerY += playerVelocityY*t0;
float bulletX = ((cos(heading * DEGREE2RAD)*bulletSpeed + enemyVelocityX) * t0) + enemyX;
float bulletY = ((sin(heading * DEGREE2RAD) * bulletSpeed + enemyVelocityY) * t0) + enemyY;
Ausgabe ist P = (84.8069.93,0386) E = (88.3793.105.132)bulletSpeed
An dieser Stelle nicht verwenden . Ersetzencos(heading * DEGREE2RAD) * bulletSpeed
durchshootx
. Gleiches gilt fürshooty
. Der Grund ist, dass die Geschwindigkeit des Feindes zur Geschwindigkeit des Geschosses addiert wird und seine Geschwindigkeit nicht mehr genau istbulletSpeed
. Tatsächlich benötigen Sie dieheading
Variable überhaupt nicht, sie ist nur zum Debuggen hilfreich.Ein sich bewegender Schütze ist identisch mit einem stationären Schützen. Subtrahieren Sie einfach den Bewegungsvektor des Schützen vom Bewegungsvektor des Ziels.
Berechnen Sie den Schussvektor / Anfangswinkel und fügen Sie dann den Bewegungsvektor des Ziels wie gewohnt zur Kugel hinzu.
quelle
Hier ist ein Beispiel, in dem ich eine Lösung für das Problem des Predictive Targeting mithilfe eines rekursiven Algorithmus entwickelt und implementiert habe: http://www.newarteest.com/flash/targeting.html (Ich hatte einen stationären Shooter, aber der gleiche Ansatz würde für a funktionieren beweglicher Schütze)
Ich muss einige der anderen vorgestellten Lösungen ausprobieren, da es effizienter erscheint, sie in einem Schritt zu berechnen. Die Lösung bestand jedoch darin, die Zielposition zu schätzen und das Ergebnis in den Algorithmus zurückzugeben, um eine neue zu erstellen genauere Schätzung, mehrmals wiederholt.
Für die erste Schätzung "feuere" ich auf die aktuelle Position des Ziels und benutze dann Trigonometrie, um zu bestimmen, wo sich das Ziel befindet, wenn der Schuss die Position erreicht, auf die geschossen wird. Dann "feuere" ich in der nächsten Iteration an dieser neuen Position und bestimme, wo das Ziel diesmal sein wird. Nach ungefähr 4 Wiederholungen komme ich auf ein Pixel Genauigkeit.
quelle
Da Sie nur mit 2D-Physik arbeiten (keine Z-Geschwindigkeit), kann dieses Problem erheblich vereinfacht werden. Der einfache Weg, dies zu tun, besteht darin, nicht mehr daran zu denken, dass sich Quelle und Ziel relativ zu den Weltkoordinaten bewegen, sondern nur noch daran, dass sich das Ziel relativ zur Quelle bewegt (und die Quelle stationär zu halten).
Normalerweise ist die Geschwindigkeit einer Kugel viel höher als die Geschwindigkeit des Schützen, daher wird normalerweise angenommen, dass die Kugel unabhängig ist, aber es gibt Fälle, in denen dies nicht zutrifft, z. B. das Abfeuern eines Hubschraubers oder eines Kampfjets.
Dann müssen wir die Geschossgeschwindigkeit berechnen:
Das Problem, das Sie haben, ist, dass sich das Ziel bewegt hat, bis die Kugel es erreicht.
und löse nach TargetPosition == BulletPosition, weil dann die Kugel das Ziel getroffen hätte. Jetzt haben Sie drei Unbekannte und nur zwei Gleichungen. Wir können 't' entfernen, indem wir die Ableitung erster Ordnung nehmen:
Nun, um das Ziel zu treffen, möchten Sie
dV/dt == -TargetInitialPosition * k
. Die Konstante muss in den X- und Y-Koordinaten gleich sein und gibt die Anzahl der Sekunden an, die die Kugel benötigt, um das Ziel zu treffen.mach sie gleich:
oder um die Variablen zu erweitern:
Dann gibt Ihnen die Algebra Ihre endgültige Gleichung:
Der nächste Teil ist chaotisch und es liegt an Ihnen, wie Sie ihn in Ihren Code implementieren möchten, aber wir ersetzen ihn einfach in und normalisieren den Vektor.
Am Ende erhalten Sie eine Gleichung mit nur einem Unbekannten (source.directionX), und Sie können sie für directionX lösen und dann wieder einsetzen, um directionY zu erhalten.
Ich habe keinen dieser Codes getestet und kann auf methodische Fehler hinweisen, die ich gemacht habe, aber die Theorie sollte stichhaltig sein :).
Viel Glück.
quelle
Dies ist nur ein 3D-Geometrieproblem.
Zuerst benötigen Sie die relative Position und die relative Geschwindigkeit des Schützen und des Ziels:
Dann müssen Sie die Gleichung lösen:
Zum
t
undx
.Das macht:
Die letzte dieser Gleichungen ist eine einfache quadratische Gleichung, die Sie lösen sollten. Für jedes positive Ergebnis fügen Sie das Ergebnis in die Gleichung ein:
Dies sollte Ihnen jeden möglichen Feuervektor geben, wo
t
die Zeit ist, die der Schuss dauern wird.Beachten Sie, dass es nur eine Lösung gibt , wenn diese
FireSpeed
größer als die Größe ist.Vel
Wenn sieFireSpeed
jedoch kleiner ist, gibt es möglicherweise zwei oder gar keine Lösungen oder in besonderen Fällen nur eine einzige Doppellösung.Bearbeiten: Besser die Mathematik richtig machen oder diese Antwort wird nicht viel gut sein.
quelle