Page 1 sur 1

[R] Détecter Collision Guictrlcreate...

Posté : mer. 02 mars 2016 22:43
par TripleLardon
Bonjour à tous et à toutes :D

Voila, dans mon programme je souhaite détecter lorsque la hitbox d'un Guictrlcreate.. entre collision (se superpose) avec celle d'une autre hitbox d'un autre Guictrlcreate..

Si ce dont je vous parle n'est pas claire, je vous ai préparé un petit programme explicatif.

Code : Tout sélectionner

 #include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <ButtonConstants.au3>
#include <FontConstants.au3>
#include <ListviewConstants.au3>
#include <ColorConstants.au3>
#include <Misc.au3>

Guicreate("",550,300)

Guictrlcreatelabel("Les touches ZQSD pour déplacer le carré bleu" & @crlf & "Les fléches directionelles pour déplacer le carré rouge",5,5)

;creation du perso 1 qui est le carré rouge
$Perso1 = Guictrlcreatelabel("",350,100,50,50)
GUICtrlSetBkColor($Perso1,$COLOR_RED)

;creation du perso 12qui est le carré bleu
$Perso2 = Guictrlcreatelabel("",150,100,50,50)
GUICtrlSetBkColor($Perso2,$COLOR_BLUE)


Guisetstate()

While 1

	$msg = GUIGetMsg(1)

;Trouve les coordonnés du perso 1
	$Coo1 = ControlGetPos("","",$Perso1)
	$X_P1 = $Coo1[0]
	$Y_P1 = $Coo1[1]

;Trouve les coordonnés du perso 2
	$Coo2 = ControlGetPos("","",$Perso2)
	$X_P2 = $Coo2[0]
	$Y_P2 = $Coo2[1]


;Systeme pour deplacer le perso 1
	  If _IsPressed("26") Then
	  Guictrlsetpos($Perso1,$X_P1,$Y_P1 - 1)

	   ElseIf _IsPressed("28") Then
	   Guictrlsetpos($Perso1,$X_P1,$Y_P1 + 1)

	   ElseIf _IsPressed("27") Then
	   Guictrlsetpos($Perso1,$X_P1 + 1,$Y_P1)


	   ElseIf _IsPressed("25") Then
	   Guictrlsetpos($Perso1,$X_P1 - 1,$Y_P1)
	   EndIf

;Systeme pour deplacer le perso 2
	   If _IsPressed("5A") Then
	  Guictrlsetpos($Perso2,$X_P2,$Y_P2- 1)

	   ElseIf _IsPressed("53") Then
	   Guictrlsetpos($Perso2,$X_P2,$Y_P2 + 1)

	   ElseIf _IsPressed("44") Then
	   Guictrlsetpos($Perso2,$X_P2 + 1,$Y_P2)


	   ElseIf _IsPressed("51") Then
	   Guictrlsetpos($Perso2,$X_P2 - 1,$Y_P2)
	   EndIf

	   
;Permet de fermer le programme
	   Select
		   Case $Msg[0] = $Gui_event_close
		Exit
	   EndSelect


	WEnd
	

Si vous avez lancé le programme si dessus, on peut bouger les carré, et j'aimerais détecter si les carrés rentre en collision entre eux. J'ai déjà fais un test en regardant si:

Code : Tout sélectionner

 if $X_Carre_Bleu = $X_Carre_Rouge and  $Y_Carre_Bleu = $Y_Carre_Rouge then
 faire quelque chose

Le problème de cette méthode est, que la collision est détecter seulement si les pixels en haut a gauche des carrés se touchent.

En espèrent avoir étais claire et aussi, que ce dont je recherche soit possible a créer.
Merci de votre lecture et bonne journée !

Re: [..] Détecter Collision Guictrlcreate...

Posté : jeu. 03 mars 2016 08:49
par mdanielm
Souvenir lointain de fac:

Un carré est une -boule- pour la métrique du plan:
d(M,N) = max(|xM-xN|, |yM-yN|)

Deux boules se rencontrent si la distance des centres est inférieure à la somme des rayons.

Exemple:
Carré 1 de centre C1(100,120) et de rayon 20 = width/2 = height/2
Carré 2 de centre C2(130,110) et de rayon 30 = ....
Ils se rencontrent si :
d(C1,C2) = max(30,10) <= 30+20
Comme 30 <= 50, ils se rencontrent.

... idée à tester sur des carrés seulement !

Re: [..] Détecter Collision Guictrlcreate...

Posté : jeu. 03 mars 2016 10:29
par mdanielm
Idée 2:
Une autre idée consiste à convertir les contrôles en objet -Region- de GDIPlus et d'utiliser _GDIPlus_RegionCombineRect() qui effectue l'intersection des régions.
Courage!

Re: [..] Détecter Collision Guictrlcreate...  

Posté : mar. 11 avr. 2017 21:28
par TripleLardon
Bonjour!

Je me permet une petit MaJ du post. Presque un an après j'y ai soudainement repensé et j'ai donc fait une fonction permettant de détecter une collision entre 2 carrés
Cette fonction de marche qu'avec des carrés, mais ils suffit de changer la manière dont sont calculés les coordonnées des angles (ou coin) pour que cela marche avec des rectangles.

La fonction comprend les arguments suivant:
$x1 = Coordonné x de carré 1
$y1 = Coordonné y de carré 1
$x2 = Coordonné x de carré 2
$y2 = Coordonné y de carré 2
$z1 = Largeur du carré 1
$z2 = Largeur du carré 2

Fonction:
func collision($x1,$y1,$x2,$y2,$z1,$z2)

   Local $A1[2] = [$x1,$y1]
   Local $B1[2] = [$x1 + $z1,$y1]
   Local $C1[2] = [$x1 + $z1,$y1 + $z1]
   Local $D1[2] = [$x1,$y1 + $z1]

   Local $A2[2] = [$x2,$y2]
   Local $B2[2] = [$x2 + $z2,$y2]
   Local $C2[2] = [$x2 + $z2,$y2 + $z2]
   Local $D2[2] = [$x2,$y2 + $z2]

   If ($C1[0] > $A2[0] and $C1[0] < $B2[0] and $C1[0] < $C2[0] and $C1[0] > $D2[0] and $C1[1] > $A2[1] and $C1[1] > $B2[1] and $C1[1] < $C2[1] and $C1[1] < $D2[1]) or($B1[0] > $A2[0] and $B1[0] < $B2[0] and $B1[0] < $C2[0] and $B1[0] > $D2[0] and $B1[1] > $A2[1] and $B1[1] > $B2[1] and $B1[1] < $C2[1] and $B1[1] < $D2[1]) or ($D1[0] > $A2[0] and $D1[0] < $B2[0] and $D1[0] < $C2[0] and $D1[0] > $D2[0] and $D1[1] > $A2[1] and $D1[1] > $B2[1] and $D1[1] < $C2[1] and $D1[1] < $D2[1]) or ($A1[0] > $A2[0] and $A1[0] < $B2[0] and $A1[0] < $C2[0] and $A1[0] > $D2[0] and $A1[1] > $A2[1] and $A1[1] > $B2[1] and $A1[1] < $C2[1] and $A1[1] < $D2[1]) Then
      Return 1
   EndIf
EndFunc
Il a peux être moyen de réduire la fonction, mais au moins ça marche :D

Re: [R] Détecter Collision Guictrlcreate...

Posté : ven. 12 mai 2017 03:38
par Numeric
Sujet résolu mais pour faire plus simple... :D
#include <WinAPI.au3>


; #FUNCTION# ====================================================================================================================
; Name ..........: Ws_CtrlMetrics
; Description ...: Determine si deux controls de même classe entre en colision
; Syntax ........: Ws_CtrlMetrics($idCtrl1, $idCtrl2, $CtrlC_Name)
; Parameters ....: $idCtrl1             - an integer value.
;                  $idCtrl2             - an integer value.
;                  $CtrlC_Name          - an unknown value.
; Return values .: -1 Ctrl1 ou Ctrl2 n'appartient pas à la classe indiquée
;                  Succes : "String explicite"
; Author ........: Numeric
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func Ws_CtrlMetrics($idCtrl1, $idCtrl2, $CtrlC_Name)
   If Not _isGUICtrHwnd($idCtrl1, $CtrlC_Name) Then
      Return SetError(1, 0, -1)
   EndIf

   If Not _isGUICtrHwnd($idCtrl2, $CtrlC_Name) Then
      Return SetError(2, 0, -2)
   EndIf
   Local $aCtrl1_POS = ControlGetPos("", "", $idCtrl1)
   Local $aCtrl2_POS = ControlGetPos("", "", $idCtrl2)

   If (($aCtrl1_POS[2] - $aCtrl1_POS[0]) <= ($aCtrl2_POS[2] - $aCtrl2_POS[0])) And (($aCtrl2_POS[3] - $aCtrl2_POS[1]) <= ($aCtrl1_POS[3] - $aCtrl1_POS[1])) Or _
         (($aCtrl1_POS[2] - $aCtrl1_POS[0]) >= ($aCtrl2_POS[2] - $aCtrl2_POS[0])) And (($aCtrl2_POS[3] - $aCtrl2_POS[1]) >= ($aCtrl1_POS[3] - $aCtrl1_POS[1])) Then

      $sRetText = "Les deux contrôles se touchent!"
   Else
      $sRetText = "Les deux contrôles ne se touchent pas!"
   EndIf
   Return _WinAPI_ShowMsg($sRetText)

EndFunc   ;==>Ws_CtrlMetrics


; #FUNCTION# ====================================================================================================================
; Name ..........: _isGUICtrHwnd
; Description ...: Determine si un control appartient une classe determinée
; Syntax ........: _isGUICtrHwnd($hWnd[, $CtrlC_Name = "Static"])
; Parameters ....: $hWnd                - a handle value.
;                  $CtrlC_Name          - [optional] an unknown value. Default is "Static".
; Return values .: Succes True or False
; Author ........: Numeric
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _isGUICtrHwnd($hWnd, $CtrlC_Name = "Static")
   Return BitAND(_WinAPI_IsClassName($hWnd, $CtrlC_Name), True) = True
EndFunc   ;==>_isGUICtrHwnd


Exemple()


Func Exemple()
   #include <GUIConstantsEx.au3>
   #include <StaticConstants.au3>
   #include <WindowsConstants.au3>
   #Region ### START Koda GUI section ### Form=
   Global $Form1 = GUICreate("Numeric ", 304, 118, 192, 124)
   Global $Label1 = GUICtrlCreateLabel("Control Label 1", 32, 24, 75, 17)
   Global $Label2 = GUICtrlCreateLabel("Control Label 2", 88, 24, 75, 17)
   Global $Label3 = GUICtrlCreateLabel("Control Label 3", 32, 56, 75, 17)
   GUISetState(@SW_SHOW)
   #EndRegion ### END Koda GUI section ###
     Ws_CtrlMetrics($Label1,$Label2,"") ;Si Label1 et Label2
    Ws_CtrlMetrics($Label2,$Label1,"");Si Label2 et Label1
    Ws_CtrlMetrics($Label1,$Label3,"") ;Label1 et Label3
    Ws_CtrlMetrics($Label2,$Label3,"") ;Label2 et Label3
   While 1
      $nMsg = GUIGetMsg()
      Switch $nMsg
         Case $GUI_EVENT_CLOSE
            Exit

         Case $Form1
         Case $Form1
         Case $Form1
         Case $Form1
         Case $Label1
         Case $Label2
         Case $Label3
      EndSwitch
   WEnd
EndFunc   ;==>Exemple

 

Re: [R] Détecter Collision Guictrlcreate...

Posté : ven. 12 mai 2017 14:58
par jchd
... et en utilisant Abs() on a une condition à tester deux fois plus simple.