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).
Vector TargetInitialPosition = new Vector ( target.X - source.X ,
target.Y - source.Y );
Vector TargetApparentVelocity = new Vector( target.velocityX - source.velocityX ,
target.velocityY - source.velocityY );
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:
// Your directional vector MUST be normalized...
Vector BulletVelocity = new Vector( source.directionX * Bullet::StaticSpeed + source.velocityX ,
source.directionY * Bullet::StaticSpeed + source.velocityY );
Das Problem, das Sie haben, ist, dass sich das Ziel bewegt hat, bis die Kugel es erreicht.
TargetPosition = TargetInitialPosition + TargetApparentVelocity * t
BulletPosition = BulletInitialPosition + BulletVelocity * t
= BulletVelocity * t
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:
TargetInitialPosition + ( TargetApparentVelocity - BulletVelocity ) * t == 0
dV / dt = TargetApparentVelocity - BulletVelocity
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.
TargetApparentVelocity.X - BulletVelocity.X == k * -TargetInitialPosition.X
k = ( BulletVelocity.X - TargetApparentVelocity.X ) / TargetInitialPosition.X
----------------------
TargetApparentVelocity.Y - BulletVelocity.Y == k * -TargetInitialPosition.Y
k = ( BulletVelocity.Y - TargetApparentVelocity.Y ) / TargetInitialPosition.Y
mach sie gleich:
( BulletVelocity.X - TargetApparentVelocity.X ) / TargetInitialPosition.X
= ( BulletVelocity.Y - TargetApparentVelocity.Y ) / TargetInitialPosition.Y
oder um die Variablen zu erweitern:
( source.directionX * Bullet::StaticSpeed + source.velocityX - target.velocityX + source.velocityX ) / ( target.X - source.X )
== ( source.directionY * Bullet::StaticSpeed + source.velocityY - target.velocityY + source.velocityY ) / ( target.Y - source.Y )
Dann gibt Ihnen die Algebra Ihre endgültige Gleichung:
source.directionY = ( target.velocityY * ( source.X - target.X ) - 2 * source.velocityY * ( source.X - target.X ) + ( Bullet::Speed * source.directionX + 2 * source.velocityX - target.velocityX ) * ( source.Y - target.Y ) ) / ( Bullet::Speed * ( source.X - target.X ) )
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.
sqrt( source.directionX ^ 2 + source.directionY ^ 2 ) == 1
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.