Treffpunkt von 2 Kurven im 3 Dimensionalen Raum

MedRamBO

Mitglied
Hallo,

ich bin seid geraumer Zeit dabei ein kleines Spiel zu Programmieren. Ursprünglich haben wir einen kleinen FPS-Shooter innerhalb eines Schulprojekts programmiert, um ein wenig mit DiriectX zu arbeiten.
Dabei hab ich dann wohl irgentwie richtig Bock dran bekommen. Kennt ihr vielleicht :) Naja, auf jeden Fall bin ich dabei eine Art KI zu programmieren. Natürlich ist die nicht sehr schlau, aber das ist nun mal das Ziel. Wohl möglich könnte man mit einer anständigen KI Bücher füllen^^

Das laufen anhand von vorgegebenen Pfaden klappt soweit ganz gut. Jetzt müssen die künstlichen Programmierschnipsel noch das Zielen lernen.
Dabei bin ich dann auf ein mathematisches Problem gestoßen, das ich alleine bis jetzt noch nicht lösen konnte. Ich hoffe daher dringendst um eure Hilfe und produktive, anregende Beiträge.

Problemstellung:
Schnittpunkt als D3DXVECTOR3 berechnen, bei dem die "Linie" der Kugel (bedingt durch Gravitation, Geschwindigkeit), die des Gegners (bedingt durch Geschwindigkeit) trifft.

Bekannte Werte:
float projectilSpeed = 2000 m/s //enthält die Geschwindigkeit des Projektils pro Sekunde
float gravitation = 9.81 m/s^2 //endhält die Erdanziehung
D3DXVECTOR3 targetPosition //enthält die Position des Ziels
D3DXVECTOR3 projectilePosition //enthält die Position des Projektils
D3DXVECTOR3 targetSpeed //enthält die Änderung der Position des Gegners pro Sekunde

Variablendefinition:
ProjectilePosition zum Zeitpunkt der Kollision = ProjectilePos_t
TargetPosition zum Zeitpunkt der Kollision = TargetPos_t
ProjectilePosition zum Zeitpunkt 0, jetzt = ProjectilePos_0
TargetPosition zum Zeitpunkt 0, jetzt = TargetPos_0
ZeitZumAufschlag = t
Aim-Winkel = theta

Ansatz:
Ich habe eine Formel gefunden, mit deren Hilfe sich der "Drop" (Abfall des Projektils anhand der Gravitation) berechnen lässt (Quelle Wikipedia):
float drop = 0.5f * gravity * t * t

Die Geschwindigkeit eines Projektils hat natürlich einen horizontalen und vertikalen Anteil und lässt sich wie folgt beschreiben (Quelle Wikipedia):
ProjectilVelocity.x = projectilSpeed * cos(theta)
ProjectilVelocity.y = projectilSpeed * sin(theta)

Also gilt für das Projektil (Quellle mein Kopf):
ProjectilePos_t.x = ProjectilePos_0.x + ProjectileSpeed * t
ProjectilePos_t.y = ProjectilePos_0.y + ProjectileSpeed * t + 0.5f * gravity * t * t
ProjectilePos_t.z = ProjectilePos_0.z + ProjectileSpeed * t

Das Ziel läuft angenommen mit einer Konstanten Geschwindigkeit. Anders gehts nicht.
Dann gilt (Quelle Wikipedia):
TargetPos_t = TargetPos_0 + TargetSpeed * D3DXVECTOR3(t, t, t)

So. Und ab hier weißt ich nicht wieter. Ich muss das ganze ja irgentwie so auflösen, das ich mit bekannten Werten die Geschwindigkeit herausfinde. Der einfchheit halber könnte man natürlich etwas schnelles nehmen wie:
float time = distanz / projectileSpeed
Aber das wäre nicht korrekt, weil das eine lineare "Flugbahn" Vorraussetzen würde, die es wohl nur bei einem Raketenwerfer geben würde :)

Ich hoffe ich habe das Problem detailliert erklärt. Wenn was fehlt, bitte melden! Manchmal setzt man als Autor ja Sachen vorraus, die einem selber ganz klar sind.

Gruß aus NRW,
Frank
 
Ich hab das Problem mal mit einem Bekannten näher erörtert. Ich denke das Hilft um das eigentliche Problem zu verstehen
(Post nach Erlaubnis des Chat Beteiligten anonymisiert dargestellt)

Die angepriesene Belohnung von 50usd bleibt natürlich für jeden bestehen (insofern das hier toleriert wird)

09:42:11 ReUnioN: hi
09:42:33 ReUnioN: du ich wollte mal fragen ob du dich ein wenig im vector zurecht findest..
09:44:24 Anonym1: ...? ^^
09:45:03 ReUnioN: http://www.tutorials.de/c-c/370821-treffpunkt-von-2-kurven-im-3-dimensionalen-raum.html#post1919432
09:45:05 ReUnioN:
09:48:29 Anonym1: hm ich guck mal rein
09:49:26 ReUnioN: danke
09:51:50 Anonym1: du willst jetzt mit der letzten formel die zeit die es für den flug braucht oder was?
09:51:55 Anonym1: is doch ne einfache wurfparabel...?
09:52:07 ReUnioN: ja, aber wie soll ich das machen?
09:52:20 ReUnioN: ich kenne ja die zeit nicht.. also nicht die position des gegners zu der zeit
09:52:26 ReUnioN: eine unbekannte zu viel^^
09:52:39 Anonym1: hm....?
09:52:44 Anonym1: was fehlt dir denn noch?
09:53:00 ReUnioN: angenommen der gegner würde sich nicht bewegen.. dann könnte ich berechnen, wie hoch ich zielen muss um den gegner zu treffen
09:53:09 Anonym1: willst du eine flugbahn die trifft oder wissen ob die flugbahn trifft?
09:53:43 ReUnioN: mit gegnerPosition.y += 0.5 * gravity * time * time
und vorher time = distance / speed
09:53:50 ReUnioN: aber jetzt bewegt sich der gegner..
09:54:07 ReUnioN: wie rechne ich dann die "richtige" zeit aus
09:54:16 ReUnioN: die ich dann in die obere formel einsetze?
09:54:27 Anonym1: die richtige zeit für was?
09:54:32 ReUnioN: bis der schuss ankommt
09:54:41 ReUnioN: das verändert sich ja wenn der gegner sich bewegt
09:54:41 Anonym1: aso ...
09:54:53 Anonym1: nja hast doch eigtl. zwei funktionenen die dir ne kurve beschreiben
09:54:55 Anonym1: setz die gleich
09:55:01 Anonym1: und guck ob sich alles auflöst ^^
09:55:02 ReUnioN: ich hab quasi 2 geraden (eine durch ballistik abfallend)..
09:55:21 ReUnioN: hab ich nicht hin bekommen
09:55:44 ReUnioN: ich hab ja nicht mal die distanz zum gegner
09:56:07 ReUnioN: weil ich nicht weiß wo ich hin zielen muss.. ich brauch die zeit um die position des gegners zur zeit des aufpralls zu berechnen
09:56:49 ReUnioN: kann ja nicht einfach die zum zeitpunkt 0 nehmen.. der gegner läuft ja.. und die kugel fliegt auch nicht "gerade" sondern halt nach ner funktion die die gravitation berücksichtigt
09:56:53 Anonym1: hm ... die zeit bis zu genau welchem ereignis?
09:57:07 Anonym1: bei der die kurve wieder 0 ist
09:57:12 ReUnioN: ok, ich erkläre das mal mehr ins detail..
09:57:19 Anonym1: weil wenner trifft sollte der abstand 0 sein
09:57:57 ReUnioN: ich hab einen gegner der sich bewegt.. position(t) = position(0) + speed * zeitBisZumAufschlag
09:59:26 Anonym1: jop ... kay pos(0) is aber ne konstante, oder?
10:00:05 ReUnioN: und ich habe eine ballistische linie..
position(t).y = position(0).y + sin(theta) * speed + 0.5 * gravity * zeitZumAufschlag * zeitZumAufschlag
10:00:57 ReUnioN: position(t).x = position(0).x + cos(theta) * speed
10:01:08 ReUnioN: x hat ja keien abhängigkeit zur gravitation
10:01:16 ReUnioN: und für z.. bin nicht sicher
10:01:36 ReUnioN: ist das dann
position(t).z = position(0).z + tan(theta) * speed? weiß nicht genau
10:01:41 Anonym1: warum sollte z eine haben...?
10:01:42 Anonym1: nein
10:01:51 ReUnioN: y ist ja nach oben..
10:01:57 Anonym1: jo x zur seite
10:01:59 Anonym1: acuh kla
10:02:07 ReUnioN: hehe
10:02:11 ReUnioN: naja
10:02:15 ReUnioN: ist ja quasi nach vorne
10:02:22 ReUnioN: also müsste ich x und z zusammen bringen
10:02:26 ReUnioN: irgnetwie
10:02:26 Anonym1: nja aber hast doch nicht viel mehr als ne variable t
10:02:36 ReUnioN: und nen winkel theta
10:02:49 ReUnioN: um dem speed richtung zu geben
10:03:09 ReUnioN: rechne mal durch.. da ist nicht viel was du berechnen kannst.. zumindest konnte ich es nicht
10:05:03 ReUnioN:

position(t).y = position(0).y + sin(theta) * speed + 0.5 * gravity * zeitZumAufschlag * zeitZumAufschlag

das macht ja noch sinn. aber wie beschreibe ich nun die "weite" nach vorne?
10:05:51 ReUnioN: naja, ganz viele fragezeichen die ich hab.. bin nicht sicher wie ich das lösen kann
10:07:19 Anonym1: aber der gegner bewegt sich nur auf x u. z, oder? ^^
10:10:15 ReUnioN: y auch
10:10:20 ReUnioN: da das terrain ja nicht gerade ist
10:10:45 ReUnioN: oder er springt irgentwo runter
10:10:54 Anonym1: oha ist die geschwindigkeit nen vector?
10:11:04 ReUnioN: vom gegner? ja
10:11:25 ReUnioN: vom projectil? nein.. das hängt ja vom abschusswinkel ab
10:11:38 Anonym1: joa und is kein vector...? doch
10:11:38 ReUnioN: speed * sin(pitch)
10:11:43 ReUnioN: speed * cos(yaw)
10:12:00 Anonym1: is dein y und speed*cos dein x vom vector, oder hab ich da grad was falsch? ^^
10:12:49 ReUnioN: gegner:
speed.x
speed.y
speed.z

projectil:
speed
10:13:24 Anonym1: nja okay aber du hast doch speed.x ist cos(theta) * speed
10:13:34 Anonym1: und speed.y = sin(theta) * speed
10:13:37 Anonym1: beim projectil
10:13:46 ReUnioN: ja
10:13:55 Anonym1: also ...?
10:14:06 ReUnioN: verstehe nicht worauf du hinaus willst
10:14:27 ReUnioN: abhängig vom abschusswinkel ändert sich berim projektil ja der speed nach vorn bzw nach oben
10:14:35 ReUnioN: deswegen die abhängigkeit vom winkel
10:14:45 ReUnioN:
10:15:47 ReUnioN: deswegen muss in die berechnung für y halt speed * sin(theta) bzw für vorwärts = speed * cos(theta) genommen werden
10:16:56 ReUnioN: wobei bei nem geraden schuss dann speed * sin(theta) = 0 ist weil y keinen speed erfährt.. bzw.. speed * cos(theta) = speed ist weil der ganze "schuss" nach vorne wirkt
10:16:58 ReUnioN:
10:17:28 ReUnioN: trotzdem ist der schuss nicht gerade, weil ja die gravitation noch einwirkt
10:17:34 ReUnioN: und die kugel "runter" zieht
10:17:57 ReUnioN: würde mann von nem 45° winkel schießen.. hätte man nach oben 1/2 speed wirkung
10:18:03 ReUnioN: und nach vorne 1/2 speed wirkung
10:18:05 ReUnioN: macht sinn?
10:22:14 ReUnioN: ziel des ganzen ist es dann, einen vector zu berechnen, auf den ich zielen muss.. und wenn ich dann einen schuss auslöse, wird die kugel genau den kopf des gegners treffen
10:22:29 ReUnioN: also quasi den zeitlich abhängigen schnittpunkt der kurven
10:22:37 Anonym1: hm nja du hast doch y0 + vy0*t - 0.5gt²
10:22:45 ReUnioN: jo
10:22:50 Anonym1: das is die formeil für y(t)
10:22:56 ReUnioN: jep, das ist richtig
10:23:00 Anonym1: also öhe in abhängigkeit der zeit
10:23:04 ReUnioN: genau
10:23:17 Anonym1: so und da sind praktisch nur konstanten drin
10:23:26 ReUnioN: nein, t ist ja unbekannt
10:23:45 ReUnioN: und vy auch
10:23:52 Anonym1: warum das?
10:23:53 ReUnioN: weil vy ja von theta abhängt
10:24:03 ReUnioN: und t von der zeit der flugbahn
10:24:17 ReUnioN: wie gesagt.. vy = sin(theta) * speedDerKugel
10:24:20 Anonym1: vy0 ist zwar von theata abhängig aber ändert sich nich wärend des fluges
10:24:26 ReUnioN: das stimmt
10:24:34 Anonym1: praktisch konstant
10:24:38 ReUnioN: ja^^
10:25:10 ReUnioN: dann bliebe noch die zeit als unbekannte größe
10:25:23 ReUnioN: ich weiß ja nicht wo ich den gegner schneiden werde
10:25:36 Anonym1: nja musst die y koordinate des gegners nehmena
10:25:39 ReUnioN: je nachdem wie weit er in der zeit läuft, ändert sich ja die zeit
10:25:42 Anonym1: also in abhängigkeit der zeit
10:25:53 Anonym1: und dann die ts versuchen rauszukürzen
10:26:00 ReUnioN: klar..
target.y = target_0.y + speed.y * time
10:26:47 ReUnioN: wie gesagt.. ich bekomm die berechnung nicht hin.
10:28:25 Anonym1: höö und warum? au warte nja gucken
10:28:51 ReUnioN: probier mal ne formel aufzustellen.. aus den sachen die wir so besprochen haben..
10:32:06 Anonym1: jo geht
10:32:11 Anonym1: und kommt was raus
10:32:16 Anonym1: wird zwar hässlich aber geht ^^
10:32:20 ReUnioN: hat bei mir nie geklappt..

hab ja quasi..

kurve gegner:
pos(t).x = pos(0).x + speed.x * time
pos(t).y = pos(0).y + speed.y * time
pos(t).z = pos(0).z + speed.z * time

kurve kugel:
pos(t).y = pos(0).y + sin(theta) * speed + 0.5 * gravity * time * time
pos(t).x und pos(t).z weiß ich gerade nicht.. aber theoretisch ist die "vorwärtsbewegung" durch pos(0) + cos(theta) * speed definiert
10:32:21 Anonym1: ob die nachher richtig ist .... ka
10:32:44 Anonym1: nja reicht ja acuh erstmal nur eine bewegung um dein t rauszubekommen
10:32:48 ReUnioN: und du musst ja bedenken das nicht nur y wichtig ist
10:32:53 ReUnioN: sondern auch x
10:32:57 Anonym1: doch zum berechnen erstmal auch
10:32:59 ReUnioN: weil der gegner sich seitlich bewegen kann
10:33:11 Anonym1: kannst es ja dann mit x ´überprüfen obs stimmt
10:33:17 ReUnioN: muss ja dann quasi "vorhalten"
10:33:23 ReUnioN: kk
10:33:25 Anonym1: aber sollte zum berechnen nicht nötig sein
10:33:37 ReUnioN: mal sehen was kommt
10:33:41 Anonym1: bekommst nachher halt normal 2 lösungen raus ... quadratische gleichung
10:33:48 ReUnioN: klar
10:33:50 Anonym1: ma soll ichs dir jetzt hier vorrechnen oder was? ^^
10:33:53 ReUnioN: eine liegt in der zeit zurück
10:34:01 ReUnioN: wäre cool, ich bekomm die gleichung nicht hin
10:34:08 ReUnioN: sodas ich die werte eintragen kann
10:34:26 ReUnioN: float projectilSpeed = 2000 m/s //enthält die Geschwindigkeit des Projektils pro Sekunde
float gravitation = 9.81 m/s^2 //endhält die Erdanziehung
D3DXVECTOR3 targetPosition //enthält die Position des Ziels
D3DXVECTOR3 projectilePosition //enthält die Position des Projektils
D3DXVECTOR3 targetSpeed //enthält die Änderung der Position des Gegners pro Sekund
10:34:38 ReUnioN: das ist bekannt.. dir wird immer was fehlen beim aufstellen der gleichung
10:34:41 ReUnioN: zumindest ging es mir so
10:35:04 ReUnioN: theta kennste nicht weil du die zeit nicht weißt.. und ohne theta kennst du die zeit nicht..
10:35:06 ReUnioN: verstehste..
10:35:15 Anonym1: warum kenn ich theta nicht?
10:35:28 Anonym1: theta bei der berechnung der endposition der anfangswinkel?
10:35:29 Anonym1: *ist
10:35:39 Anonym1: mit dem das ding geschossen wird. ...?
10:35:41 ReUnioN: jep
10:35:48 Anonym1: also kennsst de den doch?
10:35:56 ReUnioN: und man hat nen theta für pitch (links/rechts) und einen für yaw (oben/unten)
10:36:12 ReUnioN: den kennt man doch gerade nicht
10:36:28 ReUnioN: das will ich ja durch die endposition raus finden
10:36:34 ReUnioN: mit welchem "angles" ich aimen muss
10:36:36 ReUnioN: um zu treffen
10:36:39 Anonym1: maaa
10:36:40 Anonym1: kay
10:36:42 Anonym1: dann
10:37:05 ReUnioN: wird das ganze schon schwieriger
10:37:40 ReUnioN: aber macht sinn.. die KI soll wissen wohin sie zielen muss um den gegner in der zukunft zu treffen.. dann berechne ich pitch und yaw und feuer
10:38:02 ReUnioN: dann fliegt die kugel.. fliegt.. fliegt.. und irgentwann.. ist die kugelposition = der gegnerposition
10:38:08 ReUnioN: das ist das ziel
10:38:26 ReUnioN: weil der gegner dann umfällt x)
10:38:55 Anonym1:
10:39:16 Anonym1: hm nja kay mit reichweite bekannt ist es leicht aber reichweite is abhängig von t ... hm
10:39:28 ReUnioN: siehste
10:39:35 ReUnioN: sehr kompliziert glaub ich
10:39:41 ReUnioN: vllt gibts ne iterative möglichkeit oder so
10:39:46 ReUnioN: kp, darum frag ich^^
10:40:08 ReUnioN: hab nur realschul mahte.. alles andere hab ich mir selber beigebracht
10:40:12 ReUnioN: aus interesse
10:41:17 ReUnioN: mein lehrer hatte mal gesagt das cos(theta)^2 + cos(theta)^2 = 1 ist
10:41:22 ReUnioN: und das mir das helfen könnte
10:41:26 ReUnioN: aber kp, ich komm nicht weiter
10:41:47 ReUnioN: cos(theta)^2 + sin(theta)^2 = 1 meinte ich^^
10:43:01 Anonym1: nja kay phytagoras halt
10:43:51 ReUnioN: ich setz ne paypal belohnung von 50 dollar aus für den der das hin bekommt.. ich komm da echt nicht weiter, wills aber wissen
10:44:35 Anonym1: hm guck dir mal von giancoli physik an, da steht die lösung mein ich drin ...
10:45:23 ReUnioN: hab das buch nicht
10:45:37 ReUnioN: auch noch nie von dem gehört^^
10:49:22 Anonym1: mist muss los freundin wartet ... warte mal ob jemand bei tutorials.de antwortet sond guck ichs mir morgen früh nochmla an, kay?
10:49:32 ReUnioN: danke
10:49:38 ReUnioN: kann ich unsere konvo da posten?
10:49:47 ReUnioN: dass jeder die genauere erklärung des problems kennt
10:50:08 Anonym1: kannst du wenne meine nummer da rausmachst
10:50:15 ReUnioN: mach ich
 
Zuletzt bearbeitet:
Hi,

ich habe mir jetzt mal deine Beschreibung durchgelesen, den Chat habe ich überflogen, da ich dort keine nützlichen Informationen auf den ersten Blick finden konnte. Wenn du einen Schnittpunkt zwischen zwei Kurven benötigst, dann hast du ein Problem aus der linearen Algebra. Selbstverständlich musst du wissen, wie deine Kurve berechnet wird. Und zwar formal und nicht Iterativ, wie du es oben beschreibst.

Wenn du eine formale Beschreibung hast, kannst du die Formeln gleichsetzen, denn ein Treffpunkt = Schnittpunkt = die Funktionswerte von x,y,z beider Funktionen haben die gleichen Werte. Alles weitere ist dann ein ganz "normales" Lösen einer Matrix mit dem Gaußverfahren.
 
Das verstehe ich nicht ganz. Wenn ich mal so kombiniere komme ich auf folgende definition der Kurve.

Projektil:
Projektil_t.y = Projektil_0.y + sin(pitch) * Projektil_Speed + 0.5 * gravity * time * time
Projektil_t.x =
Projektil_t.z =
bin nicht sicher wie ich x und z berechnen muss. Hängt ja davon ab wie ich im Raum stehe nehme ich an.. Also vom Forward vector aus der Projektilmatrix oder?
Bzw. wie ich den "Anteil" in diese Richtungen ausrechne.


Gegner:
Gegner_t.x = Gegner_0.x + Speed.x * time
Gegner_t.y = Gegner_0.y + Speed.x * time
Gegner_t.z = Gegner_0.z + Speed.x * time


Angenommen ich hätte die Kurven jetzt definiert. (Fehlt ja nur der Teil bei Projektil.x und z), dann könnte ich das noch nicht wirklich Gleichsetzen oder?

Klar, wenn time dann gilt Gegnerposition = Projektilposition. Trotzdem kommt man nicht weiter. Yaw und Pitch sind abhängig von der Zeit, und die Zeit abhängig von Yaw und Pitch.. Vielleicht blicke ich auch einfach nicht durch.
 
Das Problem ist, dass du die Zeit wie eine Variable betrachtest. Die Zeit ist aber eben keine Variable, sondern eine Konstante. Wenn du die Zeit wirklich als Variable betrachten möchtest, dann ist es kein Schnittpunkt zwischen zwei Funktionen mehr. Du benötigst dann einen Abstand zwischen den Kurven zu einem Zeitpunkt (ist ebenfalls eine Funktion), von der du dann den Minimalwert suchst. Das ist aber etwas aufwändig.

Ich habe momentan so ein bisschen das Gefühl, dass du nicht so ganz weißt, was du machst. Deshalb möchte ich dir die Situation mal etwas aus meiner Sicht erläutern.

Die erste Frage überhaupt ist, wo die Spielfigur sich nach einer bestimmten (festgesetzten) Zeit befinden wird. Da die sich linear verhält, lässt sich diese Position ganz einfach berechnen. Die Zeit hast du und die künftige Position als x,y,z Vektor. Damit kannst du auch lösen, wohin zu zielen musst, um die Drift des Projektils auszugleichen.
 
Zurück