Collision avec un rectangle qui peut rotater !

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Collision avec un rectangle qui peut rotater !

Message par Thyphoon »

Bon une petite question...
J'utilise un Sprite 3D pour affiche un véhicule. Bien entendu ce dernier ne le rempli pas entièrement...En gros le véhicule est un Rectangle dans ce sprite...
Comment puis-je savoir si un point x,y est dans ce rectangle sachant que j'utilise la rotation de ce sprite...Donc je connais les coordonnée, et l'angle du sprite...
Vous voyez ce que je veux dire ? la plus part des tutoriels que j'ai trouvé était ou pour de la 3D ou pour des Sprite2D ou pour des intersections de forme géométrique.

si vous avez une idée merci d'avance :P
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

fais une recherche sur "point dans polygone" ou tu peux adapter ce code'point dans un triangle", ou utiliser la méthode de séparation des axes, j'ai un exemple en cours de développement, mais j'ai la flemme de le finir, il fonctionne sans les rotations, j'ai commencé à ajouter les matrices pour gérer les rotations, faut juste que je trouve une heure ou deux et beaucoup de motivation pour finir. Si mes souvenirs sont bons, il y a aussi une procédure qui teste un point dans un triangle dans le code Collision3D dans ma signature.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Merci beaucoup comtois ! je vais etudier ça de suite !! :D
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

Si cela peux t'aider, il y a une fonction dans la lib Windows GDI, (user32.lib)
'IntersectRect' tu trouvera des précisions ici:

http://msdn.microsoft.com/library/defau ... l_1mpg.asp

il existe pas pal de lien sur la toile qui en parle et fournis des exemples...
Force et sagesse...
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

tmyke a écrit :Si cela peux t'aider, il y a une fonction dans la lib Windows GDI, (user32.lib)
'IntersectRect' tu trouvera des précisions ici:

http://msdn.microsoft.com/library/defau ... l_1mpg.asp

il existe pas pal de lien sur la toile qui en parle et fournis des exemples...
Merci ! Mais je voudrais eviter d'utiliser les API...

Voici mon code pour faire des tests...il me reste plus qu'a completer la procedure Coli()

Code : Tout sélectionner

Structure Rectangle
  X.l ;Coordonée Central X
  Y.l ;Coordonée Central Y
  R.l ;Demi Diagonal du Rectangle
  Angle.l ;Angle de Rotation
  X1.l 
  Y1.l
  X2.l
  Y2.l
  X3.l
  Y3.l
  X4.l
  Y4.l
EndStructure

Global Rect.Rectangle

Rect\X=400
Rect\Y=300
Rect\R=150


If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0 Or InitSprite3D()=0 Or InitSound()=0
  MessageRequester("Error","DirectX 7+ is needed.",0) 
  End
EndIf

OpenWindow(0,0,0,800,600,"Planete Alien ",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0, 800, 600, 0, 0, 0)

Procedure Drawrect()
   LineXY(Rect\X1,Rect\Y1,Rect\X2,Rect\Y2,RGB(255,255,255))
   LineXY(Rect\X2,Rect\Y2,Rect\X3,Rect\Y3,RGB(255,255,255))
   LineXY(Rect\X3,Rect\Y3,Rect\X4,Rect\Y4,RGB(255,255,255))
   LineXY(Rect\X4,Rect\Y4,Rect\X1,Rect\Y1,RGB(255,255,255))
  Circle(Rect\X1,Rect\Y1,10,RGB(255,0,0))
  Circle(Rect\X2,Rect\Y2,10,RGB(255,0,0))
  Circle(Rect\X3,Rect\Y3,10,RGB(255,0,0))
  Circle(Rect\X4,Rect\Y4,10,RGB(255,0,0))
EndProcedure


Procedure Coli()

ProcedureReturn 0
EndProcedure

Repeat
  ExamineMouse()
  ExamineKeyboard()
  #DEG=#PI/180
  Rect\Angle+1
  If Rect\Angle>360:Rect\Angle=0:EndIf
  
    Rect\X1=Rect\X+Rect\R*Cos((Rect\Angle-25)*#DEG)
    Rect\Y1=Rect\Y+Rect\R*Sin((Rect\Angle-25)*#DEG)
  
    Rect\X2=Rect\X+Rect\R*Cos((Rect\Angle+25)*#DEG)
    Rect\Y2=Rect\Y+Rect\R*Sin((Rect\Angle+25)*#DEG)
    
    Rect\X3=Rect\X+Rect\R*Cos((Rect\Angle+180-25)*#DEG)
    Rect\Y3=Rect\Y+Rect\R*Sin((Rect\Angle+180-25)*#DEG)
    
    Rect\X4=Rect\X+Rect\R*Cos((Rect\Angle-180+25)*#DEG)
    Rect\Y4=Rect\Y+Rect\R*Sin((Rect\Angle-180+25)*#DEG)
    
  ;Si ma souris passe dans le rectangle
  If Coli()
    ClearScreen(RGB(255,255,255))
  Else
    ClearScreen(0)
  EndIf
  
  StartDrawing(ScreenOutput())
    Drawrect()
    Circle(MouseX(),MouseY(),10,RGB(0,255,0))
    
  StopDrawing()
  
  
  
  Delay(1)
  
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) 
si certain veulent s'y essayer n'hesitez pas ...moi je vais analyser les documents que Comtois m'a donné
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Bon c'est absolument pas optimisé ! Je me suis basé sur ce qu'a fait Comtois (encore une fois....que ferais-je sans toi :wink: )et je test 2 triangles (pour faire un rectangle)

je partage le code

Code : Tout sélectionner

;Code de colision avec un rectangle... d'apres un code de comtois
;http://www.purebasic.fr/french/viewtopic.php?t=1960
Structure Rectangle
  X.l ;Coordonée Central X
  Y.l ;Coordonée Central Y
  R.l ;Demi Diagonal du Rectangle
  Angle.l ;Angle de Rotation
  X1.l 
  Y1.l
  X2.l
  Y2.l
  X3.l
  Y3.l
  X4.l
  Y4.l
EndStructure

Global Rect.Rectangle

Rect\X=400
Rect\Y=300
Rect\R=150


If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0 Or InitSprite3D()=0 Or InitSound()=0
  MessageRequester("Error","DirectX 7+ is needed.",0) 
  End
EndIf

OpenWindow(0,0,0,800,600,"Planete Alien ",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0, 800, 600, 0, 0, 0)

Procedure Drawrect()
   LineXY(Rect\X1,Rect\Y1,Rect\X2,Rect\Y2,RGB(255,255,255))
   LineXY(Rect\X2,Rect\Y2,Rect\X3,Rect\Y3,RGB(255,255,255))
   LineXY(Rect\X3,Rect\Y3,Rect\X4,Rect\Y4,RGB(255,255,255))
   LineXY(Rect\X4,Rect\Y4,Rect\X1,Rect\Y1,RGB(255,255,255))
  Circle(Rect\X1,Rect\Y1,10,RGB(255,0,0))
  Circle(Rect\X2,Rect\Y2,10,RGB(255,0,0))
  Circle(Rect\X3,Rect\Y3,10,RGB(255,0,0))
  Circle(Rect\X4,Rect\Y4,10,RGB(255,0,0))
EndProcedure

Procedure Signe(a.l)
  If a>0
    ProcedureReturn 1
  ElseIf a=0
    ProcedureReturn 0
  Else
    ProcedureReturn -1
  EndIf
EndProcedure


Procedure Coli()
;Test la collision du point avec le triangle
  ;pour en savoir plus  http://tanopah.jo.free.fr/seconde/region.html
  ;Plan 1
  xu1=Rect\X2-Rect\X1:yu1=Rect\Y2-Rect\Y1
  c1=Rect\Y1*xu1-Rect\X1*yu1
  P1=Rect\X3*yu1-Rect\Y3*xu1+c1
  AX1=MouseX()*yu1-MouseY()*xu1+c1
  ;Plan 2
  xu2=Rect\X3-Rect\X2:yu2=Rect\Y3-Rect\Y2
  c2=Rect\Y2*xu2-Rect\X2*yu2
  P2=Rect\X1*yu2-Rect\Y1*xu2+c2
  AX2=MouseX()*yu2-MouseY()*xu2+c2
  ;Plan 3
  xu3=Rect\X1-Rect\X3:yu3=Rect\Y1-Rect\Y3
  c3=Rect\Y3*xu3-Rect\X3*yu3
  P3=Rect\X2*yu3-Rect\Y2*xu3+c3
  AX3=MouseX()*yu3-MouseY()*xu3+c3
 
  If  Signe(AX1)=Signe(P1) And Signe(AX2)=Signe(P2) And Signe(AX3)=Signe(P3)
    ProcedureReturn #True
  Else
    xu1=Rect\X3-Rect\X1:yu1=Rect\Y3-Rect\Y1
    c1=Rect\Y1*xu1-Rect\X1*yu1
    P1=Rect\X4*yu1-Rect\Y4*xu1+c1
    AX1=MouseX()*yu1-MouseY()*xu1+c1
    ;Plan 2
    xu2=Rect\X4-Rect\X3:yu2=Rect\Y4-Rect\Y3
    c2=Rect\Y3*xu2-Rect\X3*yu2
    P2=Rect\X1*yu2-Rect\Y1*xu2+c2
    AX2=MouseX()*yu2-MouseY()*xu2+c2
    ;Plan 3
    xu3=Rect\X1-Rect\X4:yu3=Rect\Y1-Rect\Y4
    c3=Rect\Y4*xu3-Rect\X4*yu3
    P3=Rect\X3*yu3-Rect\Y3*xu3+c3
    AX3=MouseX()*yu3-MouseY()*xu3+c3
    If  Signe(AX1)=Signe(P1) And Signe(AX2)=Signe(P2) And Signe(AX3)=Signe(P3)
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
  EndIf
EndProcedure
  #DEG=#PI/180
Repeat
  ExamineMouse()
  ExamineKeyboard()
  
  Rect\X=400+100*Sin(Rect\Angle*#DEG)
  Rect\Y=300+100*Cos(Rect\Angle*#DEG)
  

  Rect\Angle+1
  If Rect\Angle>360:Rect\Angle=0:EndIf
  
    Rect\X1=Rect\X+Rect\R*Cos((Rect\Angle-25)*#DEG)
    Rect\Y1=Rect\Y+Rect\R*Sin((Rect\Angle-25)*#DEG)
  
    Rect\X2=Rect\X+Rect\R*Cos((Rect\Angle+25)*#DEG)
    Rect\Y2=Rect\Y+Rect\R*Sin((Rect\Angle+25)*#DEG)
    
    Rect\X3=Rect\X+Rect\R*Cos((Rect\Angle+180-25)*#DEG)
    Rect\Y3=Rect\Y+Rect\R*Sin((Rect\Angle+180-25)*#DEG)
    
    Rect\X4=Rect\X+Rect\R*Cos((Rect\Angle-180+25)*#DEG)
    Rect\Y4=Rect\Y+Rect\R*Sin((Rect\Angle-180+25)*#DEG)
    
  ;Si ma souris passe dans le rectangle
  If Coli()
    ClearScreen(RGB(255,255,255))
  Else
    ClearScreen(0)
  EndIf
  
  StartDrawing(ScreenOutput())
    Drawrect()
    Circle(MouseX(),MouseY(),10,RGB(0,255,0))
    
  StopDrawing()
  
  
  
  Delay(1)
  
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)  
EDIT: j'ai rajouter un petit deplacement au Rectangle en plus de la rotation :P
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Sympa ta démo :)

tu peux tester les 4 plans qui entourent ton rectangle

Code : Tout sélectionner

;Code de collision avec un rectangle... d'apres un code de comtois
;http://www.purebasic.fr/french/viewtopic.php?t=1960
Structure Rectangle
  X.l ;Coordonée Central X
  Y.l ;Coordonée Central Y
  R.l ;Demi Diagonal du Rectangle
  Angle.l ;Angle de Rotation
  X1.l
  Y1.l
  X2.l
  Y2.l
  X3.l
  Y3.l
  X4.l
  Y4.l
EndStructure

Global Rect.Rectangle

Rect\X=400
Rect\Y=300
Rect\R=150


If InitSprite() = 0 Or InitKeyboard()=0 Or InitMouse()=0 Or InitSprite3D()=0 Or InitSound()=0
  MessageRequester("Error","DirectX 7+ is needed.",0)
  End
EndIf

OpenWindow(0,0,0,800,600,"Planete Alien ",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0, 800, 600, 0, 0, 0)

Procedure Drawrect()
   LineXY(Rect\X1,Rect\Y1,Rect\X2,Rect\Y2,RGB(255,255,255))
   LineXY(Rect\X2,Rect\Y2,Rect\X3,Rect\Y3,RGB(255,255,255))
   LineXY(Rect\X3,Rect\Y3,Rect\X4,Rect\Y4,RGB(255,255,255))
   LineXY(Rect\X4,Rect\Y4,Rect\X1,Rect\Y1,RGB(255,255,255))
  Circle(Rect\X1,Rect\Y1,10,RGB(255,0,0))
  Circle(Rect\X2,Rect\Y2,10,RGB(255,0,0))
  Circle(Rect\X3,Rect\Y3,10,RGB(255,0,0))
  Circle(Rect\X4,Rect\Y4,10,RGB(255,0,0))
EndProcedure

Procedure Signe(a.l)
  If a>0
    ProcedureReturn 1
  ElseIf a=0
    ProcedureReturn 0
  Else
    ProcedureReturn -1
  EndIf
EndProcedure


Procedure Coli()
;Test la collision du point avec le triangle
  ;pour en savoir plus  http://tanopah.jo.free.fr/seconde/region.html
  ;Plan 1
  mx = MouseX() : my=MouseY()
  xu1=Rect\X2-Rect\X1:yu1=Rect\Y2-Rect\Y1
  c1=Rect\Y1*xu1-Rect\X1*yu1
  P1=Rect\X3*yu1-Rect\Y3*xu1+c1
  AX1=Mx*yu1-My*xu1+c1
  ;Plan 2
  xu2=Rect\X3-Rect\X2:yu2=Rect\Y3-Rect\Y2
  c2=Rect\Y2*xu2-Rect\X2*yu2
  P2=Rect\X1*yu2-Rect\Y1*xu2+c2
  AX2=Mx*yu2-My*xu2+c2
  ;Plan 3
  xu3=Rect\X4-Rect\X3:yu3=Rect\Y4-Rect\Y3
  c3=Rect\Y3*xu3-Rect\X3*yu3
  P3=Rect\X1*yu3-Rect\Y1*xu3+c3
  AX3=Mx*yu3-My*xu3+c3
  ;Plan 4
  xu4=Rect\X1-Rect\X4:yu4=Rect\Y1-Rect\Y4
  c4=Rect\Y4*xu4-Rect\X4*yu4
  P4=Rect\X3*yu4-Rect\Y3*xu4+c4
  AX4=Mx*yu4-My*xu4+c4

  If  Signe(AX1)=Signe(P1) And Signe(AX2)=Signe(P2) And Signe(AX3)=Signe(P3) And Signe(AX4)=Signe(P4) 
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
EndProcedure
  #DEG=#PI/180
Repeat
  ExamineMouse()
  ExamineKeyboard()
 
  Rect\X=400+100*Sin(Rect\Angle*#DEG)
  Rect\Y=300+100*Cos(Rect\Angle*#DEG)
 

  Rect\Angle+1
  If Rect\Angle>360:Rect\Angle=0:EndIf
 
    Rect\X1=Rect\X+Rect\R*Cos((Rect\Angle-25)*#DEG)
    Rect\Y1=Rect\Y+Rect\R*Sin((Rect\Angle-25)*#DEG)
 
    Rect\X2=Rect\X+Rect\R*Cos((Rect\Angle+25)*#DEG)
    Rect\Y2=Rect\Y+Rect\R*Sin((Rect\Angle+25)*#DEG)
   
    Rect\X3=Rect\X+Rect\R*Cos((Rect\Angle+180-25)*#DEG)
    Rect\Y3=Rect\Y+Rect\R*Sin((Rect\Angle+180-25)*#DEG)
   
    Rect\X4=Rect\X+Rect\R*Cos((Rect\Angle-180+25)*#DEG)
    Rect\Y4=Rect\Y+Rect\R*Sin((Rect\Angle-180+25)*#DEG)
   
  ;Si ma souris passe dans le rectangle
  If Coli()
    ClearScreen(#Blue)
  Else
    ClearScreen(0)
  EndIf
 
  StartDrawing(ScreenOutput())
    Drawrect()
    Circle(MouseX(),MouseY(),10,RGB(0,255,0))
   
  StopDrawing()
 
 
 
  Delay(1)
 
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)  
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

comtois a écrit :Sympa ta démo :)

tu peux tester les 4 plans qui entourent ton rectangle
Lollll Merci c'est ce que je me suis dit lorsque j'ai posté le code...et comme je devais rentrer pour aller chercher mon fils je me suis dit que je verrais ça a mon retour mais tu m'a devancé lollllllll.

En tout cas merci beaucoup pour l'aide ...faut que je regarde maintenant si j'inclu ça dans mon jeu si c'est pas trop gourmand en temps :) En tout cas ça marche parfaitement ;)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Merci beaucoup a tous Mon problème de collision est resolu ... :o)
Mais ça fait apparaitre un autre problème mais de physique cette fois...Il ne faut pas que ma voiture puisse tourner sur elle même sans avancer...
Mais bon c'est un autre sujet.

Merci a tout ceux qui se sont penché sur le problème !! :)
Répondre