BPS #4: Vektoren - Auswertung

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

Xeres

Moderator

Betreff: BPS #4: Vektoren - Auswertung

BeitragDo, März 17, 2011 21:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Damit ist die Zeit 'rum.

Das war die Aufgabe

Postet hier eure Ergebnisse, Codes, Gedanken. Lernt von den anderen, seht euch deren Quelltext an und versucht euren eigenen zu verbessern.

Diskussion
Postet zu euren Codes stets eine kurze Erklärung mit euren Gedanken in denen ihr simpel gesagt die Frage "Wieso habe ich XY auf diese Art gelöst?" beantwortet. Beiträge, die nur den Code enthalten werden wir aus dem Thread entfernen.

Nächste Aufgabe
In drei Tagen, am 20. März wird die Musterlösung nach editiert und die nächste Aufgabe eingestellt.

Viel Spaß & viel Erfolg!

Musterlösung:
BlitzMax: [AUSKLAPPEN]
SuperStrict
' BPS: Holzchopf - Vektoren

' nötige Module importieren
Framework BRL.Max2D
Import BRL.Timer
Import BRL.GLMax2D

' ein paar Konstanten für die Übersichtlichkeit
Const WIDTH:Int = 800 ' Breite (vom Grafikfenster)
Const HEIGHT:Int = 600 ' Höhe
Const CENTER_X:Int = WIDTH /2
Const CENTER_Y:Int = HEIGHT /2

' Fenster initialisieren
Graphics WIDTH,HEIGHT
Global timer:TTimer = CreateTimer(50)

' Deklarationen
Local mouseVector:Int[2] ' Vektor zur Maus (0: X-Koordinate, 1: Y-Koordinate)
Local unitVector:Double[2] ' Normalisierter Maus-Vektor
Local orthVector:Int[2] ' Vektor orthogonal zum Maus-Vektor

' Hauptschleife
While Not (KeyDown(KEY_ESCAPE) Or AppTerminate())
' Vektor von der Bildschirmmitte zur Mausposition
mouseVector[0] = MouseX() -CENTER_X
mouseVector[1] = MouseY() -CENTER_Y

' Betrag (Länge) des Maus-Vektors
' Der Betrag kann mit dem Satz des Pythagoras berechnet werden.
Local mouseVectorLn:Double = Sqr(mouseVector[0]*mouseVector[0] +mouseVector[1]*mouseVector[1])
' Einheitsvektor bilden
' Einheitsvektoren sind Vektoren mit der Länge 1. Für einen gegebenen
' Vektor kann man den Einheitsvektor bilden, indem man ihn durch seinen
' Betrag (Länge) teilt.
' unitVector = mouseVector / ||mouseVector||
If mouseVectorLn>0 ' Nur normalisieren, wenn mouseVektor <> 0-Vektor
unitVector[0] = mouseVector[0] /mouseVectorLn
unitVector[1] = mouseVector[1] /mouseVectorLn
Else ' 0-Vektor -> Länge = 0 -> e-Vektor nicht definiert
unitVector[0] = 0
unitVector[1] = 0
EndIf

' orthogonalen Vektor erstellen...
' Orthogonale Vektoren lassen sich bilden, indem man die Komponenten
' eines Vektors vertauscht und bei einem das Vorzeichen wechselt.
' xo = -y1
' yo = x1
' ... und in der Länge halbieren
' Halbiert man die Komponenten eines Vektors, so halbiert sich auch der
' Betrag des ganzen Vektors.
orthVector[0] = -mouseVector[1] *0.5
orthVector[1] = mouseVector[0] *0.5

' Vektoren zeichnen (als Offset (Nullpunkt) wird immer die Bildschirm-
' mitte verwendet (deshalb werden CENTER_X /Y addiert)
' Maus-Vektor
SetColor 255,0,0
DrawLine CENTER_X,CENTER_Y, CENTER_X+mouseVector[0], CENTER_Y+mouseVector[1]
' Einheitsvektor *(-100)
SetColor 0,0,255
DrawLine CENTER_X,CENTER_Y, CENTER_X-unitVector[0] *100, CENTER_Y-unitVector[1]*100
' orthogonaler Vektor
SetColor 0,255,0
DrawLine CENTER_X,CENTER_Y, CENTER_X+orthVector[0], CENTER_Y+orthVector[1]

' Double-Buffering
Flip 0
Cls
' FPS-Begrenzung
WaitTimer(timer)
Wend

End
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
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
  • Zuletzt bearbeitet von Xeres am So, März 20, 2011 21:03, insgesamt einmal bearbeitet

BlitzMoritz

BeitragDo, März 17, 2011 22:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Im ersten Beispiel folge ich ganz der Aufgabenstellung und gehe von einem Vektor aus, der durch die Summe seines Ortsvektors mit einem skalaren Vielfachen seines Richtungsvektors definiert wird. Die Richtungszuweisungen der anderen geforderten Vektoren sind ja eigentlich schon alle in der Aufgabenstellung verraten worden, das einzige, was noch ergänzt werden müsste, ist die Auseinandersetzung mit dem Satz des Pythagoras, mit dem man den Betrag des Vektors aus der Wurzel der Summe der Quadrate seiner Richtungsvektorkoordinaten berechnen kann. Da das Ganze ziemlich anspruchslos ist, habe ich mir erlaubt, noch eine kleine Prozedur hinzuzufügen, mit der man den Schnittpunkt mit einem anderen Vektor bestimmen kann.
BlitzMax: [AUSKLAPPEN]
Graphics 800,600

'Damit wir nicht permanent dieselbe Funktion aufrufen wollen, legen wir hiermit den geforderten "Ursprung" fest:
Local BildschirmMitteX:Int = GraphicsWidth()/2
Local BildschirmMitteY:Int = GraphicsHeight()/2

'Nun werden die drei Vektorobjekte gebildet (siehe unten die Klasse "TVektor"):
Local MausVektor:TVektor = TVektor.erschaffen([BildschirmMitteX, BildschirmMitteY], [MouseX() - BildschirmMitteX, MouseY() - BildschirmMitteY])
Local GegenVektor:TVektor = TVektor.erschaffen([BildschirmMitteX, BildschirmMitteY], [-MausVektor.Richtung[0], -MausVektor.Richtung[1]])
Local SenkrechtVektor:TVektor = TVektor.erschaffen([BildschirmMitteX, BildschirmMitteY], [-MausVektor.Richtung[1], MausVektor.Richtung[0]])
'Und noch einen zusaetzlichen Vektor fuer die Schnittpunktermittlung mit dem MausVektor:
Local ZufallsVektor:TVektor = TVektor.erschaffen([Rand(200,GraphicsWidth()-200), Rand(200,GraphicsHeight()-200)], [Rand(-200,200), Rand(-200,200)])

While Not KeyDown(KEY_ESCAPE) And Not AppTerminate()
Cls

MausVektor.NeueRichtung([MouseX() - BildschirmMitteX, MouseY() - BildschirmMitteY])
MausVektor.Zeichnen(255, 0, 0)
DrawText "MausVektor", 10, 10

GegenVektor.NeueRichtung([-MausVektor.Richtung[0], -MausVektor.Richtung[1]]) 'Genau entgegengesetzt = umgekehrte Vorzeichen
GegenVektor.NeuerBetrag(100) 'die BPS-Aufgabe verlangt eine genormte Laenge von 100 Pixel
GegenVektor.Zeichnen(255,255,0)
DrawText "Entgegengesetzter Vektor mit genormten Betrag von 100 Pixeln", 10, 30

SenkrechtVektor.NeueRichtung([-MausVektor.Richtung[1], MausVektor.Richtung[0]]) 'wird bereits in der BPS-Aufgabenstellung verraten ('s gibt aber zwei Moeglichkeiten)
SenkrechtVektor.NeuerBetrag(MausVektor.ErrechneBetrag()/2) 'die BPS-Aufgabe verlangt die halbe Laenge des MausVektors
SenkrechtVektor.Zeichnen(0,255,0)
DrawText "Orthogonaler Vektor, halb so lang wie MausVektor", 10, 50

If MouseHit(1) Then 'bei Mausklick soll ein neuer Zufallsvektor erstellt werden
ZufallsVektor = Null
ZufallsVektor = TVektor.erschaffen([Rand(200,GraphicsWidth()-200), Rand(200,GraphicsHeight()-200)], [Rand(-200,200), Rand(-200,200)])
End If
ZufallsVektor.Zeichnen(0,255,255)
DrawText "ZufallsVektor (neu mit Mausklick!)", 10, 70

Local Schnittpunkt:Float[] = MausVektor.ErrechneSchnittpunkt(ZufallsVektor)
If Schnittpunkt <> Null Then
SetColor 255,255,255
DrawOval Schnittpunkt[0]-3, Schnittpunkt[1]-3, 7, 7
DrawText "Schnittpunkt", Schnittpunkt[0]+16, Schnittpunkt[1]+12
End If

Flip
Wend

'------------------------------------------------------------------------------------------
'Fuer den zweidimensionalen Vektor definieren wir eine eigene Klasse...
Type TVektor

'...und folgen der ueblichen Vektordarstellung:
Field Ort:Int[2], Skalar:Float, Richtung:Int[2]
'Vektor = Ort(svektor) + Skalar * Richtung(svektor)

'Zuerst der "Konstruktor", mit dem man ein Objekt bzw. eine Instanz der Klasse "TVektor" erzeugt:
Function erschaffen:TVektor(Ort:Int[], Richtung:Int[])
Local NeuerVektor:TVektor = New TVektor
NeuerVektor.NeuerOrt(Ort)
NeuerVektor.NeueRichtung(Richtung)
Return NeuerVektor
End Function

'Es folgen die klasseninternen Prozeduren:

Method NeuerOrt(O:Int[])
Ort[0] = O[0]
Ort[1] = O[1]
End Method

Method NeueRichtung(R:Int[])
Richtung[0] = R[0]
Richtung[1] = R[1]
Skalar = 1
End Method

Method NeuerBetrag(B:Float)
If Richtung[0] <> 0 Or Richtung[1] <> 0 Then 'durch dieses Ausschlussverfahren wird die Division durch Null verhindert.
Skalar = B / Sqr(Richtung[0]^2 + Richtung[1]^2) 'hier steckt die gute alte Formel von Pythagoras d'rin...
End If
End Method

Method ErrechneBetrag:Float()
Return Skalar * Sqr( Richtung[1]^2 + Richtung[0]^2 ) 'hier ebenso...
End Method

Method Zeichnen(Rot:Int, Gruen:Int, Blau:Int) 'Rot-Gruen-Blau-Werte fuer die Farbe des Vektors
SetColor Rot, Gruen, Blau
DrawLine Ort[0], Ort[1], Ort[0] + Skalar * Richtung[0], Ort[1] + Skalar * Richtung[1] 'siehe uebliche Vektordarstellung
End Method

Method ErrechneSchnittpunkt:Float[](AndererVektor:TVektor)

'Laeuft eigentlich auf das Loesen eines Linearen Gleichungssystems hinaus (siehe BlitzMax-Code-Archiv ...),
'ist aber hier aufgrund der Zweidimensionalitaet relativ leicht ohne Algorithmus in eine kleine Formel zu packen.

'Einige Sonderfaelle muessen davor ausgeschlossen werden, z.B. reine Nullvektoren ohne Betrag und daher auch ohne Schnittpunkt:
If (Richtung[0] = 0 And Richtung[1] = 0) Or (AndererVektor.Richtung[0] = 0 And AndererVektor.Richtung[1] = 0) Then Return Null

'oder parallele Vektoren, die sich natuerlich auch nicht schneiden (das Lineare Gleichungssystem waere dann "linear abhaengig"):
If Richtung[0] * AndererVektor.Richtung[1] = Richtung[1] * AndererVektor.Richtung[0] Then Return Null
'(Der Sonderfall des Sonderfalls, dass zwei Vektoren bei gleichem Ortsvektor aufeinander liegen, also unendlich viele gemeinsame Punkte besitzen, sei hier ignoriert)

'Ansonsten muss es einen Schnittpunkt geben. Die mathematische Herleitung der Formel wuerde hier den Rahmen leider sprengen.
Local SchnittSkalar:Float[2] 'bilden die zu berechnenden Variablen, es folgen die entsprechenden Umformungen aus der Gleichsetzung Vektor = AndererVektor
SchnittSkalar[1] = 1.0 * ( Ort[1] * Richtung[0] - Ort[0] * Richtung[1] + AndererVektor.Ort[0] * Richtung[1] - AndererVektor.Ort[1] * Richtung[0] ) / ( Richtung[0] * AndererVektor.Richtung[1] + Richtung[1] * AndererVektor.Richtung[1] - Richtung[1] * AndererVektor.Richtung[0] - Richtung[1] * AndererVektor.Richtung[1] )
If Richtung[0] <> 0 Then 'dafuer sorgen, dass man nicht durch Null dividiert
SchnittSkalar[0] = 1.0 * ( AndererVektor.Ort[0] - Ort[0] + SchnittSkalar[1] * AndererVektor.Richtung[0] ) / Richtung[0]
Else '(beide koennen nicht gleich Null sein, das wurde oben bereits ausgeschlossen)
SchnittSkalar[0] = 1.0 * ( AndererVektor.Ort[1] - Ort[1] + SchnittSkalar[1] * AndererVektor.Richtung[1] ) / Richtung[1]
End If

'Im letzten Schritt muss noch ueber einen Skalarvergleich geprueft werden, ob der potentielle Geradenschnittpunkt nicht etwa ausserhalb der Vektorlaengen liegt:
If (Skalar > 0 And (SchnittSkalar[0] < 0 Or Skalar < SchnittSkalar[0])) Or (Skalar < 0 And (SchnittSkalar[0] > 0 Or Skalar > SchnittSkalar[0])) Then Return Null
If (AndererVektor.Skalar > 0 And (SchnittSkalar[1] < 0 Or AndererVektor.Skalar < SchnittSkalar[1])) Or (AndererVektor.Skalar < 0 And (SchnittSkalar[1] > 0 Or AndererVektor.Skalar > SchnittSkalar[1])) Then Return Null

'Ansonsten werden endlich die Koordinaten des Schnittpunkts zurueckgegeben:
Return [ Ort[0] + SchnittSkalar[0] * Richtung[0], Ort[1] + SchnittSkalar[0] * Richtung[1] ]

End Method

End Type

Auch wenn es in der Aufgabenstellung "verboten" wurde, möchte ich es nicht versäumen, ein alternatives Beispiel mit Winkeln statt Richtungsvektoren anzuführen, weil diese Methode nach meiner Erfahrung in vielen Spielsituationen praktikabler ist. Zum Beispiel könnte ich ohne weiteren Rechenaufwand den Richtungswinkel nutzen, um an den Vektorspitzen passend gedrehte Pfeile zu malen, was im obigen Beispiel gar nicht so leicht ginge und letztlich doch diesen einen Drehungswinkel benötigte.
BlitzMax: [AUSKLAPPEN]
Graphics 800,600

'Diese Vorbereitungen sind schon bekannt:
Local BildschirmMitteX:Int = GraphicsWidth()/2
Local BildschirmMitteY:Int = GraphicsHeight()/2
Local MausVektor:TWinkelVektor = TWinkelVektor.erschaffen_aus_zwei_Punkten([BildschirmMitteX, BildschirmMitteY], [MouseX(), MouseY()])
Local GegenVektor:TWinkelVektor = TWinkelVektor.erschaffen_aus_Winkel_und_Betrag([BildschirmMitteX, BildschirmMitteY], (MausVektor.Winkel + 180) Mod 360, 100)
Local SenkrechtWinkelVektor:TWinkelVektor = TWinkelVektor.erschaffen_aus_Winkel_und_Betrag([BildschirmMitteX, BildschirmMitteY], (MausVektor.Winkel + 90) Mod 360, MausVektor.Betrag/2)
Local ZufallsVektor:TWinkelVektor = TWinkelVektor.erschaffen_aus_Winkel_und_Betrag([Rand(100,GraphicsWidth()-100), Rand(100,GraphicsHeight()-100)], Rand(0,360), Rand(100,200))
'Auch die Hauptschleife ist kaum anders, nur die Prozeduren der Vektorklasse sind anders!
While Not KeyDown(KEY_ESCAPE) And Not AppTerminate()
Cls

MausVektor.VerbindeMit(MouseX(), MouseY())
MausVektor.Zeichnen(255, 0, 0)
DrawText "MausVektor", 10, 10

GegenVektor.NeuerWinkel((MausVektor.Winkel + 180) Mod 360) 'Genau entgegengesetzt = um 180° gedreht!
GegenVektor.NeuerBetrag(100) 'die BPS-Aufgabe verlangt eine genormte Laenge von 100 Pixel
GegenVektor.Zeichnen(255,255,0)
DrawText "Entgegengesetzter Vektor mit genormten Betrag von 100 Pixeln", 10, 30

SenkrechtWinkelVektor.NeuerWinkel((MausVektor.Winkel + 90) Mod 360) 'orthogonal = 90°
SenkrechtWinkelVektor.NeuerBetrag(MausVektor.Betrag/2) 'die BPS-Aufgabe verlangt die halbe Laenge des MausVektors
SenkrechtWinkelVektor.Zeichnen(0,255,0)
DrawText "Orthogonaler Vektor, halb so lang wie MausVektor", 10, 50

If MouseHit(1) Then 'bei Mausklick soll ein neuer Zufallsvektor erstellt werden
ZufallsVektor = Null
ZufallsVektor = TWinkelVektor.erschaffen_aus_Winkel_und_Betrag([Rand(100,GraphicsWidth()-100), Rand(100,GraphicsHeight()-100)], Rand(0,360), Rand(100,200))
End If
ZufallsVektor.Zeichnen(0,255,255)
DrawText "ZufallsVektor (neu mit Mausklick!)", 10, 70

Local Schnittpunkt:Float[] = MausVektor.ErrechneSchnittpunkt(ZufallsVektor)
If Schnittpunkt <> Null Then
SetColor 255,255,255
DrawOval Schnittpunkt[0]-3, Schnittpunkt[1]-3, 7, 7
DrawText "Schnittpunkt", Schnittpunkt[0]+16, Schnittpunkt[1]+12
End If

Flip
Wend

'------------------------------------------------------------------------------------------
Type TWinkelVektor

'...und hier nun eine alternative Darstellung:
Field Anker:Int[2], Betrag:Float, Winkel:Float
'Der "Anker" bzw. Anfangspunkt entspricht dem "Ortsvektor", der Richtungsvektor wird
'quasi von einem Winkel ersetzt und der konkrete Betrag ersetzt den Skalar.

'Zuerst der "Konstruktor", mit dem man ein Objekt bzw. eine Instanz der Klasse "TWinkelVektor" aus zwei Punkten erzeugt:
Function erschaffen_aus_zwei_Punkten:TWinkelVektor(Anker:Int[], EndPunkt:Int[])
Local NeuerWinkelVektor:TWinkelVektor = New TWinkelVektor
NeuerWinkelVektor.NeuerAnker(Anker)
NeuerWinkelVektor.VerbindeMit( EndPunkt[0], EndPunkt[1] )
Return NeuerWinkelVektor
End Function

'Ein alternativer "Konstruktor" ohne zweiten Punkt, aber Winkel und Betrag:
Function erschaffen_aus_Winkel_und_Betrag:TWinkelVektor(Anker:Int[], Winkel:Float, Betrag:Float)
Local NeuerWinkelVektor:TWinkelVektor = New TWinkelVektor
NeuerWinkelVektor.NeuerAnker(Anker)
NeuerWinkelVektor.NeuerWinkel(Winkel)
NeuerWinkelVektor.NeuerBetrag(Betrag)
Return NeuerWinkelVektor
End Function

'Es folgen die klasseninternen Prozeduren:

Method NeuerAnker(A:Int[])
Anker[0] = A[0]
Anker[1] = A[1]
End Method

Method NeuerWinkel(W:Float)
Winkel = W
End Method

Method NeuerBetrag(B:Float)
Betrag = B
End Method

'Diese wichtige Prozedur kommt hinzu und berechnet Winkel und Betrag aus einem Punkt, mit dem der Anker verbunden werden soll:
Method VerbindeMit( Punkt_X:Int, Punkt_Y:Int )
Betrag = Sqr( (Anker[0]-Punkt_X)^2 + (Anker[1]-Punkt_Y)^2 ) 'sieh' da: Pythagoras!
Winkel = ATan2( Punkt_Y - Anker[1], Punkt_X - Anker[0] ) 'ein Hoch auf den Erfinder der ATan2-Funktion! (Siehe BPS#3)
End Method

Method Zeichnen(Rot:Int, Gruen:Int, Blau:Int) 'Rot-Gruen-Blau-Werte fuer die Farbe des Vektors
SetColor Rot, Gruen, Blau
DrawLine Anker[0], Anker[1], Anker[0] + Betrag * Cos(Winkel), Anker[1] + Betrag * Sin(Winkel)
'siehe Trigonometrie 10.Klasse, wobei der Unterschied zur deutschen Schulmathematik darin besteht,
'dass in der zweiten y-Koordinate + Betrag * Sin() statt, wie ueblich, - Betrag ' Sin() steht.
'Der Grund dafuer liegt im "verkehrten" Koordinatensystem des Bildschirms, bei der y = 0 oben statt unten liegt.
End Method

Method ErrechneSchnittpunkt:Float[](AndererVektor:TWinkelVektor)

'Einige Sonderfaelle muessen davor ausgeschlossen werden, z.B. reine Nullvektoren ohne Betrag und daher auch ohne Schnittpunkt:
If Betrag = 0 Or AndererVektor.Betrag = 0 Then Return Null

'Um ausschliesslich Winkel zwischen 0° und 360° zu untersuchen, normieren wir erst die Winkel:
Winkel = Winkel Mod 360
If Winkel < 0 Then Winkel:+360
AndererVektor.Winkel = AndererVektor.Winkel Mod 360
If AndererVektor.Winkel < 0 Then AndererVektor.Winkel:+360
'Parallele Winkelvektoren schneiden sich nicht:
If Abs(Winkel - AndererVektor.Winkel) Mod 180 = 0 Then Return Null
'(Der Sonderfall des Sonderfalls, dass zwei Vektoren bei gleichem Ankervektor aufeinander liegen, also unendlich viele gemeinsame Punkte besitzen, sei hier ignoriert)

'Ansonsten muss es wieder einen Schnittpunkt geben. Die mathematische Herleitung auch dieser Formel wuerde ebenso den Rahmen sprengen.
Local SchnittBetrag:Float[2] 'bilden die zu berechnenden Variablen, es folgen die entsprechenden Umformungen aus der Gleichsetzung Vektor = AndererVektor
SchnittBetrag[1] = ( Anker[1] - AndererVektor.Anker[1] + Tan(Winkel) * (AndererVektor.Anker[0] - Anker[0]) ) / ( Sin(AndererVektor.Winkel) - Tan(Winkel) * Cos(AndererVektor.Winkel) )
If Cos(Winkel) <> 0 Then
SchnittBetrag[0] = ( AndererVektor.Anker[0] - Anker[0] + SchnittBetrag[1] * Cos(AndererVektor.Winkel) ) / Cos(Winkel)
Else
SchnittBetrag[0] = ( AndererVektor.Anker[1] - Anker[1] + SchnittBetrag[1] * Sin(AndererVektor.Winkel) ) / Sin(Winkel)
End If

'Im letzten Schritt muss noch ueber einen Betragvergleich geprueft werden, ob der potentielle Geradenschnittpunkt nicht etwa ausserhalb der Vektorlaengen liegt:
If SchnittBetrag[0] < 0 Or SchnittBetrag[1] < 0 Then Return Null
If SchnittBetrag[0] > Betrag Or SchnittBetrag[1] > AndererVektor.Betrag Then Return Null

'Ansonsten werden endlich die Koordinaten des Schnittpunkts zurueckgegeben:
Return [ Anker[0] + Float(SchnittBetrag[0] * Cos(Winkel)), Anker[1] + Float(SchnittBetrag[0] * Sin(Winkel)) ]

End Method

End Type

Die Vektoren meiner Beispiele sind zweidimensional. Die analoge Erweiterung ins Dreidimensionale lässt sich leicht umsetzen und wurde nur deswegen weggelassen, weil allein das Darstellen von Geraden im Raum ein neues Problem birgt. Kennt diesbezüglich jemand ein schnelles und unkompliziertes Verfahren, das auch noch einigermaßen ansprechend aussieht? Das wäre schön.

blackgecko

BeitragFr, März 18, 2011 18:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich musste natürlich gleich mal wieder groß mit OOP loslegen - das macht Spaß Very Happy
Ausgangspunkt ist die Klasse TVector, die eine abstrakte Methode update() hat. Die wird dann von den abgeleiteten Klassen TMouseVector, T100PxVector und TOrthoVector implementiert. Sie hat die Aufgabe, X- und Y-Richtung des Vektors zu aktualisieren.
TMouseVector macht das ganz einfach: Richtung = Zielpunkt - Startpunkt.
T100PxVector berechnet zuerst den Mausvektor, errechnet, mit was multipliziert werden muss, damit die 100 Pixel stimmen und multipliziert schließlich noch beide Koordinaten mit -1.
TOrthoVector berechnet den Mausvektor, vertauscht X- und Y-Koordinate und multipliziert die X-Koordinate mit 1/2 und die Y-Koordinate mit -1/2.
So, und jetzt Code!

BlitzMax: [AUSKLAPPEN]
SuperStrict

'Definition des Mittelpunkts
Const CENTER_X:Int = 320
Const CENTER_Y:Int = 240


Type TVector 'Basis-Vektor-Klasse
Global vectors:TList = New TList 'eine Liste für ALLE Vektoren
Field x:Int 'x- und
Field y:Int 'y-Richtung des Vektors
Field red:Int
Field green:Int
Field blue:Int 'Farbe, damit man auch was sieht Wink
Function updateAll() 'alle Vektoren updaten
For Local i:TVector = EachIn vectors
i.update()
Next
EndFunction
Function drawAll() 'alle Vektoren zeichnen
For Local i:TVector = EachIn vectors
i.draw()
Next
EndFunction
Method New()
red = Rand(0,255)
green = Rand(0,255)
blue = Rand(0,255)
vectors.addlast(Self)
EndMethod
Method update() Abstract '<= Das ist der eigentliche Kern des Ganzen
Method draw(xfrom:Int=CENTER_X,yfrom:Int=CENTER_Y)
SetColor red,green,blue
DrawLine xfrom,yfrom,xfrom+x,yfrom+y
EndMethod
EndType

Type TMouseVector Extends TVector 'Der Mausvektor
Method update()
x = MouseX() - CENTER_X 'Richtung = Zielpunkt - Startpunkt
y = MouseY() - CENTER_Y 'Das war noch einfach
EndMethod
EndType

Type T100PxVector Extends TVector 'Der 100-Pixel-Vektor
Method update()
Local mx:Int = MouseX() - CENTER_X 'Wie lang
Local my:Int = MouseY() - CENTER_Y 'ist der
Local ml:Float = Sqr(mx^2+my^2) 'Mausvektor?

Local n:Float = 100 / ml 'Um welchen Faktor kleiner sind die 100 Pixel?

x = -n * mx 'Damit multiplizieren wir den Mausvektor
y = -n * my 'Und damit er in die andere Richtung zeigt kommt noch ein Minus davor
EndMethod
EndType

Type TOrthoVector Extends TVector 'Der senkrechte Vektor
Method update()
Local mx:Int = MouseX() - CENTER_X 'Wie sieht der
Local my:Int = MouseY() - CENTER_Y 'Mausvektor aus?

x = -0.5*my 'x- und y-Richtung vertauschen und eins von beiden negieren -> senkrechter Vektor
y = 0.5*mx 'multipliziert mit 0.5 -> halb so langer Vektor
EndMethod
EndType



Graphics 640,480,0
SeedRnd MilliSecs()

'Erstellen der drei Vektoren
New TMouseVector
New T100PxVector
New TOrthoVector

Local tim:TTimer = TTimer.Create(40)
Repeat
tim.wait()
Cls
TVector.updateAll()
TVector.drawAll()
Flip
Until KeyHit(KEY_ESCAPE) Or AppTerminate()
So long and thanks for all the fish.
Fedora 17 | Windows 7 || BlitzPlus | BlitzMax
Rechtschreibflame GO!!! Deppenapostroph | SeidSeit | Deppenakzent | DassDas | Deppenleerzeichen | TodTot | enzigste.info - Ja, ich sammel die.

Xeres

Moderator

BeitragSo, März 20, 2011 21:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke euch beiden für die Teilname! Vielleicht kommt mit der Zeit ja noch was dazu; Fragen & Anregungen sind und bleiben erwünscht.

Die Musterlösung findet sich im Eingangspost.
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
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group