Kollision: Ball hängt in Wand und geht durch

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

Liliput

Betreff: Kollision: Ball hängt in Wand und geht durch

BeitragSa, Jul 01, 2006 13:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab mal ein Script rausgekramt, den ich schon seit Ewigkeiten hier umfliegen hab und wollte daraus was machen. Der Quellcode ist nicht von mir, deswegen lass ich den Copyright mal mit drin.

Ich bin nicht so wirklich gut in Mathe und wollte mal fragen ob mir jemand weiterhelfen kann.

Die Bälle prallen alle scheinbar im richtigen Winkel etc. von den Wänden ab, allerdings passiert es ab und zu, daß ein Ball hängen bleibt und dann einfach durch die Wand abhaut.. Kann mir evtl. jemand helfen dieses Problem zu lösen?

Per Mausklick kann man Wände erstellen...

PS: Ich hoffe es ist nicht zu unverschämt den ganzen Code hier zu posten und dann auf Hilfe zu hoffen Wink

Code: [AUSKLAPPEN]

;2D Collision Example By Jeppe Nielsen 2004
;nielsen_jeppe@hotmail.com

;Added June 28th 2004:
;global variables to get the intersection or collision point between a line and a circle.
;use these globals to get the collision point between a circle and a line.

Global LineCollisionX#
Global LineCollisionY#

Graphics 800,600,16,2
SetBuffer BackBuffer()

Type cline
   Field x1#,y1#,x2#,y2#,nx#,ny#,ux#,uy#
End Type

Type circle
   Field x#,y#,vx#,vy#
   Field vel#
   Field r#
End Type

Type poof
   Field x,y
   Field age#
   Field maxage
End Type

;Create lines at screen edges
LineNew(0,0,800,0)
LineNew(800,0,800,600)
LineNew(0,600,800,600)
LineNew(0,0,0,600)

;Create two Circles
CircleNew(100,100,8,6,0.2)
CircleNew(500,100,8,4,0.2)
CircleNew(200,100,8,-0.6,2)
CircleNew(100,200,8,8,0.2)

event=0
cline.cline=Null
Repeat
   Cls
      
   If MouseHit(2)
      CircleNew(Rnd(200,600),Rnd(100,500),Rnd(10,40),Rnd(-2,2),Rnd(-2,2))
   EndIf
   
   Select event
      Case 0
         If MouseHit(1)
            x1#=MouseX()
            y1#=MouseY()
            event=1
            cline=LineNew(x1#,y1#,x1+10,y1)
         EndIf
      Case 1
         LineRecalc(cline,x1,y1,MouseX(),MouseY())
         If MouseHit(1)
            event=0
         EndIf
   End Select
   
   ;Update and draw stuff
   CircleUpdate()
   PoofUpdate()

   CircleDraw()
   LineDraw()
   PoofDraw()
         
   i=0
   For c.cLine=Each cline
      Text 10,15*i,c\x1+""+c\y1+":"+c\x2+":"+c\y2
      i=i+1
   Next   

   Flip
Until KeyDown(1)
End

Function LineNew.cline(x1#,y1#,x2#,y2#)
   l.cline=New cline
   LineRecalc(l,x1#,y1#,x2#,y2#)
   Return l
End Function

Function LineRecalc(l.cline,x1#,y1#,x2#,y2#)
   l\x1=x1
   l\y1=y1
   l\x2=x2
   l\y2=y2

   dx#=l\x2-l\x1
   dy#=l\y2-l\y1
   
   d#=Sqr(dx*dx+dy*dy)
   If d#<0.0001
      d#=0.0001
   EndIf
   
   l\ux=dx/d
   l\uy=dy/d
   
   l\nx#=l\uy
   l\ny#=-l\ux
End Function

Function LineDraw()
   For l.cline=Each cline
      Color 255,255,255
      Line l\x1,l\y1,l\x2,l\y2

      Color 255,255,0
      ;Draw normal
      xm#=(l\x1+l\x2)/2.0
      ym#=(l\y1+l\y2)/2.0
      Line xm,ym,xm+l\nx*10,ym+l\ny*10
   Next
End Function

;Global LineCollisionX#
;Global LineCollisionY#

;Returns the shortest distance from a point to a line
;Use LineCollisionX and LineCollisionY to get the collision point.
Function LineDistance#(l.cline,x#,y#)
   dx#=l\x2-l\x1
   dy#=l\y2-l\y1
   
   d#=Sqr(dx*dx+dy*dy)
   
   px#=l\x1-x#
   py#=l\y1-y#
   
   dist#=(dx*py-px*dy) / d
   
   LineCollisionX=x#-l\nx*dist#
   LineCollisionY=y#-l\ny*dist#
      
   Return Abs(dist#)
End Function

;Returns true if a point collides with a line within range r
Function LineCollide(l.cline,x#,y#,r#)
   dx1#=x-(l\x1-l\ux*r)
   dy1#=y-(l\y1-l\uy*r)
   
   d#=Sqr(dx1*dx1+dy1*dy1)
   
   dx1=dx1/d
   dy1=dy1/d
   
   dx2#=x-(l\x2+l\ux*r)
   dy2#=y-(l\y2+l\uy*r)
   
   d#=Sqr(dx2*dx2+dy2*dy2)
   
   dx2=dx2/d
   dy2=dy2/d
   
   dot1#=dx1*l\ux+dy1*l\uy
   dot2#=dx2*l\ux+dy2*l\uy
   Return ((dot1#>=0 And dot2#<=0) Or (dot1#<=0 And dot2#>=0)) And (LineDistance(l,x,y)<=r)
End Function

Function CircleNew.circle(x#,y#,r#=50,vx#=0,vy#=0)
   c.circle=New circle
   c\x=x
   c\y=y
   c\r=r
   c\vx=vx
   c\vy=vy
   CirclePlace(c)
   Return c
End Function

Function CirclePlace(c.circle,w#=800,h#=600)
   num=0
   While CirclePlaceTest(c,c\x,c\y)=False And num<1000
      c\x=Rnd(w)
      c\y=Rnd(h)
      num=num+1
   Wend
End Function

;Returns true if a circle can be placed, it doesn´t collide with any other circles or lines
Function CirclePlaceTest(c.circle,x#,y#)
   For cc.circle=Each circle
      If cc<>c
         dx#=cc\x-c\x
         dy#=cc\y-c\y
         d#=Sqr(dx*dx+dy*dy)
         If d<(c\r+cc\r)
            Return False
         EndIf
      EndIf
   Next

   For l.cline=Each cline
      If LineCollide(l,c\x,c\y,c\r)
         Return False
      EndIf
   Next
   Return True
End Function

;draw circles
Function CircleDraw()
   Color 0,0,255
   For c.circle=Each circle
      rh#=c\r*2
      Oval c\x-c\r,c\y-c\r,rh,rh
   Next
End Function

Function CircleUpdate()
   For c.circle=Each circle
      ;Calculate total velocity
      c\vel#=Sqr(c\vx*c\vx+c\vy*c\vy)
      
         ;collision against other circles
      For cc.circle=Each circle
         ;do not test against itself
         If cc<>c
            ;vector from one circle to another
            dx#=cc\x-c\x
            dy#=cc\y-c\y
            d#=Sqr(dx*dx+dy*dy)
            ;check of distance is smaller than the two circle´s radii together
            If d<(c\r+cc\r)
            ;make the vector a unit vector (length=1), multiply it with the circle´s
            ;total velocity, to get the new motion vector
            c\vx=(-dx#/d) * c\vel
            c\vy=(-dy#/d) * c\vel
         EndIf
      EndIf
   Next
   ;collision agains lines
   For l.cline=Each cline
      ;Check if circle collides with a line
      If LineCollide(l,c\x,c\y,c\r)
         ;create a mark, where the circle has colliede with the line
         PoofNew(LineCollisionX,LineCollisionY)
            
         ;Get the dot product between the circles motion vector and the line´s normal vector
         dot#=c\vx*l\nx+c\vy*l\ny   
         
         ;Calculate the circle´s new motion vector
         c\vx=c\vx-2.0*l\nx*dot
         c\vy=c\vy-2.0*l\ny*dot
         EndIf
      Next
      
      ;add velocity to position
      c\x=c\x+c\vx
      c\y=c\y+c\vy
   
      ;Wrap to screen boundaries
      If c\x>GraphicsWidth()
         c\x=0
      EndIf
   
      If c\y>GraphicsHeight()
         c\y=0
      EndIf

      If c\x<0
         c\x=GraphicsWidth()
      EndIf   
   
      If c\y<0
         c\y=GraphicsHeight()
      EndIf
   Next
End Function

Function PoofNew.poof(x,y,age#=20)
   p.poof=New poof
   p\x=x
   p\y=y
   p\maxage=age
   Return p
End Function

Function PoofUpdate()
   For p.poof=Each poof
      p\age=p\age+1
      If p\age>=p\maxage
         Delete p
      EndIf
   Next
End Function

Function PoofDraw()
   For p.poof=Each poof
      pah=p\age*0.5
      Oval p\x-pah,p\y-pah,p\age,p\age,0
   Next
End Function

Rone

BeitragSa, Jul 01, 2006 13:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

Also bei mir klappt alles wunderbar...
Aber ich glaube man muss drauf achten, dass aufgezogene Wände eine Fläche einschließen, damit es kein Problem mit parralel fliegenden Kugeln gibt

mfg
 

Liliput

BeitragSa, Jul 01, 2006 13:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Mhh komisch, also ich habs jetzt nochmal wirklich Pixelgenau gemacht, und alle Wände waren 100% geschlossen, aber trotzdem passiert ab und zu das:
http://img270.imageshack.us/im...lli8sy.jpg

Dann wandert der Ball an der Wand hin und her und irgendwann löst er sich, allerdings dann auch zum Teil in die falsche Richtung, also raus aus der Wand.

Ich hab irgendwie auch noch nicht ganz rausgefunden wann er das macht, aber eben sah es so aus als wenn es in den Ecken passiert (kann aber auch Zufall sein)

Rone

BeitragSa, Jul 01, 2006 14:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn man dem Ball keine chance, bei einer Bewegung die ungefähr Parallel zur Linie ist, mit der Liniespitze zu Kollidieren, dann passiert das auch nicht.
Habe es gerade mal etwas länger durchlaufen lassen: http://www.sa-tec.net/colli.jpg
Die Kugel darf halt nicht in die Linie geraten...

mfg
 

Liliput

BeitragSa, Jul 01, 2006 14:28
Antworten mit Zitat
Benutzer-Profile anzeigen
ok danke für die Hilfe Smile

Dann ist der Code nicht so ganz das was ich brauche, weil ich wollte schon immer einen Abprall, egal welchen Winkel die Ecken haben usw. Mal schauen wie ich das drehe oder ob ich was besseres finde bzw. zustandebringe +g+

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group