Veränderte Variablen=Gleiches Ergebnis???

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

funkmaster5000

Betreff: Veränderte Variablen=Gleiches Ergebnis???

BeitragDo, Sep 20, 2012 21:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi Alle!

Also im Moment verzweifel ich fast. Ich will eine Kollisionsabfrage machen, auf der Basis von f(x)=mx+b. Die Formeln und das Umstellen klappen einwandfrei. Jetzt soll sich natürlich die Linie, die abgefragt wird, bewegen (wär sonst schwer für eine Kollisionsabfrage zu gebrauchen). Ich benutze eine Function, um die benötigten Werte auszurechnen. Verändere ich allerdings die Variablen in meinem "Repeat" Block, ändert sich nicht das Rechenergebnis. Da wird doch was nicht stimmen...Ich hab bestimmt wieder was doofes übersehen. Danke im Voraus!

Code: [AUSKLAPPEN]
Graphics 640,480
SetBuffer BackBuffer()

x1#=100 ;Startpunkt Linie 1 x1
y1#=310 ;Startpunkt Linie 1 y1
x2#=170 ;Startpunkt Linie 1 x2
y2#=500 ;Startpunkt Linie 1 y2

x3#=150 ;Startpunkt Linie 2 x1
y3#=400 ;Startpunkt Linie 2 y1
x4#=100 ;Startpunkt Linie 2 x2
y4#=420 ;Startpunkt Linie 2 y2

m1#=(y2#-y1#)/(x2#-x1#) ;m für Linie 1 ausrechnen
b1#=y1#-(m1#*x1#) ;b für Linie 1 ausrechnen

m2#=(y4#-y3#)/(x4#-x3#) ;m für Linie 2 ausrechnen
b2#=y3#-(m2#*x3#) ;b für Linie 2 ausrechnen

x#=(b2#-b1#)/(m1#-m2#) ;X-Position des Schnittpunkts
playerspeed#=2   ;Verschiebung der Linie

Repeat
   Cls ;Clear Screen

      If KeyDown(205) Then
         x3#=x3#+playerspeed#
         x4#=x4#+playerspeed#
      End If

      If KeyDown(203) Then
         x3#=x3#-playerspeed#
         x4#=x4#-playerspeed#
      End If


      If KeyDown(200) Then
         y3#=y3#-playerspeed#
         y4#=y4#-playerspeed#
      End If

      If KeyDown(208) Then
         y3#=y3#+playerspeed#
         y4#=y4#+playerspeed#
      End If


      a#=mtwo#(y4#,y3#,x4#,x3#) ;Function aufrufen, um m zu aktualisieren
               
               Text 0,10,a#
      
                If m1#-a#=0 Then ;Ist m1#-a# = 0, dann   
         Text 0,0,"Kein Schnittpunkt!"
      End If


   Line x1#,y1#,x2#,y2#
   Line x3#,y3#,x4#,y4#
   Flip
Until KeyHit(1)

Function mtwo#(y4#,y3#,x4#,x3#)
   m2# = (y4#-y3#)/(x4#-x3#)
   Return m2#
End Function

Xeres

Moderator

BeitragDo, Sep 20, 2012 21:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Das hier wird nie funktionieren: m1# - a# = 0
Das sich die Floats 100% auf exakt null addieren ist so ziemlich ausgeschlossen. Das müsstest du vermutlich nach Int casten oder mit > oder < abfragen. Float und genau gleich ist aber wie gesagt sehr unwahrscheinlich.
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)

BlitzMoritz

BeitragDo, Sep 20, 2012 21:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Was meinst du mit "ändert sich nicht das Rechenergebnis"? Vielleicht die -0,4, die du dir anzeigen lässt?
Die kann sich ja nicht ändern, weil es die Steigung deiner zweiten Gerade ist, die ja gerade deswegen immer gleich bleibt, weil du stets BEIDE Koordinaten x3 und x4 bzw. y3 und y4 schön gleichmäßig bewegst. Wenn du z.B. nur einen der zwei Punkte bewegst, ändert sich auch die Steigung.
Übrigens - falls du dich an der Schulmathematik orientierst - das Vorzeichen der Steigung ist umgekehrt, weil die "y-Achse" statt unten oben hängt. Was bei dir wie m = 0.4 "aussieht", ist daher eigentlich -0.4
Evtl. ist dies oder jenes für dich interessant.
 

funkmaster5000

BeitragDo, Sep 20, 2012 22:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja ich habe mir ein bisschen Schulmathe reingezogen, danke für die Links, ich werde sie durcharbeiten! Mein Ansatz scheint ja sowieso nicht zu klappen. m1#-m2# bleibt ja dementsprechend gleich. Also schneiden sich die Linien immer.

EDIT: Also sind für eine Linienkollision Vektoren angesagt?

Chester

BeitragFr, Sep 21, 2012 20:43
Antworten mit Zitat
Benutzer-Profile anzeigen
In dem Fall ist es so wie du es machst, ziemlich sinnlos.

Du gehst in deiner Überlegung nämlich nicht von Strecken, sondern von Geraden aus, bei denen abgesehen bei gleicher Steigung (m1-m2=0) es immer einen Schnittpunkt geben wird. Insofern bringt es auch nichts, hier die Gerade rumzuschieben und dann die Steigung neuzuberechnen. Die bleibt nämlich sofern du die Gerade nicht drehst, unverändert. Es ändert sich lediglich der Achsenabschnitt.

Wobei die Idee mit der Steigung aber gar nicht mal so schlecht ist.

Wenn das eben gesagte(m1-m2=0) nicht gilt, dann muss es einen Schnittpunkt geben. Den kannst du ja, wenn du die Geraden als Funktionen beschreibst, durch gleichsetzen (physikalisch betracht zeitlichen Abhängigkeit/geometrisch X-Achsenabschnitt) berechnen, also:

Code: [AUSKLAPPEN]
Achsenabschnitt1 + t*Steigung1 = Achsenabschnitt2 + t*Steigung2
t*(Steigung1-Steigung2) = Achsenabschnitt2 - Achsenabschnitt1
t=(Achsenabschnitt2 - Achsenabschnitt1)/(Steigung1-Steigung2)


Wenn du diese Variable berechnet hast, kannst du durch Einsetzen in die Gleichung einer der beiden Geraden den Schnittpunkt auusrechnen. Dann musst du nur noch schauen, ob der Schnittpunkt auch innerhalb der Grenzen der Strecken liegt. Das geht ganz einfach, indem du schaust ob der Schnittpunkt innerhalb der Fläche, die - mathematisch ausgedrückt - von Achsenparallelen die Start- und Endpunkt schneiden aufgespannt wird, liegt. Diese Vereifachung ist deshalb richtig, weil innerhalb dieser Quadrate jeder Punkt eindeutig definiert ist und somit automatisch auf der Strecke liegen muss. (Da könnte man RectsOverlap zweckentfremden).

Ich bastel mal nen kleinen Beispielcode Wink


Edit:

Ich habe mal versucht, es mithilfe von Types ein wenig anschaulich umzusetzen, ich hoffe das verwirrt dich nicht.

Nach obiger Gleichung kann man für für den Schnittpunkt ausrechnen:
BlitzBasic: [AUSKLAPPEN]
t# = (Linie2\Achsenabschnitt - Linie1\Achsenabschnitt)/(Linie1\Steigung-Linie2\Steigung)


Mithilfe dieser Variable lassen sich nun die Koordinaten des Schnittpunktes berechnen:
BlitzBasic: [AUSKLAPPEN]
Schnittpunkt\X = t
Schnittpunkt\Y = Linie2\Steigung*t + Linie2\Achsenabschnitt#


Jetzt muss man schauen, ob der Punkt innerhalb der erwähnten Flächen liegt. Da RectsOverlap leider nicht mit negativen Breiten/Höhen arbeiten kann, kann man die Rechtecke nicht einfach mit Start-/Endpunkt der Linien berechnen. Hier muss man die Rechtecke manuell anpassen, so dass die Breite/Höhe immer positiv ist. Dafür habe ich eine Funktion geschrieben (siehe unten). RectsOverlap kann man dann benutzen, indem man für den Schnittpunkt von einem Rechteck mit der Breite/Höhe = 1 Pixel ausgeht:
Dann kann man es ganz einfach verwenden:
BlitzBasic: [AUSKLAPPEN]
RectsOverlap( Linie\RectStart\X, ... , ..., ... ,    Schnittpunkt\X,Schnittpunkt\Y, 1 , 1 )


Wenn nun für beide Rechtecke eine Kollision vorliegt, dann liegt der Schnittpunkt auf der Strecke.

Hier das Gesamtbeispiel:
BlitzBasic: [AUSKLAPPEN]
Const CPlayerspeed=2  
Graphics 800,600,32,2

SetBuffer BackBuffer()


Global ConstLinie.TLine = NewLine(200,200,70,470)
Global PlayerLinie.TLine = NewLine(50,50,70,100)


Repeat
Cls


Control() ; Tastatureingabe
DrawLines() ; Zeichnung der Linien und Neuberechnung Achsenabschnitt

Text 0,10, "Schnittpunkt auf Strecken: "+Schnittpunkt(ConstLinie, PlayerLinie)

Flip
Until KeyHit(1)



Function Schnittpunkt(Linie1.TLine, Linie2.TLine)

; Im Fall parallel oder identisch abbrechen, sonst gibts ne Division durch Null - dürfte dank Float eigentlich nie vorkommen
If Linie1\Steigung-Linie2\Steigung = 0 Then Return 42

; Schnittpunkt
Local t# = (Linie2\Achsenabschnitt - Linie1\Achsenabschnitt)/(Linie1\Steigung-Linie2\Steigung)

Local Schnittpunkt.TKoord = New TKoord
; Koordinaten Schnittpunkt
Schnittpunkt\X = t
Schnittpunkt\Y = Linie2\Steigung*t + Linie2\Achsenabschnitt#

; Schnittpunkt als Rect einzeichnen
Color 255,0,0
Rect Schnittpunkt\X-2,Schnittpunkt\Y-2,4,4,1

; Debug
Color 255,255,255
Text 0,50, "Schnittpunkt X: "+Schnittpunkt\X
Text 0,65, "Schnittpunkt Y: "+Schnittpunkt\Y

; Rechtecke aus Linienkoordinaten berechnen
CalcLineRect(Linie1)
CalcLineRect(Linie2)

; Abfragen ob Schnittpunkte in Rechtecke liegt
If RectsOverlap(Linie1\RectStart\X,Linie1\RectStart\Y,Linie1\RectEnde\X,Linie1\RectEnde\Y,Schnittpunkt\X,Schnittpunkt\Y,1,1)
If RectsOverlap(Linie2\RectStart\X,Linie2\RectStart\Y,Linie2\RectEnde\X,Linie2\RectEnde\Y,Schnittpunkt\X,Schnittpunkt\Y,1,1)
Delete Schnittpunkt
Return 1
EndIf
EndIf

Return 0
End Function


Function Control()

If KeyDown(205) Then
PlayerLinie\Start\X=PlayerLinie\Start\X + CPlayerspeed
PlayerLinie\Ende\X=PlayerLinie\Ende\X + CPlayerspeed
End If

If KeyDown(203) Then
PlayerLinie\Start\X=PlayerLinie\Start\X - CPlayerspeed
PlayerLinie\Ende\X=PlayerLinie\Ende\X - CPlayerspeed
End If


If KeyDown(200) Then
PlayerLinie\Start\Y=PlayerLinie\Start\Y - CPlayerspeed
PlayerLinie\Ende\Y=PlayerLinie\Ende\Y - CPlayerspeed
End If

If KeyDown(208) Then
PlayerLinie\Start\Y=PlayerLinie\Start\Y + CPlayerspeed
PlayerLinie\Ende\Y=PlayerLinie\Ende\Y + CPlayerspeed
End If
End Function


Type TKoord
Field X#
Field Y#
End Type

Type TLine
Field Start.TKoord
Field Ende.TKoord
Field Steigung#
Field Achsenabschnitt#
Field RectStart.TKoord
Field RectEnde.TKoord
End Type


Function NewLine.TLine(x#,y#,x2#,y2#)
Local Linie.TLine = New TLine

Linie\Start = New TKoord
Linie\Ende = New TKoord

Linie\RectStart = New TKoord
Linie\RectEnde = New TKoord


Linie\Start\X=x
Linie\Ende\X=x2
Linie\Start\Y=y
Linie\Ende\Y=y2


Linie\Steigung#=(Linie\Ende\Y#-Linie\Start\Y#)/(Linie\Ende\X#-Linie\Start\X#)
Return Linie
End Function

Function CalcLineRect(linie.TLine)
If linie\Start\X <= linie\Ende\X Then
linie\RectStart\X=linie\Start\X
linie\RectEnde\X=linie\Ende\X-linie\Start\X
Else
linie\RectEnde\X=linie\Start\X-linie\Ende\X
linie\RectStart\X=linie\Ende\X
EndIf

If linie\Start\Y <= linie\Ende\Y Then
linie\RectStart\Y=linie\Start\Y
linie\RectEnde\Y=linie\Ende\Y-linie\Start\Y
Else
linie\RectEnde\Y=linie\Start\Y-linie\Ende\Y
linie\RectStart\Y=linie\Ende\Y
EndIf
End Function


Function DrawLines()

Local Linie.TLine
For Linie.TLine = Each TLine
Linie\Achsenabschnitt = Linie\Start\Y#-(Linie\Steigung#*Linie\Start\X#)
Color 255,255,255
Line Linie\Start\X#, Linie\Start\Y#,Linie\Ende\X#, Linie\Ende\Y#
;Color 0,100,0
;Rect Linie\RectStart\X,Linie\RectStart\Y,Linie\RectEnde\X,Linie\RectEnde\Y,0
Next
Color 255,255,255
End Function


Bei Fragen immer melden, ich hoffe die Types verwirren dich nicht. Wink

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group