Source:BoxCollision.pb


;Comtois 03/12/04
;Tut sur les Box Collisions
;l'exemple est en 2D , mais le principe est le même pour la 3D.
;la différence réside dans le test de l'encadrement
;en 2D on a collision si xa2>xb1 And xa1<xb2 And ya2>yb1 And ya1<yb2
;en 3D on a collision si xa2>xb1 And xa1<xb2 And ya2>yb1 And ya1<yb2 And za2>zb1 And za1<zb2
;Avec xa1,ya1,za1 les coordonnées du coin haut gauche de la box A
;et xa2,ya2,za2 les coordonnées du coin bas droit de la box A

;un petit dessin pour une box 2D

; xa1/ya1 _________xa2/ya1
;        |         |
;        |         |
;        |         |
;        |         |
;        |         |
; xa1/ya2|_________|xa2/ya2

;En 3d cette méthode fonctionne dans la mesure où il n'y a pas rotation sur les box.
;Par exemple , Cette méthode peut être utilisée pour un jeu de casse briques 3D ou encore dans un space invaders 3D.

;-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 Zone
  x.l
  y.l
  Largeur.l
  Hauteur.l
EndStructure
Global Sprite1.point
Global Sprite2.point

;/Sprite 1
Sprite1\x=400
Sprite1\y=300
CreateSprite(1,128,128)
If StartDrawing(SpriteOutput(1))
  Box(0,0,SpriteWidth(1),SpriteHeight(1),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
CreateSprite(2,82,82)
If StartDrawing(SpriteOutput(2))
  Box(0,0,SpriteWidth(2),SpriteHeight(2),RGB(55,55,255))
  StopDrawing()
EndIf

;-Procedures
Procedure Erreur(Message$)
  MessageRequester( "Erreur" , Message$ , 0 )
  End
EndProcedure

Procedure BoxCollision(NoA,xa1,ya1,NoB,xb1,yb1)
  ;NoA = No du sprite 1
  ;xa1,ya1 = coordonnées du sprite 1
  ;NoB = No du sprite 2
  ;xb1,yb1 = coordonnées du sprite 2
  ;C'est la même chose que la fonction purebasic SpriteCollision() ,
  ;ça pourrait être ImageCollision() d'ailleurs , il suffit de remplacer sprite par image dans le code qui suit.
  ;Si on a besoin de connaître l'étendue de la zone touchée , il faut utiliser la procédure ZoneBoxCollision()
  Collision=#False
  xa2=xa1+SpriteWidth(NoA)
  ya2=ya1+SpriteHeight(NoA)
  xb2=xb1+SpriteWidth(NoB)
  yb2=yb1+SpriteHeight(NoB)
  ;En 3D il faut ajouter And za2>zb1 And za1<zb2
  If xa2>xb1 And xa1<xb2 And ya2>yb1 And ya1<yb2
    Collision=#True
  EndIf
  ProcedureReturn Collision
EndProcedure

Procedure ZoneBoxCollision(*Zone.Zone,NoA,xa1,ya1,NoB,xb1,yb1)
  ;C'est la même chose que la procédure BoxCollision ,
  ;sauf qu'en plus on récupère dans "Zone" les valeurs de la zone en collision
  Collision=#False
  xa2=xa1+SpriteWidth(NoA)
  ya2=ya1+SpriteHeight(NoA)
  xb2=xb1+SpriteWidth(NoB)
  yb2=yb1+SpriteHeight(NoB)
  ;En 3D il faut ajouter And za2>zb1 And za1<zb2
  If xa2>xb1 And xa1<xb2 And ya2>yb1 And ya1<yb2
    Collision=#True
    ;/Zone en collision
    MinX=xa1 : MaxX=xa2
    If xa1<xb1: MinX=xb1 : EndIf
    If xa2>xb2 : MaxX=xb2 : EndIf
    MinY=ya1 : MaxY=ya2
    If ya1<yb1 : MinY=yb1 : EndIf
    If ya2>yb2 : MaxY=yb2 : EndIf
    *Zone\x=MinX : *Zone\y=MinY
    *Zone\Largeur=MaxX-MinX
    *Zone\Hauteur=MaxY-MinY
  EndIf
  ProcedureReturn Collision
EndProcedure

Procedure AfficheInfos()
  If StartDrawing(ScreenOutput())
    FrontColor(255,255,0)
    BackColor(0,0,0)
    ;Si on a pas besoin de connaitre l"étendue de la zone en collision , BoxCollision(xa1,ya1,2,xb1,yb1) suffit
    If ZoneBoxCollision(@i.Zone,1,Sprite1\x,Sprite1\y,2,Sprite2\x,Sprite2\y)
      T$="Collision"
      ;/Affiche la zone en collision
      Box(i\x,i\y,i\Largeur,i\Hauteur,RGB(255,0,0))
    Else
      T$="Pas de collision"
    EndIf
    Locate(0,0)
    DrawText(T$)
    StopDrawing()
  EndIf
EndProcedure

;- Boucle principale
Repeat
  ClearScreen(0,0,0)
  ExamineKeyboard()
  ExamineMouse()
  ;/Affiche le sprite 1
  DisplaySprite(1,Sprite1\x,Sprite1\y)
  ;/Affiche le sprite 2 à la position de la souris
  Sprite2\x=MouseX()
  Sprite2\y=MouseY()
  DisplayTransparentSprite(2,Sprite2\x,Sprite2\y)
  ;/Test la collision
  AfficheInfos()
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)