Kollision von konvexen Polygonen

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

Goodjee

Betreff: Kollision von konvexen Polygonen

BeitragSo, Okt 18, 2009 15:58
Antworten mit Zitat
Benutzer-Profile anzeigen
aloa,
heute habe ich mal auf Noobodys Terrain begeben Wink und mittels 2er Tutorials das Seperating Axis Theorem implementiert. Es erlaubt einem Kollisionen zwischen 2 beliebigen konvexen Polygonen zu erkennen. Es lässt sich auch um konkave Polygone und auf Punkte/Kreise erweitern.

Erstmal die beiden Tutorials: http://wiki.delphigl.com/index...is_Theorem und http://www.gamedev.net/referen...Collision/

Und dann der Sourcecode, der ist ein bisschen kommentiert und mit beispiel versehen:

Code: [AUSKLAPPEN]
SuperStrict
SetGraphicsDriver GLMax2DDriver()
Graphics 800,600
SetBlend ALPHABLEND

Type Polygon
   Field poly:Float[,]
   Field x:Float
   Field y:Float
   Field rot:Float
   
   Method draw()
      SetAlpha(0.5)
      Local data:Float[]=New Float[getVertexCount()*2]
      For Local i:Int=0 To poly.dimensions()[0]-1
         data[2*i]=getTransformedVertexX(i)
         data[2*i+1]=getTransformedVertexY(i)
      Next
      DrawPoly data
   EndMethod
   
   Method getTransformedVertexX:Float(i:Int)
      Return Cos(rot)*poly[i Mod getVertexCount(),0]-Sin(rot)*poly[i Mod getVertexCount(),1]+x
   EndMethod
   
   Method getTransformedVertexY:Float(i:Int)
      Return Sin(rot)*poly[i Mod getVertexCount(),0]+Cos(rot)*poly[i Mod getVertexCount(),1]+y
   EndMethod
   
   Method collide:Int(partner:Polygon)
      'alle kanten bzw achsen berechnen
      Local edges:Float[getVertexCount()+partner.getVertexCount(),2]
      For Local i:Int=0 To getVertexCount()-1
         '2 vertices holen
         Local vx:Float=getTransformedVertexX(i)
         Local vy:Float=getTransformedVertexY(i)
         Local vx2:Float=getTransformedVertexX(i+1)
         Local vy2:Float=getTransformedVertexY(i+1)         
         
         'normale bilden
         edges[i,0]=-1*(vy-vy2)
         edges[i,1]=vx-vx2
      Next
      For Local i:Int=0 To partner.getVertexCount()-1
         edges[i+getVertexCount(),1]=partner.poly[i,0]-partner.poly[(i+1) Mod partner.getVertexCount(),0]
         edges[i+getVertexCount(),0]=(partner.poly[i,1]-partner.poly[(i+1) Mod partner.getVertexCount(),1])*-1
         
         Local vx:Float=partner.getTransformedVertexX(i)
         Local vy:Float=partner.getTransformedVertexY(i)
         Local vx2:Float=partner.getTransformedVertexX(i+1)
         Local vy2:Float=partner.getTransformedVertexY(i+1)         
         
         'normale bilden
         edges[i+getVertexCount(),0]=-1*(vy-vy2)
         edges[i+getVertexCount(),1]=vx-vx2
         
      Next
      
      'achsen malen
      SetColor(0,255,0)
      For Local i:Int=0 To edges.dimensions()[0]-1
         If(i>3) SetColor(255,0,0)
         DrawLine 400,300,400+edges[i,0]*1000,300+edges[i,1]*1000
         DrawLine 400,300,400+edges[i,0]*-1000,300+edges[i,1]*-1000
      
      Next
      SetColor(255,255,255)
      
      'alle achsen durchgehn
      For Local i:Int=0 To edges.dimensions()[0]-1      
         'alle punkte berechnen
         Local minA:Float=10^37,maxA:Float=-10^37,minB:Float=10^37,maxB:Float=-10^37
         For Local j:Int=0 To getVertexCount()-1
            'vertexpunkte berechnen
            Local vx:Float=getTransformedVertexX(j)
            Local vy:Float=getTransformedVertexY(j)
            'und an achse transformieren
            Local bruch:Float=(vx*edges[i,0]+vy*edges[i,1])/(edges[i,0]*edges[i,0]+edges[i,1]*edges[i,1])
            Local skalar:Float=bruch*edges[i,0]*edges[i,0]+bruch*edges[i,1]*edges[i,1]
            If(skalar<minA) minA=skalar
            If(skalar>maxA) maxA=skalar
         Next
         For Local j:Int=0 To partner.getVertexCount()-1
            'vertexpunkte berechnen
            Local vx:Float=partner.getTransformedVertexX(j)
            Local vy:Float=partner.getTransformedVertexY(j)
            'und an achse transformieren
            Local bruch:Float=(vx*edges[i,0]+vy*edges[i,1])/(edges[i,0]*edges[i,0]+edges[i,1]*edges[i,1])
            Local skalar:Float=bruch*edges[i,0]*edges[i,0]+bruch*edges[i,1]*edges[i,1]
            If(skalar<minB) minB=skalar
            If(skalar>maxB) maxB=skalar
         Next
         If(minB>maxA Or maxB<minA) Return 0
      Next
      Return 1
   EndMethod
   
   Method getVertexCount:Int()
      Return poly.dimensions()[0]
   EndMethod
   
EndType

Local poly1:Polygon=New Polygon
Local poly2:Polygon=New Polygon

Local data1:Float[3,2]
data1[0,0]=0
data1[0,1]=0
data1[1,0]=250
data1[1,1]=0
data1[2,0]=125
data1[2,1]=150
poly1.poly=data1
poly2.poly=data1

Local data2:Float[4,2]
data2[0,0]=-50
data2[0,1]=-50
data2[1,0]=50
data2[1,1]=-50
data2[2,0]=50
data2[2,1]=50
data2[3,0]=-50
data2[3,1]=50
poly1.poly=data1
poly2.poly=data2

poly1.x=100
poly1.y=100
poly1.rot=90
poly2.x=300
poly2.y=250
Local j:Int=0
Repeat
   j:+1
   j=j Mod 360
   Cls
   'poly1.rot=j
   poly2.rot=-j
   poly1.draw()
   poly2.draw()
   poly1.x=MouseX()
   poly1.y=MouseY()
   DrawText(poly1.collide(poly2),0,0)
   Flip
Until KeyHit(KEY_ESCAPE) Or AppTerminate()


ich hoffe der code ist fehlerfrei, anderenfalls seid ihr meine betatester Wink

mfg
goodjee
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

Markus2

BeitragFr, Apr 13, 2012 13:42
Antworten mit Zitat
Benutzer-Profile anzeigen
Interessant , Danke Smile

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group