Zielwinkel errechnen (mathematisches Problem)
Übersicht

proggerkindBetreff: Zielwinkel errechnen (mathematisches Problem) |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hi Leute,
folgendes Problem: ich bin gerade dabei, ein kleines 2D-Weltraumspielchen zu programmieren und hänge an den Bots. Für diese soll unter Berücksichtigung ihrer Bewegungen, der Bewegung des Ziels (beides linear) und der Schussgeschwindigkeit der richtige Zielwinkel errechnet werden. Wäre dankbar wenn mir jemand eine Funktion schreiben könnte, die den richtigen Zielwinkel zurückgibt. ![]() PS: Die Koordinaten sollten natürlich auch berücksichtigt werden ![]() |
||
da_poller |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
vielleicht wäe es besser wenn du das selber versuchst und wenn du code probleme hast postest du den hier und wir versuchen zu helfen..
ansonsten gehört sowas eher in den stellenmarkt. |
||
ke^kx |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Als kleiner Denkanstoss: Guck dir mal Geraden an... und Vektoren. Oder machs einfach geometrisch, du brauchst eigentlich nichts mehr als sin(, cos, tan) und dreiecksgesetze. | ||
http://i3u8.blogspot.com
Asus Striker II Intel Core2Quad Q9300 @ 2,5 GHz (aber nur zwei Kerne aktiv aufgrund der Instabilität -.-) Geforce 9800 GTX 2GB RAM |
proggerkind |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Natürlich habe ich es schon selber versucht, schließlich geht es mir nicht darum um jeden Preis ein Spiel fertigzustellen, sondern um das Programmieren selbst.
Selbstverständlich habe ich auch schon mit Geraden, Vektoren und Dreieckssätzen herumexperimentiert, jedoch bin ich dabei auf Probleme gestoßen die meine mathematischen Kenntnisse bei weitem übertreffen (ich bin in der 9. Klasse, das heißt, dass ich eigentlich noch gar nicht wissen dürfte was Trigonometrie überhaupt ist). Ich habe zunächst versucht, mithilfe von Cosinus und Sinus eines unbekannten Winkels die Vektoren eines Objekts so zu verändern, dass die Funktionen für die X- und Y-Koordinatendifferenz der beiden Objekte sich auf der Y-Achse schneiden. Danach wollte ich die Gleichung nach diesem Winkel auflösen... Allerdings müsst ihr verstehen, dass ich - trotz zahlreicher Versuche - bei Additionstheoremen, inversen Tangensfunktionen usw. mit meinem Latein am Ende bin. Ich versuche hier nicht mir ein Spiel von anderen zusammenprogrammieren zu lassen, ich habe in den 15 Monaten Entwicklungszeit bisher alles selbst gemacht. An dieser Stelle komme ich allerdings nicht weiter und ich brauche die beschriebene Funktion unbedingt, um endlich weiterprogrammieren zu können. |
||
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
2 Objekte, Ziel und Schuss, beide bewegen sich auf einer Geraden. Du musst den Schnittpunkt der beiden Geraden berechnen, dann kannst du mittels Atan2![]() Such dazu mal im Codearchiv unter "Schnittpunkt zweier Strecken berechnen"oder so... |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
![]() |
HolzchopfMeisterpacker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das Problem ist ja, dass er den Winkel der Schussgerade nicht kennt :> und ergo so auch keinen genauen Schnittpunkt bestimmen kann =/
Ich setz mich nachher kurz mal dahinter und mach n paar Skizzen, ich denke, mit ein paar Funktionen sollte das machbar sein. Ich hoffs zumindest... Allerdings kann ich schon jetzt sagen, dass es ziemlich kompliziert wird, da ja ein Gegner einem langsamen Geschoss entfliehen kann ( = keine Lösung) oder es kann sein, dass es zwei Möglichkeiten gibt... |
||
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BY ♫ BinaryBorn - Yogurt ♫ (31.10.2018) Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm |
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Man kann immer aus Koordinaten und Geschwindigkeit die Bewegungsrichtung (=Winkel) des Objekts berechnen, bzw. die lineare Funktion aus den Zwei Koordinaten berechnen.
Bisschen herumrechnerei aber nicht gar so schwer. |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
![]() |
HolzchopfMeisterpacker |
![]() Antworten mit Zitat ![]() |
---|---|---|
*Erfolg* \o/
Code: [AUSKLAPPEN] Graphics 800,600,0,2
SetBuffer BackBuffer() Global TIMER = CreateTimer(60) ; (Start)position des Geschosses, resp des Schützens Local P#[2], P0[2] P0[0] = 200: P[0] = P0[0] P0[1] = 200: P[1] = P0[1] ; Geschwindigkeit des Geschosses Local vP# = 5 ; Winkel des Geschosses Local wP# ; (Start)position des Gegners Local G#[2], G0[2] G0[0] = 400: G[0] = G0[0] G0[1] = 500: G[1] = G0[1] ; Geschwindigkeit des Gegners Local vG# ; Winkel des Gegners Local wG# ; Ob ein Schuss unterwegs ist Local active = False Local mh While Not KeyDown(1) Cls mh = MouseHit(1) ; Schuss auslösen (Maustaste) If mh=1 And active=False ; Bewegung des Gegners richtung Maus Local dx = MouseX() -G0[0], dy = MouseY() -G0[1] wG = ATan2( dy, dx ) vG = Sqr( dx *dx +dy *dy ) *0.01 ; Schusswinkel berechnen wP = Schusswinkel( P0, G0, vP, vG, wG ) ; *voodoo* aktivieren If wP > -1 Then active = True ; Zurücksetzen ElseIf mh=1 And active=True ; Beides auf Startpunkt setzen P[0] = P0[0] P[1] = P0[1] G[0] = G0[0] G[1] = G0[1] ; *voodoo* deaktivieren active = False EndIf If active ; Schuss bewegen P[0] = P[0] +Cos(wP) *vP P[1] = P[1] +Sin(wP) *vP ; Gegner bewegen G[0] = G[0] +Cos(wG) *vG G[1] = G[1] +Sin(wG) *vG EndIf Oval P[0]-1, P[1]-1, 3,3 Oval G[0]-3, G[1]-3, 7,7 Flip 0 WaitTimer( TIMER ) Wend End Function Schusswinkel#( PunktA[2], PunktB[2], GeschwA#, GeschwB#, WinkelB# ) ; Komponenten berechnen Local Sx# = PunktB[0] -PunktA[0] Local Sy# = PunktB[1] -PunktA[1] Local Vx# = Cos( WinkelB ) *GeschwB Local Vy# = Sin( WinkelB ) *GeschwB ; Koeffizienten für die Quadr. Gleichung Local a# = Vx *Vx +Vy *Vy -GeschwA *GeschwA Local b# = 2 *Sx *Vx + 2 *Sy *Vy Local c# = Sx *Sx +Sy *Sy ; Diskriminante Local D# = b *b -4 *a *c ; Wenn keine Lösung existiert, -1 zurückgeben If D < 0 Return -1 ; Zeitpunkte berechnen Local t1# = ( -b +Sqr(D) ) /( 2*a ) Local t2# = ( -b -Sqr(D) ) /( 2*a ) ; Zeitpunkt negativ -> keine Lösung If t1 < 0 And t2 < 0 Return -1 ; günstigeren Zeitpunkt wählen Local t# = t1 If t2 > 0 And t2 < t1 t = t2 ElseIf t1 < 0 t = t2 EndIf ; Koordinaten des Treffpunkts bez. Punkt A Local x# = Sx +Vx *t Local y# = Sy +Vy *t ; Winkel zurückgeben Return ( ATan2( y#, x# ) +360 ) Mod 360 End Function Hintergrund /Lösung(sansatz): 1. Ich hab zwei Funktionen gemacht, eine für die Distanz Geschoss-Schütze (lediglich y1(t) = v*t) und eine für die Distanz Schütze-Ziel ( y2(t) = |Zo + u*t - Po|, Zo = Startposition des Ziels, Po = Position des Schützens, u = Geschwindigkeit des Ziels ) 2. Die Schnittpunkte dieser Funktionen geben an, wann eine Kollision stattfinden kann. Es kann auch sein, dass keine Lösung existiert. 3. Die daraus entstehende quadratische Gleichung wird umgeformt und 4. gelöst 5. Die Lösung (der Zeitpunkt) wird in die Bewegung des Ziels eingesetzt und schon hat man die Koordinaten, wo Schuss und Gegner sich treffen (/me zahlt n Batzen in die Wortwitzkasse) 6. Aus den Koordinaten wird der Winkel berechnet. Die Funktion oben gibt einen Winkel im Bereich 0° -360° oder -1, wenn keine Lösung existiert, zurück. Ich habe sie bereits so optimiert, dass sie immer die kürzere Zeitspanne einsetzt. Viel Spass damit! mfG |
||
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BY ♫ BinaryBorn - Yogurt ♫ (31.10.2018) Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm |
![]() |
mpmxyzBetreff: Tolles Teil! |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nicht schlecht...
Ich hatte mir auch mal darüber Gedanken gemacht, habe es aber erst einmal verworfen, da ich nicht so schnell auf eine Lösung kam... Es gibt aber noch Optimierungsmöglichkeiten: Denn: 1. Sin(X)^2+Cos(X)^2=1 2. Die Größe eines Arrays fängt bei 0 an. Code: [AUSKLAPPEN] Function Schusswinkel#( PunktA[1], PunktB[1], GeschwA#, GeschwB#, WinkelB# )
; Komponenten berechnen Local Sx# = PunktB[0] -PunktA[0] Local Sy# = PunktB[1] -PunktA[1] Local Vx# = Cos( WinkelB ) *GeschwB Local Vy# = Sin( WinkelB ) *GeschwB ; Koeffizienten für die Quadr. Gleichung Local a# = GeschwB * GeschwB -GeschwA *GeschwA Local b# = 2 *Sx *Vx + 2 *Sy *Vy Local c# = Sx *Sx +Sy *Sy ; Diskriminante Local D# = b *b -4 *a *c ; Wenn keine Lösung existiert, -1 zurückgeben If D < 0 Then Return -1 ; Zeitpunkte berechnen Local t1# = ( -b +Sqr(D) ) /( 2*a ) Local t2# = ( -b -Sqr(D) ) /( 2*a ) ; Zeitpunkt negativ -> keine Lösung If t1 < 0 And t2 < 0 Then Return -1 ; günstigeren Zeitpunkt wählen Local t# = t1 If t2 > 0 And t2 < t1 t = t2 ElseIf t1 < 0 t = t2 EndIf ; Koordinaten des Treffpunkts bez. Punkt A Local x# = Sx +Vx *t Local y# = Sy +Vy *t ; Winkel zurückgeben Return ( ATan2( y#, x# ) +360 ) Mod 360 End Function mfG mpmxyz P.S.: Denke daran, die anderen Arrays auch zu ändern! |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
![]() |
HolzchopfMeisterpacker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mist, dass mit dem sin² +cos² ist mir glatt durch die Lappen gegangen ![]() Und wegen den Arrays: Ich vergess immer wieder, dass in BB beim Initialisieren ja ein Element mehr erstellt wird, als angegeben. In BMax ist's halt anders und ich arbeite in letzter Zeit fast nur noch mit BMax... Naja die Funktion wäre bestimmt noch an anderen Stellen optimierbar... Aber s war halt schon spät gestern und irgendwann wurde ich dann doch ein bissl sehr müde. mfG |
||
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BY ♫ BinaryBorn - Yogurt ♫ (31.10.2018) Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm |
![]() |
mpmxyz |
![]() Antworten mit Zitat ![]() |
---|---|---|
Moin moin,
ich habe mich jetzt mal an meinen Lösungsansatz gesetzt: Code: [AUSKLAPPEN] Graphics 800,600,0,2
SetBuffer BackBuffer() Global TIMER = CreateTimer(60) ; (Start)position des Geschosses, resp des Schützens Local P#[1], P0[1] P0[0] = 200: P[0] = P0[0] P0[1] = 200: P[1] = P0[1] ; Geschwindigkeit des Geschosses Local vP# = 5 ; Winkel des Geschosses Local wP# ; (Start)position des Gegners Local G#[1], G0[1] G0[0] = 400: G[0] = G0[0] G0[1] = 500: G[1] = G0[1] ; Geschwindigkeit des Gegners Local vG# ; Winkel des Gegners Local wG# ; Ob ein Schuss unterwegs ist Local active = False Local mh While Not KeyDown(1) Cls mh = MouseHit(1) ; Schuss auslösen (Maustaste) If mh=1 And active=False ; Bewegung des Gegners richtung Maus Local dx = MouseX() -G0[0], dy = MouseY() -G0[1] wG = ATan2( dx,-dy ) vG = Sqr( dx *dx +dy *dy ) *0.01 ; Schusswinkel berechnen wP = BesteRichtung( P[0], P[1], 0, 0,G0[0] ,G0[1],+Sin(wG)*vG,-Cos(wG) *vG,vP ) ; *voodoo* aktivieren If wP > -1 Then active = True ; Zurücksetzen ElseIf (mh=1 Or Sqr((P[0]-G[0])^2+(P[1]-G[1])^2)<5) And active=True ; Beides auf Startpunkt setzen P[0] = P0[0] P[1] = P0[1] G[0] = G0[0] G[1] = G0[1] ; *voodoo* deaktivieren active = False EndIf If active ; Schuss bewegen P[0] = P[0] +Sin(wP) *vP+0 P[1] = P[1] -Cos(wP) *vP+0 ; Gegner bewegen G[0] = G[0] +Sin(wG) *vG G[1] = G[1] -Cos(wG) *vG EndIf Oval P[0]-1, P[1]-1, 3,3 Oval G[0]-3, G[1]-3, 7,7 Flip 1 WaitTimer( TIMER ) Wend End Function BesteRichtung#(VonX#,VonY#,VonXs#,VonYs#,ZuX#,ZuY#,ZuXs#,ZuYs#,Geschwindigkeit#) Local RelXs#=VonXs-ZuXs ;Geschwingkeitsvektor relativ zum Ziel Local RelYs#=VonYs-ZuYs ; ZuX= ZuX -VonX ;Zu ist jetzt der Sollvektor ZuY= ZuY -VonY ;Vom Schützen zum Ziel Local ZuSpd#=ZuX*ZuX+ZuY*ZuY ;Normalisieren des Vektors ZuSpd#=Sqr(ZuSpd#) Local DX#=ZuX/ZuSpd Local DY#=ZuY/ZuSpd VonXs#=RelXs*DY#-RelYs*DX# ;Der 2D-Raum wird so gedreht, dass der Sollvektor im BB-Koordinatensystem nach unten zeigt. VonYs#=RelYs*DY#+RelXs*DX# ;"Von" ist jetzt der gedrehte relative Geschwindigkeitsvektor. ;+Y ist in Sollrichtung If Geschwindigkeit#*Geschwindigkeit#<VonXs#*VonXs# Then Return -1 ;Ein zu großer Geschwindigkeitunterschied lässt sich nicht ausgleichen. Local SollL#=VonYs#+Sqr(Geschwindigkeit#*Geschwindigkeit#-VonXs*VonXs) ;Multipliziert mit dem Sollvektor gibt es die relative Geschossgeschwindigkeit an. ;Zeit=ZuSpd#/SollL# If SollL#<0 Then Return -1 Local ErgX#=-RelXs#+SollL#*DX# ;Vektor mit der Schussrichtung Local ErgY#=-RelYs#+SollL#*DY# Return (360+ATan2(ErgX,-ErgY))Mod 360 End Function Wenn die "Bälle" kollidieren, dann wird im Beispiel alles zurückgesetzt. Prinzip: Zuerst drehe ich den 2D-"Raum" so, dass das Ziel in BB unten und der Schütze oben auf (0|0) wäre. Dann bestimme ich den in BB unteren Punkt, an dem sich der Kreis mit dem Radius der Schussgeschwindigkeit und die Verbindungslinie zwischen dem Schützen und Zielpunkt schneiden. Die Schussrichtung geht dann von der Schützenposition plus seiner momentanen Geschwindigkeit bis zum eben bestimmten Punkt; dieser Vektor hat übrigens die Länge der Schussgeschwindigkeit. Achtung: Bei mir zeigt der Winkel 0 nach oben und geht dann im Uhrzeigersinn weiter! mfG mpmxyz Edit: Man konnte vorher beim Code das Ziel dem Schützen ganz schnell entgegenschicken und es wurde die Lösung nicht angegeben. Angeblich sei das ganze dann laut der alten Funktion unmöglich. Dieser Fehler ist jetzt behoben. |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
proggerkindBetreff: Danke |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
ok hab's jetzt implementiert, funktioniert soweit.
Danke für Eure Bemühungen! ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group