Source:CollisionSpherique.pb
;Comtois 02/12/04
;Tut sur les Collisions Sphériques
;l'exemple est en 2D , mais le principe est le même pour la 3D.
;la différence réside dans le calcul de la distance
;en 2D on a Distance=Sqr((x1-x2)²+(y1-y2)²)
;en 3D on a Distance=Sqr((x1-x2)²+(y1-y2)²+(z1-z2)²)
;Avec x1,y1,z1 les coordonnées de la sphere 1
;et x2,y2,z2 les coordonnées de la sphere 2
;Pour détecter une collision entre deux entitys 3D , il suffit de définir une sphère qui enveloppe chacune des entitys
;et de tester la distance entre les entitys 3D. Bien sûr cette méthode a ses limites .
;Il est très rare d'avoir des entitys de forme sphérique :p
;l'avantage c'est que cette méthode est simple à mettre en oeuvre et elle est rapide (elle nécessite peu de calculs).
;-Declare
Declare Erreur(Message$)
;-Initialisation
#ScreenWidth = 800 : #ScreenHeight = 600 : #ScreenDepth = 32
If InitEngine3D() = 0
Erreur("Impossible d'initialiser la 3D , vérifiez la présence de engine3D.dll")
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse()=0
Erreur("Impossible d'initialiser DirectX 7 Ou plus")
ElseIf OpenScreen( #ScreenWidth , #ScreenHeight , #ScreenDepth , "" ) = 0
Erreur("Impossible d'ouvrir l'écran ")
EndIf
Structure Sphere
x.l
y.l
Rayon.l
EndStructure
Global Sprite1.Sphere
Global Sprite2.Sphere
;/Sprite 1
Sprite1\x=400
Sprite1\y=300
Sprite1\Rayon=60
CreateSprite(1,128,128)
If StartDrawing(SpriteOutput(1))
Circle(SpriteWidth(1)/2,SpriteHeight(1)/2,Sprite1\Rayon,RGB(185,155,255))
StopDrawing()
EndIf
;/Sprite 2
Sprite2\x=0 ; utilise les coordonnées de la souris
Sprite2\y=0 ; utilise les coordonnées de la souris
Sprite2\Rayon=40
CreateSprite(2,82,82)
If StartDrawing(SpriteOutput(2))
Circle(SpriteWidth(2)/2,SpriteHeight(2)/2,Sprite2\Rayon,RGB(55,55,255))
StopDrawing()
EndIf
;-Procedures
Procedure Erreur(Message$)
MessageRequester( "Erreur" , Message$ , 0 )
End
EndProcedure
Procedure.f CalculDistance(X1,Y1,X2,Y2)
;en 2D Distance=Sqr((x1-x2)²+(y1-y2)²)
;en 3D Distance=Sqr((x1-x2)²+(y1-y2)²+(z1-z2)²)
Distance.f=Sqr((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2))
ProcedureReturn Distance
EndProcedure
Procedure AfficheDistance(X1,Y1,X2,Y2)
If StartDrawing(ScreenOutput())
;Affiche la distance entre la sphère 1 et la sphère 2
R1=Sprite1\Rayon
R2=Sprite2\Rayon
LineXY(X1,Y1,X2,Y2,RGB(255,0,0))
x=(X1+X2)/2
y=(Y1+Y2)/2
FrontColor(0,155,0)
BackColor(255,255,0)
Locate(x,y)
Distance.f=CalculDistance(X1,Y1,X2,Y2)
DrawText("d="+StrF(Distance,1))
;/Affiche le rayon 1
Locate(X1,Y1)
DrawText("R1="+Str(R1))
;/Affiche le rayon 2
Locate(X2,Y2)
DrawText("R2="+Str(R2))
;/Commentaire et collision
FrontColor(255,255,255)
BackColor(0,0,0)
Locate(0,0)
DrawText("Soit 'R1' le rayon de la sphère 1 ,'R2' le rayon de la sphère 2 et 'd' la distance entre la sphère 1 et 2")
Locate(0,20)
DrawText("Il y a collision entre les deux sphères si la Distance 'd' est inférieure à la somme des deux rayons > 'd'<'R1+R2'")
Locate(0,40)
If Distance<R1+R2
T$=" , Il y a collision"
Else
T$=" , il n'y a pas de collision"
EndIf
DrawText("R1 + R2 = "+Str(R1)+" + "+Str(R2)+" = "+Str(R1+R2)+ " ..... et d = "+StrF(Distance,1))
;/Collision?
If Distance<R1+R2
FrontColor(255,255,0)
BackColor(255,0,0)
T$="Il y a collision !"
Else
FrontColor(255,255,0)
BackColor(0,0,255)
T$="Il n'y a pas de collision"
EndIf
Locate(400-TextLength(T$)/2,580)
DrawText(T$)
StopDrawing()
EndIf
EndProcedure
;- Boucle principale
Repeat
ClearScreen(0,0,0)
ExamineKeyboard()
ExamineMouse()
;/Affiche le sprite 1
CentreX1=Sprite1\x+SpriteWidth(1)/2
Centrey1=Sprite1\y+SpriteHeight(1)/2
DisplaySprite(1,Sprite1\x,Sprite1\y)
;/Affiche le sprite 2 à la position de la souris
Sprite2\x=MouseX()
Sprite2\y=MouseY()
CentreX2=Sprite2\x+SpriteWidth(2)/2
Centrey2=Sprite2\y+SpriteHeight(2)/2
DisplayTransparentSprite(2,Sprite2\x,Sprite2\y)
;/
;Il y a collision si la distance entre la sphere de rayon R1 et la sphere de rayon R2 est < R1+R2
AfficheDistance(CentreX1,Centrey1,CentreX2,Centrey2)
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)

