2D Ball Physik ... !?

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

ToeB

Betreff: 2D Ball Physik ... !?

BeitragMo, Jun 29, 2009 21:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ... Ich war heute mal in der stimmung mal was runterfallen zu lassen....

Dazu wollte ich mir eine kleine 2D-Ball-Physik-Engine basteln. Die geht auch schon gut. Bis auf die Kollision. Die funtz zwar, aber der Ball prallt nicht so ab wie ich es haben will. Könnt ihr mir helfen ?

Steuerung :
Rechte Maustaste drücken und gedrückt halten : Ball erstellen
Linke Maustaste drücken und gedrückt halten : Ball auswählen

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

SeedRnd MilliSecs()

Global BGBuffer = BackBuffer()
Global BGSizeX = GraphicsWidth()
Global BGSizeY = GraphicsHeight()

Global GravityX# = 0
Global GravityY# = + 0.5


Type b
   Field size#
   Field x#,y#
   Field sx#,sy#
   Field w#,sw#
   Field col
End Type


Global TB_on,TB_x#,TB_y#,TB_r#,TB_w#
Global MB_on,MB_b.b


Global timer = CreateTimer(60)

;Global Ball1 = AddCircle(400,300,100)

Repeat
   MX = MouseX()
   MY = MouseY()
   SMX# = MouseXSpeed()
   SMY# = MouseYSpeed()
   If MouseHit(1)
      If TB_on = 0
         TB_x = MX
         TB_y = MY
         TB_on = 1      
      EndIf
   EndIf    
   If MouseHit(2)
      For tmp.b = Each b
         mouse_abs = Sqr( (tmp\x-MX)*(tmp\x-MX) + (tmp\y-MY)*(tmp\y-MY) )
         If mouse_abs <= tmp\size
            MB_On = 1
            MB_b = tmp
            Exit
         EndIf
      Next
   EndIf    
   UpdateAll()
   If MB_On = 1
      MB_b\x = MX
      MB_b\y = MY
      If MouseDown(2) = 0
         MB_On = 0
         MB_b\sx = SMX
         MB_b\sy = SMY
      EndIf
   EndIf          
   DrawAll()
   If TB_On = 1
      TB_r = Sqr( (TB_x-MX)*(TB_x-MX) + (TB_y-MY)*(TB_y-MY) )
      TB_w# = ATan2( (MY-TB_y) , (MX-TB_x) )
      Color 0,255,0
      Line TB_x,TB_y,TB_x+Cos(TB_w)*TB_r,TB_y+Sin(TB_w)*TB_r
      Color 0,0,255
      Oval TB_x-TB_r,TB_y-TB_r,TB_r*2,TB_r*2,0
      If MouseDown(1) = 0
         TB_On = 0
         AddCircle(TB_x,TB_y,TB_r,TB_w)
      EndIf
   EndIf
   Flip 0
   Cls
   WaitTimer(timer)
Until KeyHit(1)
End

Function AddCircle(x#,y#,r#,w#=0)
   tmp.b = New b
   tmp\x = x
   tmp\y = y
   tmp\size = r
   tmp\sx = 0
   tmp\sy = 0
   tmp\w = w
   tmp\sw# = Rnd(-2.0,2.0)
   Return Handle(tmp)
End Function

Function UpdateAll()
   For tmp.b = Each b
      ;Bewegung      
      tmp\x# = tmp\x + tmp\sx
      tmp\y# = tmp\y + tmp\sy
      tmp\sx = tmp\sx + GravityX
      tmp\sy = tmp\sy + GravityY
      ;tmp\w = tmp\w + tmp\sw
      
      ;Kollision mit den wänden
      If tmp\x-tmp\size < 0       Then tmp\sx = tmp\sx * -0.5 : tmp\x = tmp\size         
      If tmp\x+tmp\size > BGSizeX Then tmp\sx = tmp\sx * -0.5 : tmp\x = BGSizeX-tmp\size
      ;If tmp\y-tmp\size < 0       Then tmp\sy = tmp\sy * -0.5 : tmp\y = tmp\size         
      If tmp\y+tmp\size > BGSizeY Then tmp\sy = tmp\sy * -0.5 : tmp\y = BGSizeY-tmp\size
   
      ;Kollision mit anderen bällen
      For b.b = Each b
         If b <> tmp
            If RectsOverlap(tmp\x-tmp\size,tmp\y-tmp\size,tmp\size*2,tmp\size*2,b\x-b\size,b\y-b\size,b\size*2,b\size*2) Then
               ball_abs_x# = b\x - tmp\x
               ball_abs_y# = b\y - tmp\y
               ball_abs# = Sqr( ball_abs_x*ball_abs_x + ball_abs_y*ball_abs_y )
               ball_rad# = tmp\size + b\size
               If ball_abs < ball_rad
                  ball_winkel# = ATan2( ball_abs_y , ball_abs_x )
                  ball_rad2# = ball_rad - ball_abs
                  ball_speedx1# = tmp\sx * 0.5 + b\sx
                  ball_speedy1# = tmp\sy * 0.5 + b\sy
                  ball_speedx2# =   b\sx * 0.5 + tmp\sx
                  ball_speedy2# =   b\sy * 0.5 + tmp\sy
                  tmp\sx = Cos(ball_winkel+180) * ball_speedx1
                  tmp\sy = Sin(ball_winkel+180) * ball_speedy1
                    b\sx = Cos(ball_winkel    ) * ball_speedx2
                    b\sy = Sin(ball_winkel    ) * ball_speedy2
                  tmp\x = tmp\x + Cos(ball_winkel+180) * ball_rad2
                  tmp\y = tmp\y + Sin(ball_winkel+180) * ball_rad2
                   b\x =  b\x + Cos(ball_winkel    ) * ball_rad2
                   b\y =  b\y + Cos(ball_winkel    ) * ball_rad2
               EndIf
            EndIf
         EndIf
      Next   
      
   Next
End Function


Function DrawAll()
   For tmp.b = Each b
      Color 0,255,0
      Line tmp\x,tmp\y,tmp\x+Cos(tmp\w)*tmp\size,tmp\y+Sin(tmp\w)*tmp\size
      Color 255,0,0
      Oval tmp\x-tmp\size,tmp\y-tmp\size,tmp\size*2,tmp\size*2,0   
      Color 255,255,0
      ;Text tmp\x,tmp\y,tmp\col,1,1   
   Next
End Function


Ich blicks einfach net -.-

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!

PSY

BeitragMo, Jun 29, 2009 23:21
Antworten mit Zitat
Benutzer-Profile anzeigen
hm,

mit rectsoverlap würd ich das nicht machen.

wenn die bälle sich geschnitten haben, liegt keine genaue kollision mehr vor. deshalb müssen die ursprünglichen ballpositionen BEI auftreten der kollision (zurück)gerechnet werden.

pseudocode:
Code: [AUSKLAPPEN]

For b.ball = Each ball
   For b2.ball = Each ball
      If b2.ball <> b.ball
         
         collisionDistance# = b\radius+b2\radius
         actualDistance# = Sqr((c2\x-c\x)^2+(c2\y-c\y)^2)
         
         If actualDistance < collisionDistance Then ; KOLLISION HAT STATTGEFUNDEN
            collNormalAngle#=ATan2(c2\y-c\y, c2\x-c\x) ; WINKEL DER 2 BETROFFENEN BÄLLE ZUEINANDER
            moveDist#=(collisionDistance-actualDistance) ; WIE WEIT SIND DIE BÄLLE SCHON "INEINANDER"?
            
            ; URSPRÜNGLICHE POSITION DER BÄLLE VOR (BEI) KOLLISION BERECHNEN
            c\x=c\x - moveDist*Cos(collNormalAngle)
            c\y=c\y - moveDist*Sin(collNormalAngle)
            c2\x=c2\x + moveDist*Cos(collNormalAngle)
            c2\y=c2\y + moveDist*Sin(collNormalAngle)
         EndIf
      EndIf
   Next
Next


l8er,
psy
PSY LABS Games
Coders don't die, they just gosub without return

ToeB

BeitragDi, Jun 30, 2009 7:24
Antworten mit Zitat
Benutzer-Profile anzeigen
*hust* aber ich glaub genau so habe ich das gemacht Very Happy

Rectsoverlap habe ich nur genommen, damit ich die Bälle vor der Kollision ausschließen kann, die nicht in der nähe sind, damit ich erst bei Rectsoverlap die enfernung berechnen muss... Sonst wäre das allles viel zu lahm...

aber Danek trotzdem Wink

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!

PSY

BeitragDi, Jun 30, 2009 20:01
Antworten mit Zitat
Benutzer-Profile anzeigen
ups, dreck, hab rectsoverlap gelesen und sogleich ging ne warnlampe im zentralhirn an *g*

sorry.

hier mal ein code, der billardbälle simuliert, vllt hilft er dir weiter.

das original ist von phish?...hm ist lange her. war jedenfalls free source!

habs damals teilweise modifiziert und ausserdem die masse komplett aus der berechnung genommen, weil bei meiner simulation alle bälle die gleiche masse haben mussten. kann ich aber wieder einbaun falls es nötig ist.

l8er,
psy

(edit) war klar, vergessen code einzufügen ^^ /selfbonk

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


Type circle
   Field x#, y#      
   Field dx#, dy#      
   Field radius#      
End Type


.Setup
ballTriangleSize=5
For xloop = ballTriangleSize To 1 Step -1
   For yloop = 1 To xloop
      c.circle = New circle
      c\x = (5-xloop)*27 + 200
      c\y = yloop*31-(xloop*31)/2.0 + 300
      c\dx=0
      c\dy=0
      c\radius = 15
   Next
Next


cue.circle = New circle
cue\x = 800
cue\y = 300 +20
cue\dx = -20
cue\dy = Rnd(4)-2
cue\radius = 14


; MAINLOOP
While Not KeyDown(1)
   Cls
   UpdateCirclePhysics()
   RenderCircles()
   Text 10, 10, "Press a mouse button to reset"
   Text 10, 25, "ESC terminates program"
   If GetMouse() Then
      For c.circle = Each circle
         Delete c
      Next
      Goto Setup
   End If
   Flip
Wend
End



Function UpdateCirclePhysics()
   
   
   For c.circle = Each circle
      
      c\x=c\x+c\dx
      c\y=c\y+c\dy
      
      c\dx=c\dx*0.999
      c\dy=c\dy*0.999
      
      
      For c2.circle = Each circle
         
         If c2.circle <> c.circle
         
         collisionDistance# = c\radius+c2\radius
         actualDistance# = Sqr((c2\x-c\x)^2+(c2\y-c\y)^2)
         
         If actualDistance<collisionDistance Then
            
            collNormalAngle#=ATan2(c2\y-c\y, c2\x-c\x)
            
            moveDist#=(collisionDistance-actualDistance)
            
            c\x=c\x - moveDist*Cos(collNormalAngle)
            c\y=c\y - moveDist*Sin(collNormalAngle)
            c2\x=c2\x + moveDist*Cos(collNormalAngle)
            c2\y=c2\y + moveDist*Sin(collNormalAngle)
            
            nX#=Cos(collNormalAngle)
            nY#=Sin(collNormalAngle)
            
            CImpuls#    = c\dx *nX + c\dy *nY
            C2Impuls# = c2\dx *nX + c2\dy *nY
            
            resultierenderImpuls# = CImpuls-C2Impuls
            
            c\dx = c\dx - (resultierenderImpuls*nX) 
            c\dy = c\dy - (resultierenderImpuls*nY)
            
            c2\dx = c2\dx + (resultierenderImpuls*nX)
            c2\dy = c2\dy + (resultierenderImpuls*nY)
         End If
      EndIf
      
      Next
      
      If c\x<c\radius Then
         c\x=c\radius
         c\dx=c\dx*-0.9
      End If
      If c\x>GraphicsWidth()-c\radius Then
         c\x=GraphicsWidth()-c\radius
         c\dx=c\dx*-0.9
      End If
      If c\y<c\radius Then
         c\y=c\radius
         c\dy=c\dy*-0.9
      End If
      If c\y>GraphicsHeight()-c\radius Then
         c\y=GraphicsHeight()-c\radius
         c\dy=c\dy*-0.9
      End If
   Next
End Function


Function RenderCircles()
   For c.circle = Each circle
      If c\radius=15 Then Color 200, 50, 50 Else Color 255, 255, 255
      Oval c\x-c\radius, c\y-c\radius, c\radius*2, c\radius*2
   Next
End Function
PSY LABS Games
Coders don't die, they just gosub without return

ToeB

BeitragDi, Jun 30, 2009 21:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey cool danke !!!

Findet ihr das so realistisch ?

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

SeedRnd MilliSecs()

Global BGBuffer = BackBuffer()
Global BGSizeX = GraphicsWidth()
Global BGSizeY = GraphicsHeight()

Global GravityX# = 0
Global GravityY# = + 0.1


Type b
   Field size#
   Field x#,y#
   Field sx#,sy#
   Field w#,sw#
   Field col
End Type


Global TB_on,TB_x#,TB_y#,TB_r#,TB_w#
Global MB_on,MB_b.b


Global timer = CreateTimer(60)

;Global Ball1 = AddCircle(400,300,100)

Repeat
   MX = MouseX()
   MY = MouseY()
   SMX# = MouseXSpeed()
   SMY# = MouseYSpeed()
   If MouseHit(1)
      If TB_on = 0
         TB_x = MX
         TB_y = MY
         TB_on = 1      
      EndIf
   EndIf    
   If MouseHit(2)
      For tmp.b = Each b
         mouse_abs = Sqr( (tmp\x-MX)*(tmp\x-MX) + (tmp\y-MY)*(tmp\y-MY) )
         If mouse_abs <= tmp\size
            MB_On = 1
            MB_b = tmp
            Exit
         EndIf
      Next
   EndIf    
   UpdateAll()
   If MB_On = 1
      MB_b\x = MX
      MB_b\y = MY
      If MouseDown(2) = 0
         MB_On = 0
         MB_b\sx = SMX
         MB_b\sy = SMY
      EndIf
   EndIf          
   DrawAll()
   If TB_On = 1
      TB_r = Sqr( (TB_x-MX)*(TB_x-MX) + (TB_y-MY)*(TB_y-MY) )
      TB_w# = ATan2( (MY-TB_y) , (MX-TB_x) )
      Color 0,255,0
      Line TB_x,TB_y,TB_x+Cos(TB_w)*TB_r,TB_y+Sin(TB_w)*TB_r
      Color 0,0,255
      Oval TB_x-TB_r,TB_y-TB_r,TB_r*2,TB_r*2,0
      If MouseDown(1) = 0
         TB_On = 0
         AddCircle(TB_x,TB_y,TB_r,TB_w)
      EndIf
   EndIf
   Flip 0
   Cls
   WaitTimer(timer)
Until KeyHit(1)
End

Function AddCircle(x#,y#,r#,w#=0)
   tmp.b = New b
   tmp\x = x
   tmp\y = y
   tmp\size = r
   tmp\sx = 0
   tmp\sy = 0
   tmp\w = w
   tmp\sw# = Rnd(-2.0,2.0)
   Return Handle(tmp)
End Function

Function UpdateAll()
   For tmp.b = Each b
      ;Bewegung      
      tmp\x# = tmp\x + tmp\sx
      tmp\y# = tmp\y + tmp\sy
      tmp\sx = tmp\sx + GravityX
      tmp\sy = tmp\sy + GravityY
      ;tmp\w = tmp\w + tmp\sw   
      
      ;Kollision mit den wänden
      If tmp\x-tmp\size < 0       Then tmp\sx = tmp\sx * -0.5 : tmp\x = tmp\size         
      If tmp\x+tmp\size > BGSizeX Then tmp\sx = tmp\sx * -0.5 : tmp\x = BGSizeX-tmp\size
      ;If tmp\y-tmp\size < 0       Then tmp\sy = tmp\sy * -0.5 : tmp\y = tmp\size         
      If tmp\y+tmp\size > BGSizeY Then tmp\sy = tmp\sy * -0.5 : tmp\y = BGSizeY-tmp\size    
   
      ;Kollision mit anderen bällen
      For b.b = Each b
         If b <> tmp
            If RectsOverlap(tmp\x-tmp\size-50,tmp\y-tmp\size-50,tmp\size*2+100,tmp\size*2+100,b\x-b\size-50,b\y-b\size-50,b\size*2+100,b\size*2+100) Then
               ball_abs_x# = b\x - tmp\x
               ball_abs_y# = b\y - tmp\y
               ball_abs# = Sqr( ball_abs_x*ball_abs_x + ball_abs_y*ball_abs_y )
               ball_rad# = tmp\size + b\size
               If ball_abs < ball_rad
                  ball_winkel# = ATan2( ball_abs_y , ball_abs_x )
                  ball_rad2# = ball_rad - ball_abs +1      
                  nX# = Cos(ball_winkel)
                  nY# = Sin(ball_winkel)         
                  tmp\x = tmp\x - nX * ball_rad2
                  tmp\y = tmp\y - nY * ball_rad2
                    b\x =   b\x + nX * ball_rad2
                    b\y =   b\y + nY * ball_rad2
                  
                  tmp_Impulse# = nX#*tmp\sx + nY#*tmp\sy
                    b_Impulse# = nY#*  b\sx + nY#*  b\sy
                  res_Impulse# = tmp_Impulse - b_Impulse
                  tmp\sx = tmp\sx - res_Impulse * nX
                  tmp\sy = tmp\sy - res_Impulse * nY    
                    b\sx =   b\sx + res_Impulse * nX
                    b\sy =   b\sy + res_Impulse * nY    
               EndIf
            EndIf
         EndIf
      Next
      
      
      
   Next
End Function


Function DrawAll()
   For tmp.b = Each b
      Color 0,255,0
      Line tmp\x,tmp\y,tmp\x+Cos(tmp\w)*tmp\size,tmp\y+Sin(tmp\w)*tmp\size
      Color 255,0,0
      Oval tmp\x-tmp\size,tmp\y-tmp\size,tmp\size*2,tmp\size*2,0   
      Color 255,255,0
      ;Text tmp\x,tmp\y,tmp\col,1,1   
   Next
End Function


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!

Tankbuster

BeitragDi, Jun 30, 2009 21:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Am Anfang sieht das ziemlich gut aus, aber wenn man zuviele Bälle erstellt, prallen alle aneinander ab, und fliegen wie wild durch die Gegend. Außerdem fehlt da sowas wie eine Masse, denn ein kleiner Ball kann einen, der die hälfte des Bildschirms bedeckt ganz einfach in den Orbit schleudern..... Irgnedwie sieht das unlogisch aus.

Und die Bälle Zittern immer, wenn man zuviele davon macht. Also keine ruhige Lage.

Außerdem geht die Performance bei vielen Bällen runter Wink
Twitter
Download Jewel Snake!
Windows|Android

PSY

BeitragDi, Jun 30, 2009 22:11
Antworten mit Zitat
Benutzer-Profile anzeigen
anytime Very Happy

Um die Masse mit zu Berücksichtigen (beim 2D Billard) musst Du folgendes ändern:

1. in den type ein field einfügen (field mass#)

2. Masse bei jedem Ball auch zuweisen Very Happy

3. Mainloop folgendermassen ändern:

Code: [AUSKLAPPEN]
      For c.circle = Each circle
      
      c\x=c\x+c\dx
      c\y=c\y+c\dy
      
      c\dx=c\dx*0.999
      c\dy=c\dy*0.999
      
      For c2.circle = Each circle
         
         If c2.circle <> c.circle
      
            collisionDistance# = c\radius+c2\radius
            actualDistance# = Sqr((c2\x-c\x)^2+(c2\y-c\y)^2)
            
            If actualDistance<collisionDistance Then
            
               collNormalAngle#=ATan2(c2\y-c\y, c2\x-c\x)
               
               moveDist1#=(collisionDistance-actualDistance)*(c2\mass/Float((c\mass+c2\mass)))
               moveDist2#=(collisionDistance-actualDistance)*(c\mass/Float((c\mass+c2\mass)))
               c\x=c\x - moveDist1*Cos(collNormalAngle)
               c\y=c\y - moveDist1*Sin(collNormalAngle)
               c2\x=c2\x + moveDist2*Cos(collNormalAngle)
               c2\y=c2\y + moveDist2*Sin(collNormalAngle)
               
               nX#=Cos(collNormalAngle)
               nY#=Sin(collNormalAngle)
            
               CImpuls#    = c\dx *nX + c\dy *nY
               C2Impuls#    = c2\dx *nX + c2\dy *nY         
         
               resultierenderImpuls# = (2.0*(CImpuls-C2Impuls)) / (c\mass + c2\mass)
               
               c\dx = c\dx - (resultierenderImpuls*c2\mass*nX) 
               c\dy = c\dy - (resultierenderImpuls*c2\mass*nY)
               
               c2\dx = c2\dx + (resultierenderImpuls*c\mass*nX)
               c2\dy = c2\dy + (resultierenderImpuls*c\mass*nY)
               
            End If
         End If

      Next


Sollte so eigentlich in Ordnung sein.

L8er,
PSY
PSY LABS Games
Coders don't die, they just gosub without return

ToeB

BeitragMi, Jul 01, 2009 18:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey cool danke !!

Hier probiert nochmal :

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

SeedRnd MilliSecs()

Global BGBuffer = BackBuffer()
Global BGSizeX = GraphicsWidth()
Global BGSizeY = GraphicsHeight()

Global GravityX# = 0
Global GravityY# = + 0.1


Type b
   Field size#
   Field x#,y#
   Field sx#,sy#
   Field w#,sw#
   Field col
   Field mass#
End Type


Global TB_on,TB_x#,TB_y#,TB_r#,TB_w#
Global MB_on,MB_b.b


Global timer = CreateTimer(60)

;Global Ball1 = AddCircle(400,300,100)

Repeat
   MX = MouseX()
   MY = MouseY()
   SMX# = MouseXSpeed()
   SMY# = MouseYSpeed()
   If MouseHit(1)
      If TB_on = 0
         TB_x = MX
         TB_y = MY
         TB_on = 1      
      EndIf
   EndIf    
   If MouseHit(2)
      For tmp.b = Each b
         mouse_abs = Sqr( (tmp\x-MX)*(tmp\x-MX) + (tmp\y-MY)*(tmp\y-MY) )
         If mouse_abs <= tmp\size
            MB_On = 1
            MB_b = tmp
            Exit
         EndIf
      Next
   EndIf    
   UpdateAll()
   If MB_On = 1
      MB_b\x = MX
      MB_b\y = MY
      If MouseDown(2) = 0
         MB_On = 0
         MB_b\sx = SMX
         MB_b\sy = SMY
      EndIf
   EndIf          
   DrawAll()
   If TB_On = 1
      TB_r = Sqr( (TB_x-MX)*(TB_x-MX) + (TB_y-MY)*(TB_y-MY) )
      TB_w# = ATan2( (MY-TB_y) , (MX-TB_x) )
      Color 0,255,0
      Line TB_x,TB_y,TB_x+Cos(TB_w)*TB_r,TB_y+Sin(TB_w)*TB_r
      Color 0,0,255
      Oval TB_x-TB_r,TB_y-TB_r,TB_r*2,TB_r*2,0
      If MouseDown(1) = 0
         TB_On = 0
         AddCircle(TB_x,TB_y,TB_r,TB_r*TB_r,TB_w)
      EndIf
   EndIf
   Flip 0
   Cls
   WaitTimer(timer)
Until KeyHit(1)
End

Function AddCircle(x#,y#,r#,mass#=1,w#=0)
   tmp.b = New b
   tmp\x = x
   tmp\y = y
   tmp\size = r
   tmp\sx = 0
   tmp\sy = 0
   tmp\mass = mass
   tmp\w = w
   tmp\sw# = Rnd(-2.0,2.0)
   Return Handle(tmp)
End Function

Function UpdateAll()
   For tmp.b = Each b
      ;Bewegung      
      tmp\x# = tmp\x + tmp\sx
      tmp\y# = tmp\y + tmp\sy
      tmp\sx = tmp\sx + GravityX
      tmp\sy = tmp\sy + GravityY
      ;tmp\w = tmp\w + tmp\sw   
      
      ;Kollision mit den wänden
      If tmp\x-tmp\size < 0       Then tmp\sx = tmp\sx * -0.5 : tmp\x = tmp\size         
      If tmp\x+tmp\size > BGSizeX Then tmp\sx = tmp\sx * -0.5 : tmp\x = BGSizeX-tmp\size
      ;If tmp\y-tmp\size < 0       Then tmp\sy = tmp\sy * -0.5 : tmp\y = tmp\size         
      If tmp\y+tmp\size > BGSizeY Then tmp\sy = tmp\sy * -0.5 : tmp\y = BGSizeY-tmp\size    
   
      ;Kollision mit anderen bällen
      For b.b = Each b
         If b <> tmp
            If RectsOverlap(tmp\x-tmp\size-50,tmp\y-tmp\size-50,tmp\size*2+100,tmp\size*2+100,b\x-b\size-50,b\y-b\size-50,b\size*2+100,b\size*2+100) Then
               ball_abs_x# = b\x - tmp\x
               ball_abs_y# = b\y - tmp\y
               ball_abs# = Sqr( ball_abs_x*ball_abs_x + ball_abs_y*ball_abs_y )
               ball_rad# = tmp\size + b\size
               If ball_abs < ball_rad
                  ball_winkel# = ATan2( ball_abs_y , ball_abs_x )
                  ball_rad1# = ( ball_rad - ball_abs ) * (b\mass/Float(tmp\mass+b\mass))      
                  ball_rad2# = ( ball_rad - ball_abs ) * (tmp\mass/Float(tmp\mass+b\mass))      
                  nX# = Cos(ball_winkel)
                  nY# = Sin(ball_winkel)         
                  tmp\x = tmp\x - nX * ball_rad1
                  tmp\y = tmp\y - nY * ball_rad1
                    b\x =   b\x + nX * ball_rad2
                    b\y =   b\y + nY * ball_rad2
                  
                  tmp_Impulse# = nX#*tmp\sx + nY#*tmp\sy
                    b_Impulse# = nY#*  b\sx + nY#*  b\sy
                  res_Impulse# = (2.0*(tmp_Impulse - b_Impulse)) / (tmp\mass+b\mass)
                  tmp\sx = tmp\sx - res_Impulse * nX
                  tmp\sy = tmp\sy - res_Impulse * nY    
                    b\sx =   b\sx + res_Impulse * nX
                    b\sy =   b\sy + res_Impulse * nY    
               EndIf
            EndIf
         EndIf
      Next
      
      
      
   Next
End Function


Function DrawAll()
   For tmp.b = Each b
      Color 0,255,0
      Line tmp\x,tmp\y,tmp\x+Cos(tmp\w)*tmp\size,tmp\y+Sin(tmp\w)*tmp\size
      Color 255,0,0
      Oval tmp\x-tmp\size,tmp\y-tmp\size,tmp\size*2,tmp\size*2,0   
      ;Color 255,255,0
      ;Text tmp\x,tmp\y,tmp\col,1,1   
   Next
End Function


Sieht für mich realitisch aus, aber ich krig das mit dem still stand net hin.. irgenteine idee ?

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!

Tankbuster

BeitragMi, Jul 01, 2009 20:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Hatte Noobody nichtmal ein ähnliches Problem mit seiner Engine? Oder bilde ich mir das grad nur ein. Vielleicht solltest du ihn fragen Wink
Twitter
Download Jewel Snake!
Windows|Android

ToeB

BeitragMi, Jul 01, 2009 20:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Nochmal ne kleine Frage : Wie löse ich das mit der Rotation der Kugeln ?
Ich wollte die Engine nämlich in eine anderes Programm einbauen, und da brauch ich auch die realistische rotation... hab aber gar keinen plan davon ^^


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!

PSY

BeitragFr, Jul 03, 2009 18:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Hm,

fürne halbwegs passable Rotationsberechnung würd ich die Rotationsrichtung und Geschwindigkeit jeder Kugel speichern, bei der Kollision einfach -je nach Masse der Kugeln und Rotationsgeschwindigkeit- den Richtungsvektor der getroffenen Kugel mehr oder minder leicht abändern und ihr ne entgegengesetzte Rotation verpassen.

Wenns physikalisch korrekt sein soll, google einfach mal nach Billardphysik...wird aber relativ komplex wenns genau passen soll.

L8er,
PSY
PSY LABS Games
Coders don't die, they just gosub without return

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group