Flugbahnen berechnen - bitte um Hilfe

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

Kompensator

Betreff: Flugbahnen berechnen - bitte um Hilfe

BeitragDi, März 22, 2016 7:44
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi, ich habe 2 Probleme:

1.
Ein Planet bewegt sich auf einer Kreisbahn um eine Sonne. Mein Raumschiff soll den Planeten anfliegen, ist zum Hinterherfliegen aber zu langsam. Also muß ich eine Flugrichtung berechnen die den Kreis dann schneidet, wenn der Planet auch da ist. Ich will ja nicht auf der Kreisbahn warten, bis der Planet irgendwann mal wieder vorbeikommt. Das Raumschiff beschleunigt nicht spontan sondern kontinuierlich, ebenso sind Richtungsänderungen träge (zur Not für den Anfang vernachlässigen). Weiß jemand, wie sowas geht?

Zur Illustration was ich will hier ein Beispiel-Code:
Wenn geklickt wird, brauche ich eine passende Position für mein grünes Zielobjekt.
Schön wär's, wenn man nicht mit FullSpeed in den Planeten reinkracht, sondern vorher mit negativer Beschleunigung sanft abbremst (acceleration acc#=0.0015).

Code: [AUSKLAPPEN]


Graphics3D 800, 600, 32, 2

vMax#=0.2
acc#=0.0015 ; acceleration
MaxTurnSpeed#=1.5
OrbitRadius#=12
PlanetSpeed#=1

camera=CreateCamera()
PositionEntity camera, 0, 20, -10

sun=CreateSphere()
PointEntity camera,sun

planet=CreateSphere(8,sun)
MoveEntity planet,OrbitRadius,0,0
ScaleEntity planet,0.5,0.5,0.5
EntityColor sun,255,255,0
EntityColor planet,55,55,155

ship=CreateCone()
RotateMesh ship,90,0,0
PositionEntity ship,Rand(-10,10),Rand(-10,10),Rand(-10,10)

desired=CreateCone()
RotateMesh desired,90,0,0
EntityAlpha desired,0.5

target=CreateSphere(2)
EntityColor target,55,155,55
PositionEntity target,Rand(-10,10),Rand(-10,10),Rand(-10,10)




SetBuffer BackBuffer()
While Not KeyHit(1) Or MouseHit(2)




TurnEntity sun,0,PlanetSpeed,0

PositionEntity desired,EntityX(ship),EntityY(ship),EntityZ(ship)
PointEntity desired,target
If DeltaPitch (ship,target) > 0 Then TurnEntity ship,MaxTurnSpeed,0,0 Else TurnEntity ship,-MaxTurnSpeed,0,0
If DeltaYaw (ship,target) > 0 Then TurnEntity ship,0,MaxTurnSpeed,0 Else TurnEntity ship,0,-MaxTurnSpeed,0
If EntityDistance(ship,target)<0.5 Then PositionEntity target,Rand(-10,10),Rand(-10,10),Rand(-10,10)

If MouseHit(1) Then accelerate = Not accelerate
If accelerate=1 Then v#=v+acc : If v>vMax Then v=vMax
If accelerate=0 Then v#=v-acc : If v<0 Then v=0
MoveEntity ship,0,0,v




UpdateWorld
RenderWorld

Text 10,10,"LeftClick to start/stop ship"
Text 10,30,"v = "+v

Flip
Wend
End






2.
Ein Ball wird gegen eine Wand geschossen und prallt ab. Zum Hinterherlaufen bin ich 1. zu langsam und 2. läuft man dann unnötige Umwege. Ich muß einen Punkt berechnen, den ich mit maximaler Laufgeschwingkeit ansteuere und ihn dann erreiche, wenn der abgeprallte Ball auch da ist. Erschwerend kommt dazu, das der Läufer nicht sofort von null auf maximale Geschwindigkeit beschleunigen kann oder in null Zeit seine Richtung ändern kann (Trägheit). Das können wir für den Anfang, wenn's zu schwer ist, auch vernachlässigen. Aber auch der Ball wird mit der Zeit langsamer (Luftwiderstand).

(Beispiel-Code folgt)

Ich kann leider nicht abschätzen, wie kompliziert diese Probleme, für jemanden der sich auskennt, sind. Ich weiß nur, ich habe bis jetzt keine Ahnung wie ich das machen soll.

Für Denkanstöße, Suchbegriffe, Links, Formeln oder Codes wäre ich dankbar.

DAK

BeitragDi, März 22, 2016 13:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, im Grunde hast du jeweils ein Objekt (o1), das sich auf einer vorgegebenen Bahn mit einer vorgegebenen Geschwindigkeit bewegt. Dazu hast du ein Objekt (o2), das sich auf einer beliebigen Bahn mit einer Maximalgeschwindigkeit bewegt.

Für o1 lässt sich leicht eine Funktion (f1) erstellen, die angibt, an welcher Position sich o1 zum Zeitpunkt t befindet.

Für o2 kann man davon ausgehen, das die Maximalgeschwindigkeit immer genommen wird, weil dann o2 bei höherer Geschwindigkeit einfach früher bei o1 ankommt. Das macht es deutlich einfacher, ist aber, wenn z.B. Spritverbrauch wichtig wäre, der falsche Ansatz, ist aber nicht so, also kann man das machen. Hier lässt sich eine Funktion (f2) bilden, die für einen Zeitpunkt t einen Kreis zurück gibt, in dem alle Punkte liegen, die o2 bis zum Zeitpunkt t erreichen kann.

Soweit ist das alles ganz einfach und nur niedere Mathematik. Der Rest wird komplexer, lässt sich aber auch erschummeln. Zuerst erkläre ich mal den "richtigen" Weg, danach den "erschummelten".

Will man es richtig machen, muss man jetzt eine Funktion (f3) bilden, die mithilfe der ersten beiden Funktionen berechnet, wie weit zum Zeitpunkt t der Punkt aus f1 vom Rand des Kreises aus f2 entfernt ist. Diese Funktion muss man jetzt null-setzen ( f3(t) = 0 ) um das t zu berechnen, bei dem der Punkt aus f1 auf den Kreis aus f2 trifft. Dieser Punkt ist der Treffpunkt. Hieraus kann man dann berechnen, wie das Raumschiff fliegen / der Spieler laufen muss, um am richtigen Ort zur richtigen Zeit zu sein.

Der erschummelte Weg verwendet immer noch f1 und f2, nur statt dem ganzen Ableiten probiert man durch. Man probiert t durch, solange bis der Punkt aus f1 innerhalb des Kreises aus f2 liegt. Das kann man im Stil einer binären Suche machen, also man probiert zuerst eher grobe Werte aus, bis man ein t hat, das im Kreis liegt und eines, das außerhalb des Kreises liegt. Das verfeinert man, bis man dann einen halbwegs genauen Treffpunkt findet.
Gewinner der 6. und der 68. BlitzCodeCompo
 

Tritium

BeitragMo, Apr 04, 2016 7:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Zu Frage 1 könnten Dir https://en.wikipedia.org/wiki/...sfer_orbit und https://en.wikipedia.org/wiki/Bi-elliptic_transfer weiterhelfen.
 

Kompensator

BeitragFr, Apr 15, 2016 21:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Heieiei, das klingt aber komplitziert.
Deine leicht zu erstellende f1 übersteigt schon meine mathematischen Fähigkeiten. Bei einem Kreis in der 2D-Ebene krieg ich das vielleicht noch hin, aber bei einem schiefen Kreis im 3D-Raum bin ich am Ende meiner Kunstfertigkeit. Ich kenne auch keine Funktionen, die mir 3 3D Koordinaten zurückliefern. Ich kenne nur f(x)=y. Ich überlegte mir als t die frames zu nehmen um dann den Winkel zu bekommen f(t)=w bzw. f(frame)=winkel. Um die 3D Position zu bekommen habe ich dann einfach ein paar HelperEntities gemacht. Für die f2 wird einfach die speed pro frame zu einer Strecke aufaddiert. Wenn sich PlanetHelper und die EntfernungsSphere treffen (braucht man nicht, nur zur Veranschaulichung), dann kommt da mein target hin.
Danke DAK für deine schnelle und ausführliche Erklärung. Ich hab's noch am selben Tag programmiert, nur das zurückposten hat gedauert (bin grad mit umziehen beschäftigt). Vielleicht habe ich es nicht so umgesetzt wie du es gemacht hättest, aber ich habe ausgehend von deinen Erläuterungen eine für mich erstmal funktionierende Lösung gefunden. Eine rein mathematische Lösung wäre vielleicht eleganter, das muß aber erstmal warten oder von jemandem kompetenteren übernommen werden.

Tritium: Dein Tip ist bestimmt gut gemeint, nur weiß ich im Moment nicht, was ich damit anfangen soll. Aber das ist ja das schöne am Programmieren - man kriegt Zeug zu sehen an das man vorher im Leben noch nie gedacht hat.

Hier mein Ergebnis:

Code: [AUSKLAPPEN]

Graphics3D 800, 600, 32, 2


vMax#=0.2
acc#=0.0015
OrbitRadius#=12
PlanetSpeed#=1


camera=CreateCamera()
PositionEntity camera, 0, 20, -10

sun=CreateCube()
EntityColor sun,255,255,0
PointEntity camera,sun
TurnEntity sun,40,0,0 ; windschiefe Umlaufbahn

planet=CreateSphere(8,sun)
MoveEntity planet,0,0,OrbitRadius
ScaleEntity planet,0.5,0.5,0.5
EntityColor planet,55,55,155

ship=CreateCone()
RotateMesh ship,90,0,0
PositionEntity ship,Rand(-10,10),Rand(-10,10),Rand(-10,10)

target=CreateSphere(2)
EntityColor target,55,155,55


PlanetHelperPivot=CreateCube()
PlanetHelper=CreateCube(PlanetHelperPivot)
MoveEntity PlanetHelper,0,0,OrbitRadius
EntityAlpha PlanetHelper,0.5
EntityAlpha PlanetHelperPivot,0.5


;ShipHelper braucht man nicht - nur zur Veranschaulichung
ShipHelper=CreateSphere()
EntityAlpha ShipHelper,0.5




SetBuffer BackBuffer()
While Not KeyHit(1) Or MouseHit(2)




If calc=0 ; wenn nichts passiert kreist der Planet
   TurnEntity sun,0,PlanetSpeed,0
   TurnEntity PlanetHelperPivot,0,PlanetSpeed,0
   
   If MouseHit(1) Then accelerate = Not accelerate
   If accelerate=1 Then v#=v+acc : If v>vMax Then v=vMax
   If accelerate=0 Then v#=v-acc : If v<0 Then v=0
   MoveEntity ship,0,0,v
EndIf


If KeyHit(57)=1 Then calc = 1


; Ausgangsposition für Berechnung
If calc=1 Then
   RotateEntity PlanetHelperPivot,EntityPitch(sun),EntityYaw(sun),EntityRoll(sun)
   PositionEntity ShipHelper,EntityX(ship),EntityY(ship),EntityZ(ship)
   vOld#=v# ; ShipSpeed merken
   calc=2
EndIf

; Berechnung
If calc=2 Then
   TurnEntity PlanetHelperPivot,0,PlanetSpeed,0
   v#=v+acc : If v>vMax Then v=vMax
   s#=s+v
   ScaleEntity ShipHelper,s,s,s
   distS#=EntityDistance(PlanetHelper,ship)
   If distS<s Then
      PositionEntity target,EntityX(PlanetHelper,1),EntityY(PlanetHelper,1),EntityZ(PlanetHelper,1) ; place green target
      PointEntity ship,target
      v=vOld ; writeback ShipSpeed
      accelerate=1 ; start ship
      calc=0 ; go to animation
      s=0 : ScaleEntity ShipHelper,s,s,s ; hide ShipHelper
      Delay 1000
   EndIf
EndIf





winkel=EntityYaw(sun)
If winkel<0 Then winkel=winkel+360

UpdateWorld
RenderWorld
   
   Text 10,10,"LeftClick to start/stop ship"
   Text 10,30,"Press Space to calculate new target position"
   Text 10,50,"v = "+v
   Text 10,70,"winkel: "+winkel
   
Flip
Wend
End





Alles ist einfach, solange bis es kompliziert wird. - Erich Honecker

DAK

BeitragFr, Apr 15, 2016 22:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, wenn's funktioniert, dann ist's ja gut Wink


Für f1: Dafür definier dir einen Vektor-Type:

BlitzBasic: [AUSKLAPPEN]
Type TVector
Field x
Field y
Field z
End Type


Wenn du bei der Funktion dann eine Position im 3D-Raum zurück geben willst, kannst du dir einfach ein Objekt von diesem Typ zurück geben.

Was du auch machen kannst, wenn du eh viel mit Vektorrechnung zutun hast, wie es hier der Fall ist, wenn du es rein mathematisch machen willst, dann kannst du dir meine Vektor-Bibliothek holen von hier. Die ist klein und nett und kann alles was du mit Vektoren machen können wollen würdest. Da brauchst du nicht mehr die einzelnen Koordinaten verrechnen, das macht das Ding für dich.
Gewinner der 6. und der 68. BlitzCodeCompo

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group