Kürzeste Drehrichtung um von Winkel A zu Winkel B zu kommen
Übersicht BlitzBasic Allgemein
DCSieger des B2D Retro Wettbewerb / Aug 04Betreff: Kürzeste Drehrichtung um von Winkel A zu Winkel B zu kommen |
Do, Dez 23, 2004 15:47 Antworten mit Zitat |
|
---|---|---|
Mein Problem klingt eigentlich ganz simpel aber komme auf keine Lösung! Wirrer Winkelmist!
Ich habe 2 verschiedene Winkel. Sozusagen einen IST-Winkel und einen SOLL-Winkel. Der IST-Winkel soll sich schrittweise zum SOLL-Winkel drehen bis er mit ihm übereinstimmt. Allerdings stets über den kürzesten Weg. Aber wie finde ich raus, ob ich nun nach Links oder Rechts drehen, sprich den Winkel erhhöhen oder senken muss um den kürzesten "Drehweg" zu erhalten? Praktisches Beispiel falls das jetzt unverständlich war: Eine um 360° drehbare Überwachungskamera, die sich auf kürzestem Weg von der aktuellen Drehung zu einem beliebigen Zielobjekt drehen können soll. |
||
Core i5 4670K | 4 x 3,40 GHZ | 16 GB Ram | GeForce GTX 960 | HTC Vive | Win 10 Pro
www.UnrealSoftware.de | www.StrandedOnline.de | www.CS2D.com | www.CarnageContest.com | www.Stranded3.com |
Edlothiol |
Do, Dez 23, 2004 15:51 Antworten mit Zitat |
|
---|---|---|
Code: [AUSKLAPPEN] Function CompareAngles#(a#,b#)
Je nachdem ob die Funktion einen Wert > oder < 0 ergibt, den Winkel erhöhen oder verringern. Die beiden Ifs sind für sowas wie a = 0 b = 359
if (b - a) < -180 then b = b + 360 if (b - a) > 180 then a = a + 360 return b - a End Function Die Winkel müssen natürlich >0 und <360 sein. |
||
walskiEhemaliger Admin |
Do, Dez 23, 2004 16:46 Antworten mit Zitat |
|
---|---|---|
Edlothiol Lösung ist falsch, wenn ich die mal mit a = 0 und b = 270 durchgeh kommt dabei folgendes raus:
b - a = -270 also b - a < -180 also b = b +360 = 630 b - a = 630 also b - a > 180 also a = a +360 = 360 b - a = 270 Das ist zwar richtig für ne Rechtsdrehung aber eben ist es nicht der kürzeste Weg, der wäre eben 90 Grad Linksdrehung. Hier mein Vorschlag: Code: [AUSKLAPPEN] Function approachAngle( AngleA# ,AngleB# ) ; AngleA -> smaller Angle ; AngleB -> bigger Angle If AngleB = AngleA Return 0 AngleA = AngleA Mod 360 AngleB = AngleB Mod 360 While AngleA < 0 AngleA = AngleA + 360 Wend While AngleB < 0 AngleB = AngleB + 360 Wend Return -1 + ( 2 * ( ( ( AngleB - AngleA ) < ( 360.0 - ( AngleB - AngleA ) ) ) And ( Not ( AngleB < AngleA And ( ( AngleA - AngleB ) < ( 360.0 - ( AngleA - AngleB ) ) ) ) ) ) ) End Function walski [EDIT] Achja, der Rückgabewert ist eben -1 bei ner Linksdrehung und 1 bei ner Rechtsdrehung Hier eingebaut in Rallimenscode: Code: [AUSKLAPPEN] Function approachAngle( AngleA# ,AngleB# ) ; AngleA -> smaller Angle ; AngleB -> bigger Angle If AngleB = AngleA Return 0 AngleA = AngleA Mod 360 AngleB = AngleB Mod 360 While AngleA < 0 AngleA = AngleA + 360 Wend While AngleB < 0 AngleB = AngleB + 360 Wend Return -1 + ( 2 * ( ( ( AngleB - AngleA ) < ( 360.0 - ( AngleB - AngleA ) ) ) And ( Not ( AngleB < AngleA And ( ( AngleA - AngleB ) < ( 360.0 - ( AngleA - AngleB ) ) ) ) ) ) ) End Function Graphics 800,600,16,2 SetBuffer BackBuffer() Dim Panzer (360) ;PanzerGrafik_berechnen > 360 Einzelbilder < Rect 9,0,2,20 Rect 0,10,20,20,1 Flip Panzer(0) = CreateImage (20,30) GrabImage Panzer(0),0,0 MidHandle Panzer(0) For z= 1 To 359 panzer(z) = CopyImage (Panzer(0)) RotateImage panzer(z),z MidHandle Panzer(z) Text 500,500," Berechne Panzer : "+z Flip Cls Next x= 400: y= 30 ; damit der zielpunkt zu sehen ist Repeat If MouseDown(1) Then x= MouseX () Y= MouseY () ;Winkel bezieht sich auf den Panzer winkel = Objekt_richtung_grad(x,y ,400 ,300) End If ;kürzeren Weg suchen posPanzer = posPanzer + approachAngle(posPanzer,Winkel) posPanzer = (posPanzer+360) Mod 360 ; < 0 oder >359 Oval x-5,y-5,10,10,1 ;Klickpunkt malen DrawBlock Panzer(posPanzer),400,300;Panzer malen Text 100,30, posPanzer + " Panzer" Text 100,60, winkel + " Grad" Flip Cls Until KeyHit (1) End Function Objekt_richtung_grad(Zielpunkt_X,Zielpunkt_Y,Ausgangspunkt_X,Ausgangspunkt_Y ) grad =ATan2(Zielpunkt_Y -Ausgangspunkt_Y, Zielpunkt_X -Ausgangspunkt_X)+90 grad = (grad+360) Mod 360 Return grad End Function [/EDIT] |
||
buh! |
- Zuletzt bearbeitet von walski am Fr, Dez 24, 2004 13:50, insgesamt 2-mal bearbeitet
RallimenSieger des 30-EUR-Wettbewerbs |
Do, Dez 23, 2004 18:26 Antworten mit Zitat |
|
---|---|---|
Hallo, hab da noch so ein BeispielCode den ich mal hier gepostet habe !Code: [AUSKLAPPEN] Graphics 800,600,16,2
SetBuffer BackBuffer() Dim Panzer (360) ;PanzerGrafik_berechnen > 360 Einzelbilder < Rect 9,0,2,20 Rect 0,10,20,20,1 Flip Panzer(0) = CreateImage (20,30) GrabImage Panzer(0),0,0 MidHandle Panzer(0) For z= 1 To 359 panzer(z) = CopyImage (Panzer(0)) RotateImage panzer(z),z MidHandle Panzer(z) Text 500,500," Berechne Panzer : "+z Flip Cls Next x= 400: y= 30 ; damit der zielpunkt zu sehen ist Repeat If MouseDown(1) Then x= MouseX () Y= MouseY () ;Winkel bezieht sich auf den Panzer winkel = Objekt_richtung_grad(x,y ,400 ,300) End If ;kürzeren Weg suchen If posPanzer > Winkel And posPanzer -180 < Winkel Then posPanzer = posPanzer -1 If posPanzer > Winkel And posPanzer -180 > Winkel Then posPanzer = posPanzer +1 If posPanzer < Winkel And posPanzer +180 < Winkel Then posPanzer = posPanzer -1 If posPanzer < Winkel And posPanzer +180 > Winkel Then posPanzer = posPanzer +1 If posPanzer = Winkel -180 Or posPanzer -180 = Winkel Then posPanzer = posPanzer +1 posPanzer = (posPanzer+360) Mod 360 ; < 0 oder >359 Oval x-5,y-5,10,10,1 ;Klickpunkt malen DrawBlock Panzer(posPanzer),400,300;Panzer malen Text 100,30, posPanzer + " Panzer" Text 100,60, winkel + " Grad" Flip Cls Until KeyHit (1) End Function Objekt_richtung_grad(Zielpunkt_X,Zielpunkt_Y,Ausgangspunkt_X,Ausgangspunkt_Y ) grad =ATan2(Zielpunkt_Y -Ausgangspunkt_Y, Zielpunkt_X -Ausgangspunkt_X)+90 grad = (grad+360) Mod 360 Return grad End Function sollte verständlich sein hier noch eine gekürzte Version !Code: [AUSKLAPPEN] If posPanzer > Winkel Then
If posPanzer -180 < Winkel Then posPanzer = posPanzer -1 If posPanzer -180 => Winkel Then posPanzer = posPanzer +1 Else If posPanzer +180 < Winkel Then posPanzer = posPanzer -1 If posPanzer +180 => Winkel Then posPanzer = posPanzer +1 End If posPanzer = (posPanzer+360) Mod 360 ; < 0 oder >359 |
||
[BB2D | BB3D | BB+]
|
- Zuletzt bearbeitet von Rallimen am Do, Dez 23, 2004 18:47, insgesamt einmal bearbeitet
walskiEhemaliger Admin |
Do, Dez 23, 2004 18:37 Antworten mit Zitat |
|
---|---|---|
Ok, ich glaub ich stänkere grad etwas rum, aber ich finde die 5 Ifs oder wieviele das sind für diese Lösung nicht gerade sehr schön.
Aber das ist ja zum Glück Geschmackssache Bitte nicht zu böse nehmen oder denken ich sei ein dreckiger Egoman. walski |
||
buh! |
RallimenSieger des 30-EUR-Wettbewerbs |
Do, Dez 23, 2004 19:05 Antworten mit Zitat |
|
---|---|---|
@Walski:
nicht böse gemeint, aber bei meiner etwas gekürzten Version werden max 3 If´s abgearbeitet Zitat: Aber das ist ja zum Glück Geschmackssache
Mein ich auch so....
|
||
[BB2D | BB3D | BB+]
|
Edlothiol |
Do, Dez 23, 2004 19:08 Antworten mit Zitat |
|
---|---|---|
Walski, du bist meinen Code falsch durchgegangen: b-a ist nicht -270, sondern 270. Deshalb kommt am Ende ein Wert <0 raus, und es ist doch richtig... | ||
walskiEhemaliger Admin |
Do, Dez 23, 2004 19:36 Antworten mit Zitat |
|
---|---|---|
Du hast recht, ich hab dich wirklich verunglimpft...
Tut mir leid. Ich habe meinen Code auch nocheinmal verbessert, er kommt jetzt ohne die If-Klauseln zur Abfrage aus, damit besteht die eigentliche Prüfung jetzt nurnoch aus einer Zeile. walski |
||
buh! |
Travis |
Do, Dez 23, 2004 23:41 Antworten mit Zitat |
|
---|---|---|
@ walski
Angenommen ein Spieler schiesst zielsuchende Waffen ab. Ist DirectionToObject denn der Winkel vom Spieler zum Ziel. Ist DirectionOfCam dann der Winkel des Spielers? Ich schlage mich für mein Projekt auch mit diesem Problem rum. Meine bisherige Lösung ist der von Rallimen ähnlich. Ist natürlich auch nicht sehr elegant. Code: [AUSKLAPPEN] ; Rakete auf Ziel ausrichten winkel = (450 - ATan2((zx - r\x), (zy - r\y))) Mod 360 If Abs(s\winkel-winkel) < 180 Then If r\winkel < winkel Then r\winkel = r\winkel + 1 If r\winkel > winkel Then r\winkel = r\winkel - 1 Else If r\winkel < winkel Then r\winkel = r\winkel - 1 If r\winkel > winkel Then r\winkel = r\winkel + 1 EndIf Dabei ist Winkel der Winkel vom Spieler zum Ziel und s\Winkel der Winkel des Spielers. Weil das aber ziemlich umständlich ist, würde ich deine Methode mal probieren wollen. Dazu müsste ich aber wissen, was deine zwei Variablen genau bedeuten. EDIT: Und gehört der obere Code auch noch zu der Lösung. Dann wäre das ja auch nicht unbedingt der kürzeste Weg. ich verstehe deinen Lösungsweg leider total nicht. |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
walskiEhemaliger Admin |
Fr, Dez 24, 2004 0:26 Antworten mit Zitat |
|
---|---|---|
Meine obere Lösung ist teilweise falsch, ich habe gerade keine Zeit werde aber später noch dazu Stellung nehmen
Es gibt noch ein Problem mit dem vertauschen der Winkel, das macht natrlürlich alles etwas kaputt, ich verbessere das. Generell sind halt beides Winkel. Das eine der "Ist-Winkel" und das andere der "Soll-Winkel". Alles klar? walski |
||
buh! |
RallimenSieger des 30-EUR-Wettbewerbs |
Fr, Dez 24, 2004 0:44 Antworten mit Zitat |
|
---|---|---|
habs nochmal gekürzt und in eine Function gepackt!
Code: [AUSKLAPPEN] Function DrehAufZiel (pospanzer,winkel)
If posPanzer > Winkel Then If posPanzer -180 < Winkel Then Return -1 Else If posPanzer +180 < Winkel Then Return -1 End If Return 1 End Function Code: [AUSKLAPPEN] posPanzer =(posPanzer + drehAufZiel(pospanzer,winkel)+360)Mod 360
|
||
[BB2D | BB3D | BB+]
|
DCSieger des B2D Retro Wettbewerb / Aug 04 |
Fr, Dez 24, 2004 11:47 Antworten mit Zitat |
|
---|---|---|
Danke an alle für die Hilfe. Jetzt funktionierts | ||
Core i5 4670K | 4 x 3,40 GHZ | 16 GB Ram | GeForce GTX 960 | HTC Vive | Win 10 Pro
www.UnrealSoftware.de | www.StrandedOnline.de | www.CS2D.com | www.CarnageContest.com | www.Stranded3.com |
Ctuchik |
Fr, Dez 24, 2004 13:31 Antworten mit Zitat |
|
---|---|---|
bei mir siehts so aus, sollte auch funktionieren:
Code: [AUSKLAPPEN] aenderung#=zielwinkel-startwinkel If aenderung# > 180 Or aenderung# < -180 aenderung# = (360 - Abs(aenderung#)) * Sgn(aenderung#) * -1 End If Frage: Ist das mit Sgn() und Abs() spürbar langsamer als zum Beispiel der Code von Edlothiol? |
||
Zu den Nebenwirkungen gehören trockener Mund, Übelkeit, Erbrechen, Harnstau, schmerzhafter rektaler Juckreiz, Halluzinationen, Demenz, Psychose, Koma, Tod und Mundgeruch!
Magie eignet sich nicht für alle! Fraget euren Arzt oder Apotheker! |
walskiEhemaliger Admin |
Fr, Dez 24, 2004 13:52 Antworten mit Zitat |
|
---|---|---|
Ich habe meinen Code oben jetzt mal überarbeitet...
Er funktioniert jetzt zwar, ich halt ihn aber nicht mehr für ne gute Lösung Auch wenn er ahrscheinlich nicht langsam ist, ist er doch etwas... unübersichtlich. Die ganzen Abfragen ob die Winkel auch größer 0 und nicht größer 360 sind kann man sich natürlich sparen, wenn man das sowieso im Code abfängt, also würde man da noch etwas Speed rausholen. Zu Funktionen wie Abs und Sgn würd ich sagen: Vermeide sie wo es geht und bei diesem Ansatz geht es sicher. walski |
||
buh! |
zocker2150 |
Fr, Dez 24, 2004 14:22 Antworten mit Zitat |
|
---|---|---|
Die Funktion...
Code: [AUSKLAPPEN] Function Drehzuwinkel(IW#,SW#)
Local W# = IW# - SW# If W# < -180 Then W# = W# + 360 If W# > 180 Then W# = W# - 360 If W# < 0 Then Return 1 Else Return -1 End If End Function Zum Aufrufen... Code: [AUSKLAPPEN] IstW# = ((IstW# + Speed * drehvari)+360) Mod 360
Code: [AUSKLAPPEN] DrawImage bild(IstW#), BildX,BildY
|
||
- Zuletzt bearbeitet von zocker2150 am Fr, Dez 24, 2004 14:58, insgesamt einmal bearbeitet
MVB |
Fr, Dez 24, 2004 14:24 Antworten mit Zitat |
|
---|---|---|
Ich weiß nicht, villeicht bin ich auch zu dumm, aber irgendwas stimmt mit Rallimans Code nicht.
Nehmen wirmal an der IST-Winkel ist 10; und der SOLL-Winkel ist 20; Jetzt nehmen wir den Code und setzen wir das ein: Code: [AUSKLAPPEN] posPanzer =(10 + -1 +360)Mod 360
Da kommt 9 raus?! Das "drehAufZiel(pospanzer,winkel)" hab ich durch -1 ersetzt weil das bei der Funktion herauskäme; 10-180 ist bekanntlich kleiner als 20. Verstehe ich was falsch, oder funktioniert das nicht? EDIT: Sorry! Ich hab was übersehen. EDIT2: Jetzt wo ichs mir nochmal angucke ist wieder etwas falsch. Bei dem was ich oben geschrieben habe müsste "-1" durch "1" ersetzt werden. Jetzt kommt 11 raus?! Ich bin verwirrt. |
||
aquamonit.de|BlitzMax|MaxGUI |
RallimenSieger des 30-EUR-Wettbewerbs |
Fr, Dez 24, 2004 14:53 Antworten mit Zitat |
|
---|---|---|
das soll doch auch so sein, immer 1 grad weiter in richtige richtung drehen und zeichnen!
sonst könnte man sich das viel einfacher machen >> PosPanzer = winkel hier nochmal der Code mit Function Code: [AUSKLAPPEN] Graphics 800,600,16,2
SetBuffer BackBuffer() Dim Panzer (360) ;PanzerGrafik_berechnen > 360 Einzelbilder < Rect 9,0,2,20 Rect 0,10,20,20,1 Flip Panzer(0) = CreateImage (20,30) GrabImage Panzer(0),0,0 MidHandle Panzer(0) For z= 1 To 359 panzer(z) = CopyImage (Panzer(0)) RotateImage panzer(z),z Text 500,500," Berechne Panzer : "+z If z Mod 10 = 0 Flip Cls Next x= 400: y= 30 ; damit der zielpunkt zu sehen ist Repeat If MouseDown(1) Then x= MouseX () Y= MouseY () ;Winkel bezieht sich auf den Panzer winkel = Objekt_richtung_grad(x,y ,400 ,300) End If posPanzer =(posPanzer + drehAufZiel(pospanzer,winkel)+360)Mod 360 Oval x-5,y-5,10,10,1 ;Klickpunkt malen DrawBlock Panzer(posPanzer),400,300;Panzer malen Text 100,30, posPanzer + " Panzer" Text 100,60, winkel + " Grad" Flip Cls Until KeyHit (1) End Function Objekt_richtung_grad(Zielpunkt_X,Zielpunkt_Y,Ausgangspunkt_X,Ausgangspunkt_Y ) grad =ATan2(Zielpunkt_Y -Ausgangspunkt_Y, Zielpunkt_X -Ausgangspunkt_X)+90 grad = (grad+360) Mod 360 Return grad End Function Function drehAufZiel (pospanzer,winkel) If posPanzer > Winkel Then If posPanzer -180 < Winkel Then Return -1 Else If posPanzer +180 < Winkel Then Return -1 End If Return 1 End Function |
||
[BB2D | BB3D | BB+]
|
MVB |
Fr, Dez 24, 2004 15:24 Antworten mit Zitat |
|
---|---|---|
Auchso ist klar. Ich hab irgendwie falsch gedacht. Ich dachte jetzt werden zu den 10 nochmal 11 addiert. | ||
aquamonit.de|BlitzMax|MaxGUI |
zocker2150 |
Fr, Dez 24, 2004 15:38 Antworten mit Zitat |
|
---|---|---|
@ Rallimen
Haha das hab ich mir auch so ausgedacht... ( nettes Programm ) Sie selber; ist nicht abgeschrieben! Code: [AUSKLAPPEN] Const GrafikX = 640
Const GrafikY = 480 Graphics GrafikX,GrafikY,32,0 SetBuffer BackBuffer() TFormFilter False Dim Panzer(360) Panzer(0) = CreateImage(20,30) SetBuffer ImageBuffer(Panzer(0)) Color 50,50,250 Rect 5,0,4,30 Rect 0,10,20,20 MidHandle Panzer(0) For i = 1 To 360 Panzer(i) = CopyImage(Panzer(0)) RotateImage Panzer(i),-i Next Speed = 1 IstW# = 90 SollW# = 50 BildX = GrafikX/2 BildY = GrafikY/2 Color 0,0,0 SetBuffer BackBuffer() Repeat ClsColor 255,255,255 Cls MausX = MouseX() MausY = MouseY() If MouseHit(1) Then SaveX = MausX SaveY = MausY End If SollW# = (ATan2(BildX-SaveX,BildY-SaveY)+360) Mod 360 drehvari = Drehzuwinkel(IstW#,SollW#) IstW# = ((IstW# + Speed * drehvari)+360) Mod 360 Color 0,0,0 : Text 20,20,"ISTW " + IstW# Text 20,40,"SollW " + SollW# DrawImage Panzer(IstW#), BildX,BildY Color 255,0,0 : Rect SaveX,SaveY,5,5,1 Flip Until KeyHit(1) End Function Drehzuwinkel(IW#,SW#) Local W# = IW# - SW# If W# < -180 Then W# = W# + 360 If W# > 180 Then W# = W# - 360 If W# < 0 Then Return 1 Else Return -1 End If End Function |
||
KabelbinderSieger des WM-Contest 2006 |
Fr, Dez 24, 2004 16:29 Antworten mit Zitat |
|
---|---|---|
Als ich den Code mit den Suchraketen gemacht hatte, musste ich mich auch damit rumschlagen:
https://www.blitzforum.de/viewtopic.php?t=5986 Ich hatte da einfach geprüft, ob der IST-winkel < 180 ist wenn ja, rechnet er in einer anderen Variable 180 dazu und überprüft dann, ob diese Variable immer noch kleiner ist, als der SOLL-Winkel. Wenn nicht: winkel=winkel-1 Wenn ja: winkel = winkel+1 Ist der IST-winkel > 180 halt 180 davon abziehen. Edit: Man, die haben meine alten Texte ja total verstümmelt, hab das grad mal wieder im Ordnung gebracht. |
||
<Wing Avenger Download> ◊◊◊ <Macrophage Download> |
Übersicht BlitzBasic Allgemein
Powered by phpBB © 2001 - 2006, phpBB Group