Physik[B2D] Kollision

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

ToeB

Betreff: Physik[B2D] Kollision

BeitragMi, Jan 07, 2009 18:31
Antworten mit Zitat
Benutzer-Profile anzeigen
So ich hab nach dem Tutorial von Noobody über Verlet-Physik habe ich mir gedacht mache ich mal sowas. Natürlich habe ich größtenteils das beispiel übernommen, da ich mit der mathemathik nicht so klar komme. Jetzt wollte ich mich mal an kollisionen versuchen. Das klappt auch, nur das wenn die objecte kollidieren dann einfach stehenbleiben(auch mitten in der Luft)

Was muss ich ändern ?

Code: [AUSKLAPPEN]
Graphics 800,600,16,2
SetBuffer BackBuffer()

Type vp_point
   Field x_pos#
   Field y_pos#
   
   Field x_old_pos#
   Field y_old_pos#
   
   Field x_speed#
   Field y_speed#

End Type

Type vp_line
   Field p1.vp_point
   Field p2.vp_point
   
   Field size
End Type

Const GRAVITY_X# = 0
Const GRAVITY_Y# = 0.1
Global VP_LoopTime = 1
Global GetPoint = 0,GetPointID.vp_point
Global Winkel_ab# = 3
Global Winkel_def# = 360 / Winkel_ab#
Global Radius# = 20
Dim Winkel.vp_point(Winkel_ab)

Repeat
   If MouseHit(1)
      MX# = MouseX()
      MY# = MouseY()
      ;Winkel(0) = VP_AddPoint(MX,MY)       
      ;For i = 1 To Winkel_AB
      ;   w# = i * Winkel_def
      ;   Winkel(i) = VP_AddPoint(MX-Cos(w#)*Radius,My-Sin(w#)*Radius)
      ;   VP_AddLine(Winkel(0),Winkel(i))
      ;Next
      ;For i = 1 To Winkel_AB
      ;   If i < Winkel_AB
      ;      VP_AddLine(Winkel(i),Winkel(i+1))
      ;   Else
      ;      VP_AddLine(Winkel(i),Winkel(1))
      ;   EndIf
      ;Next
      v0.vp_point = VP_AddPoint(MX,MY-Radius)
      v1.vp_point = VP_AddPoint(MX+Radius,MY+Radius)
      v2.vp_point = VP_AddPoint(MX-Radius,MY+Radius)
      VP_AddLine(v0,v1)         
      VP_AddLine(v1,v2)         
      VP_AddLine(v2,v0)                  
   EndIf
   If MouseHit(2) And GetPoint = 0
      GetPointID.vp_point = VP_NextPoint(MouseX(),MouseY())
      GetPoint = 1
   EndIf
   If GetPoint = 1
      If MouseDown(2) = 0 GetPoint = 0
      If GetPointID <> Null
         GetPointID\x_pos = MouseX()
         GetPointID\y_pos = MouseY()
      EndIf
   EndIf        
   VP_UpdateVP(50)
   Cls
   VP_DrawDebug()
   Flip
Until KeyHit(1)
End

Function VP_AddPoint.vp_point(x_pos#,y_pos#,gew#=1)
   vp.vp_point = New vp_point
   vp\x_pos = x_pos
   vp\y_pos = y_pos
   vp\x_old_pos = x_pos
   vp\y_old_pos = y_pos
   vp\x_speed = GRAVITY_X#
   vp\y_speed = GRAVITY_Y# * gew#
   
   Return vp
End Function

Function VP_AddLine.vp_line(p1.vp_point,p2.vp_point)
   If p1 <> p2
      vp.vp_line = New vp_line
      vp\p1 = p1
      vp\p2 = p2
      vp\size = Sqr( ( vp\p1\x_pos - vp\p2\x_pos ) ^ 2 + ( vp\p1\y_pos - vp\p2\y_pos ) ^ 2 )
      Return vp
   EndIf
End Function 


Function VP_UpdateVP(Update=1)   
   For vp.vp_point = Each vp_point
      OldX# = vp\x_pos
      OldY# = vp\y_pos
      vp\x_pos = vp\x_pos + (vp\x_pos - vp\x_old_pos) + vp\x_speed * VP_LoopTime^2
      vp\y_pos = vp\y_pos + (vp\y_pos - vp\y_old_pos) + vp\y_speed * VP_LoopTime^2
      vp\x_old_pos = OldX
      vp\y_old_pos = OldY
   Next
   For i = 1 To Update
      For vp3.vp_point = Each vp_point
         vp3\x_pos = Min( Max( vp3\x_pos, 0), 799 )
         vp3\y_pos = Min( Max( vp3\y_pos, 0), 599 )
         For l.vp_line = Each vp_line
            If l\p1 <> vp3 And l\p2 <> vp3 Then
               If PointLineCol(l\p1\x_pos,l\p1\y_pos,l\p2\x_pos,l\p2\y_pos,vp3\x_pos,vp3\y_pos,10)
                  vp3\x_pos = vp3\x_old_pos
                  vp3\y_pos = vp3\y_old_pos                                 
               EndIf                      
            EndIf
         Next
      Next       
      For vp2.vp_line = Each vp_line
         DeltaX# = vp2\p2\x_pos-vp2\p1\x_pos
         DeltaY# = vp2\p2\y_pos-vp2\p1\y_pos
         DeltaL# = Sqr( DeltaX#^2  + DeltaY^2 )
         Diff# = ( DeltaL# - vp2\size ) / DeltaL
         vp2\p1\x_pos# = vp2\p1\x_pos + DeltaX#*0.5*Diff#
         vp2\p1\y_pos# = vp2\p1\y_pos + DeltaY#*0.5*Diff#
         vp2\p2\x_pos# = vp2\p2\x_pos - DeltaX#*0.5*Diff#
         vp2\p2\y_pos# = vp2\p2\y_pos - DeltaY#*0.5*Diff#
         For vp4.vp_point = Each vp_point
            If vp2\p1 <> vp4 And vp2\p2 <> vp4
               leng=PointLineCol(vp2\p1\x_pos,vp2\p1\y_pos,vp2\p2\x_pos,vp2\p2\y_pos,vp4\x_pos,vp4\y_pos,10)
               If leng Then
                  maxr=PointLineCol(vp2\p1\x_pos,vp2\p1\y_pos,vp2\p2\x_pos,vp2\p2\y_pos,vp4\x_pos,vp4\y_pos,10,1)/2
                  If leng < maxr
                     vp2\p2\x_pos = vp2\p2\x_old_pos
                     vp2\p2\y_pos = vp2\p2\y_old_pos                     
                  ElseIf leng => maxr   
                     vp2\p1\x_pos = vp2\p1\x_old_pos
                     vp2\p1\y_pos = vp2\p1\y_old_pos                     
                  EndIf
               EndIf
            EndIf
         Next
         ;For vp4.vp_line = Each vp_line
         ;   p_1.vp_point = vp4\p1
         ;   p_2.vp_point = vp4\p2
         ;   If p_1 <> vp2\p1 And p_1 <> vp2\p2 And p_2 <> vp2\p1 And p_2 <> vp2\p2
         ;      If Line_Intersect(vp2\p1\x_pos,vp2\p1\y_pos,vp2\p2\x_pos,vp2\p2\y_pos, vp4\p1\x_pos,vp4\p1\y_pos,vp4\p2\x_pos,vp4\p2\y_pos)
         ;         vp2\p1\x_old_pos = vp2\p1\x_pos 
         ;         vp2\p2\x_old_pos = vp2\p2\x_pos 
         ;         vp4\p1\x_old_pos = vp4\p1\x_pos 
         ;         vp4\p2\x_old_pos = vp4\p2\x_pos 
         ;         vp2\p1\y_old_pos = vp2\p1\y_pos 
         ;         vp2\p2\y_old_pos = vp2\p2\y_pos 
         ;         vp4\p1\y_old_pos = vp4\p1\y_pos 
         ;         vp4\p2\y_old_pos = vp4\p2\y_pos 
         ;      EndIf
         ;   EndIf
         ;Next
      Next
   Next
End Function

Function VP_DrawDebug(Buffer=0)
   If Buffer = 0 Buffer = BackBuffer()
   Color 255,0,0
   LockBuffer Buffer
   For vp2.vp_line = Each vp_line
      Line vp2\p1\x_pos,vp2\p1\y_pos,vp2\p2\x_pos,vp2\p2\y_pos
   Next
   For vp.vp_point = Each vp_point
      WritePixel(vp\x_pos,vp\y_pos,$FFFFFF)
   Next   
   UnlockBuffer Buffer
End Function 

Function VP_NextPoint.vp_point(x_pos#,y_pos#)
   Local MaxL# = 100000
   Local vpmin.vp_point
   For vp.vp_point = Each vp_point
      Lo# = Sqr( ( vp\x_pos - x_pos )*( vp\x_pos - x_pos) +  ( vp\y_pos - y_pos )*( vp\y_pos - y_pos ) )
      If Lo < MaxL Then MaxL = Lo : vpmin.vp_point = vp.vp_point
   Next 
   Return vpmin.vp_point
End Function

Function Min#( A#, B# ) ;Minimum aus zwei Werten zurückliefern
   If A# < B# Then Return A# Else Return B#
End Function

Function Max#( A#, B# ) ;Maximum aus zwei Werten zurückliefern
   If A# > B# Then Return A# Else Return B#
End Function


Function Line_intersect(x1#,y1#,x2#,y2#, x3#,y3#,x4#,y4#)
   ;Steigung ausrechnen
   m1# = (y1#-y2#)/(x1#-x2#)
   m2# = (y3#-y4#)/(x3#-x4#)
   
   ;Y-Achsen Abschnitt ausrechnen
   b1# = y1# - m1#*x1#
   b2# = y3# - m2#*x3#
   
   
   ;Term umformen
   x# = (b2# - b1#) / (m1# - m2#)
   y# = x# * m1# + b1#
   
   ;schauen, ob der Punkt auf einer Linie liegt
   abstand# = Abs (x1#-x2#)
   If Abs (x#-x1#) <= abstand # Then
      If Abs (x#-x2#) <= abstand # Then
         
         abstand# = Abs (y1#-y2#)
         If Abs (y#-y1#) <= abstand # Then
            If Abs (y#-y2#) <= abstand # Then
         
               abstand# = Abs (x3#-x4#)
               If Abs (x#-x3#) <= abstand # Then
                  If Abs (x#-x4#) <= abstand # Then
                     
                     abstand# = Abs (y3#-y4#)
                     If Abs (y#-y3#) <= abstand # Then
                        If Abs (y#-y4#) <= abstand # Then
                           
                           Return 1
                           
                           
                        EndIf
                     EndIf
                  EndIf
               EndIf
            EndIf
         EndIf
      EndIf
   EndIf
End Function

Function PointLineCol(x1,y1,x2,y2,px,py,rad=1,mo=0)
   If mo = 0
      rad1 = Sqr( ( x1 - x2 )*( x1 - x2) +  ( y1 - y2 )*( y1 - y2 ) )
      rad2 = Sqr( ( x2 - px )*( x2 - px) +  ( y2 - py )*( y2 - py ) )
      If rad2 <= rad1
         w1 = ATan2(x1-x2,y1-y2)
         w2 = ATan2(px-x2,py-y2)
         If w2 > w1-rad And w2 < w1+rad
            Return rad2
         EndIf
      EndIf
   Else
      Return Sqr( ( x1 - x2 )*( x1 - x2) +  ( y1 - y2 )*( y1 - y2 ) )
   EndIf
End Function


Die Functionen für Kollision stimmen soweit, daran kann nicht liegen, liegt ja auch an den variablen x_pos/y_pos und x_old_pos/y_old_pos (in den Types vp_point)

Wisst ihr wie ichs machen muss ?

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Goodjee

BeitragMi, Jan 07, 2009 18:46
Antworten mit Zitat
Benutzer-Profile anzeigen
ich würde eher den vektor der alten zur neuen position mit allen anderen linien checken
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

ToeB

BeitragMi, Jan 07, 2009 19:38
Antworten mit Zitat
Benutzer-Profile anzeigen
wie meinst du das ? Kannsts du mir bidde erklären ?

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Goodjee

BeitragMi, Jan 07, 2009 19:52
Antworten mit Zitat
Benutzer-Profile anzeigen
du hast ja deine ganzen kanten von deinen kisten oder was auch immer
weiterhin hast du einen vertex einer kiste, die grade mir 20px/frame fällt
dann kannst du ja die linie von vertex\x,vertex\y,vertex\x+20,vertex\y mit allen anderen kanten checken und so schnittpunkte finden, an den schnittpunkten sind sie kollidiert, dann kannst du zum beispiel die fallende kiste wieder soweit zurückschieben dass sie sich perfekt anschmiegt und abbremsen
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

ToeB

BeitragMi, Jan 07, 2009 20:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke ! So wollt ichs jetzt eigl. machen mit der Line_intersect function (liegt bei glaub ich beim code oben). Jetzt bräuchte ich nur noch den wert WO die linien sich schneiden (also den X/Y wert wo die aufeinader treffen) dann kann ich nämlich rechen wo ich das teil hin zurück setzt muss...


Kann man das damit machen oder müsste ich mir ne seperate funtction schreiben ?

mfg ToeB

Edit : Habs jetzt erstmal so gelöst :
Code: [AUSKLAPPEN]
Function VP_UpdateVP(Update=1)   
   For vp.vp_point = Each vp_point
      OldX# = vp\x_pos
      OldY# = vp\y_pos
      vp\x_pos = vp\x_pos + (vp\x_pos - vp\x_old_pos) + vp\x_speed * VP_LoopTime^2
      vp\y_pos = vp\y_pos + (vp\y_pos - vp\y_old_pos) + vp\y_speed * VP_LoopTime^2
      vp\x_old_pos = OldX
      vp\y_old_pos = OldY
      DeltaX# = vp\x_pos - vp\x_old_pos
      DeltaY# = vp\y_pos - vp\y_old_pos
      For l.vp_line = Each vp_line
         If l\p1 <> vp And l\p2 <> vp
            If Line_Intersect(l\p1\x_pos,l\p1\y_pos,l\p2\x_pos,l\p2\y_pos,vp\x_pos,vp\y_pos,vp\x_pos+DeltaX,vp\y_pos+DeltaY)
               vp\x_pos = vp\x_old_pos-DeltaX
               vp\y_pos = vp\y_old_pos-DeltaY
               vp\x_old_pos = vp\x_pos
               vp\y_old_pos = vp\y_pos               
            EndIf
         EndIf
      Next    
   Next
   For i = 1 To Update
      For vp3.vp_point = Each vp_point
         vp3\x_pos = Min( Max( vp3\x_pos, 0), 799 )
         vp3\y_pos = Min( Max( vp3\y_pos, 0), 599 )         
      Next       
      For vp2.vp_line = Each vp_line
         DeltaX# = vp2\p2\x_pos-vp2\p1\x_pos
         DeltaY# = vp2\p2\y_pos-vp2\p1\y_pos
         DeltaL# = Sqr( DeltaX#^2  + DeltaY^2 )
         Diff# = ( DeltaL# - vp2\size ) / DeltaL
         vp2\p1\x_pos# = vp2\p1\x_pos + DeltaX#*0.5*Diff#
         vp2\p1\y_pos# = vp2\p1\y_pos + DeltaY#*0.5*Diff#
         vp2\p2\x_pos# = vp2\p2\x_pos - DeltaX#*0.5*Diff#
         vp2\p2\y_pos# = vp2\p2\y_pos - DeltaY#*0.5*Diff#         
      Next
   Next
End Function


Funtz aber auch nur sehr stark begrentz...

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group