Kollision: Ball hängt in Wand und geht durch
Übersicht

LiliputBetreff: Kollision: Ball hängt in Wand und geht durch |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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 ![]() 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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
ok danke für die Hilfe ![]() 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+ |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group