_Kurt Posted October 20, 2007 Share Posted October 20, 2007 (edited) Update2:- New $i_OnlyCorners Parameter added to only check the controls corners- _GUICtrlCheckCollision function added: easily check the collision between 2 moving controls!!Update1:- New $i_Pixel Parameter added -- Improves performance (50-90% faster)- Fixed small bug- Will first search corners of control and afterwards the parameterPurpose of project:To create a method to track collisions of a control without checking each obstacle and using lots of memory. It's great because it can check as many control obstacles as you desire and it won't slow anything down.So, instead of searching your whole GUI, like belowWe're only searching the collider control that collides with the obstacle controls, like this:Limitations:-Does not work with moving obstacle controls yet (moving colliders accepted) - See _GUICtrlCheckCollision-Will not return anything if the Collider is out of the boundaries of width/height of GUIHow it works: (Skip if not interested)I apologize for my brutal attempts to explain this, I can clarify anything if someone has a problem. What it does is creates a (fairly large) array relative to the width/height of your GUI. For example if your GUI is sized at (300, 200), it will create an array $Array[300][200]. Next, from _GUICtrlSetCollision, we take a controls X,Y,W,H coordinates and set values in $Array according to them. For example, if we had a control at (20, 50, 100, 20) -- X,Y,Width,Height -- we would set the value from $Array[20][50] to $Array[120][70] to that control ID, since X + Width = 120, and Y + Height = 70. Once our array is set, we simply call the function _GUICtrlGetCollision in the While..WEnd loop, which retrieves the Collider's position and compares it to the arrays value, so if our collider were at (30,50) which is in contact with our control, we would see that $Array[30][50] <> "" meaning that it has collided with a control.Bugs/Errors:-None Yet The Functions:expandcollapse popup;================================================================================================== ; Function Name: _GUICtrlCheckCollision($GUI, $Control1, $Control2) ; ; Parameters: $GUI: The GUI Handle (returned from GUICreate) ; $Control1: ControlID of your first control (order doesn't matter) ; $Control2: ControlID of your second control (order doesn't matter) ; ; Description: Checks for collision between two controls ; ; Requirement(s): None ; ; Return Value(s) ; On Success: Returns 1 (the controls have collided) ; On Failure: Returns 0 ; ; Author(s): _Kurt ;================================================================================================== Func _GUICtrlCheckCollision($GUI, $Control1, $Control2) $1pos = ControlGetPos($GUI, "", $Control1) $2pos = ControlGetPos($GUI, "", $Control2) $X1 = $1pos[0] $Y1 = $1pos[1] $W1 = $1pos[2]+$1pos[0] $H1 = $1pos[3]+$1pos[1] $X2 = $2pos[0] $Y2 = $2pos[1] $W2 = $2pos[2]+$2pos[0] $H2 = $2pos[3]+$2pos[1] If $X1 >= $X2 AND $X1 <= $W2 Then If $Y1 >= $Y2 AND $Y1 <= $H2 Then Return 1 If $H1 >= $Y2 AND $H1 <= $H2 Then Return 1 EndIf If $W1 >= $X2 AND $W1 <= $W2 Then If $H1 >= $Y2 AND $H1 <= $H2 Then Return 1 If $Y1 >= $Y2 AND $Y1 <= $H2 Then Return 1 EndIf If $X1 <= $X2 AND $Y1 <= $Y2 Then If $W1 >= $X2 AND $H1 >= $Y2 Then Return 1 If $W1 >= $W2 AND $H1 >= $H2 Then Return 1 EndIf If $X1 >= $X2 AND $X1 <= $W2 AND $Y1 <= $Y2 Then If $W1 >= $W2 AND $H1 >= $H2 Then Return 1 EndIf If $Y1 >= $Y2 AND $X1 <= $X2 AND $Y1 <= $H2 Then If $H1 >= $H2 AND $W1 >= $W2 Then Return 1 EndIf Return 0 EndFunc ;================================================================================================== ; Function Name: _GUICtrlGetCollision($GUI, $i_Collider [, $i_Pixel = 2 [, $i_Perimeter = 1 [, $i_OnlyCorners = 0]]]) ; ; Parameters: $GUI: The GUI Handle (returned from GUICreate) ; $i_Collider: ControlID of your desired Collider ; $i_Pixel: (optional) The number of pixels to skip, default is 2, meaning that it will search ; every other pixel within the $Collider's perimeter. The higher the number, ; the faster the function will go. ; $i_Perimeter: (optional) 0 = Check each pixel of the whole control ; 1 = (default & recommended) Check the perimeter of the control ; $i_OnlyCorners: (optional) 0 = (default) Check the whole perimeter of the control ; 1 = Only check the corners of the control (MUCH faster) ; ; Description: Checks for any controls that has collided with a desired control ; ; Requirement(s): Must use _GUICtrlSetCollision on your desired Obstacles ; ; Return Value(s) ; On Success: Returns the corresponding controlID that has collided with $Collider ; On Failure: Returns -1 , No control is colliding with the $Collider ; Returns -2 , _GUICtrlSetCollision was not previously called, ; so the function has nothing to search for. ; ; Author(s): _Kurt ;================================================================================================== Func _GUICtrlGetCollision($GUI, $i_Collider, $i_Pixel = 2, $i_Perimeter = 1, $i_OnlyCorners = 0) If NOT IsArray($Data) Then Return -2 Local $Array = 0 $ColliderPos = ControlGetPos($GUI, "", $i_Collider) $X = $ColliderPos[0] $Y = $ColliderPos[1] $W = $ColliderPos[2] $H = $ColliderPos[3] $1Dim = UBound($Data) $2Dim = UBound($Data,2) If $W > $1Dim-1 Then $W = $1Dim-1 If $H > $2Dim-1 Then $H = $2Dim-1 If $Y > $2Dim-1 Then $Y = $2Dim-1 If $X < 0 Then $X = 0 If GUICtrlGetHandle($Data[$X][$Y]) <> 0 AND $i_Collider <> $Data[$X][$Y] Then Return $Data[$X][$Y] If GUICtrlGetHandle($Data[$X+$W][$Y]) <> 0 AND $i_Collider <> $Data[$X+$W][$Y] Then Return $Data[$X+$W][$Y] If GUICtrlGetHandle($Data[$X][$Y+$H]) <> 0 AND $i_Collider <> $Data[$X][$Y+$H] Then Return $Data[$X][$Y+$H] If GUICtrlGetHandle($Data[$X+$W][$Y+$H]) <> 0 AND $i_Collider <> $Data[$X+$W][$Y+$H] Then Return $Data[$X+$W][$Y+$H] If $i_OnlyCorners = 1 Then Return -1 If $i_Perimeter = 0 Then For $z = 0 To $W Step $i_Pixel If $Data[$X+$z][$Y] <> "" Then If GUICtrlGetHandle($Data[$X+$z][$Y]) <> 0 AND $i_Collider <> $Data[$X+$z][$Y] Then Return $Data[$X+$z][$Y] Else $Data[$X+$z][$Y] = "" EndIf EndIf If $Data[$X+$z][$Y+$H] <> "" Then If GUICtrlGetHandle($Data[$X+$z][$Y+$H]) <> 0 AND $i_Collider <> $Data[$X+$z][$Y+$H] Then Return $Data[$X+$z][$Y+$H] Else $Data[$X+$z][$Y+$H] = "" EndIf EndIf Next For $a = 0 To $H Step $i_Pixel If $Data[$X][$Y+$a] <> "" Then If GUICtrlGetHandle($Data[$X][$Y+$a]) <> 0 AND $i_Collider <> $Data[$X][$Y+$a] Then Return $Data[$X][$Y+$a] Else $Data[$X][$Y+$a] = "" EndIf EndIf If $Data[$X+$W][$Y] <> "" Then If GUICtrlGetHandle($Data[$X][$Y+$a]) <> 0 AND $i_Collider <> $Data[$X][$Y+$a] Then Return $Data[$X][$Y+$a] Else $Data[$X][$Y+$a] = "" EndIf EndIf Next Else For $z = 0 To $W Step $i_Pixel For $a = 0 To $H Step $i_Pixel If $Data[$X+$z][$Y+$a] <> "" Then If GUICtrlGetHandle($Data[$X+$z][$Y+$a]) <> 0 AND $i_Collider <> $Data[$X+$z][$Y+$a] Then Return $Data[$X+$z][$Y+$a] Else $Data[$X+$z][$Y+$a] = "" EndIf EndIf Next Next EndIf Return -1 EndFunc ;================================================================================================== ; Function Name: _GUICtrlSetCollision($GUI, $Ctrl) ; ; Parameters: $GUI: The GUI Handle (returned from GUICreate) ; $Ctrl: The ControlID of the desired obstacle ; ; Description: Sets data that will be used in _GUICtrlGetCollision ; ; Requirement(s): None ; ; Return Value(s) ; On Success: Returns 1 ; On Failure: Returns -1 , your GUI handle or ControlID is not valid ; ; Author(s): _Kurt ;================================================================================================== Func _GUICtrlSetCollision($GUIhandle, $Ctrl) If WinGetHandle($GUIhandle) = "" Or GUICtrlGetHandle($Ctrl) = 0 Then Return -1 If IsDeclared("Data") = 0 Then $GUISize = WinGetPos($GUIhandle) Global $Data[$GUISize[2]+1][$GUISize[3]+1] EndIf If NOT IsArray($Data) Then $GUISize = WinGetPos($GUIhandle) Global $Data[$GUISize[2]+1][$GUISize[3]+1] EndIf $CTRLSize = ControlGetPos($GUIhandle, "", $Ctrl) For $i = 0 To $CTRLSize[2] For $x = 0 To $CTRLSize[3] $Data[$CTRLSize[0]+$i][$CTRLSize[1]+$x] = $Ctrl Next Next Return 1 EndFuncoÝ÷ Ø ÞÅ©©æ®¶sd÷D¶W6WBgV÷C·´DõtçÒgV÷C²ÂgV÷C´Ö÷fTF÷vâgV÷C²´ÆÂöbFW6R÷F¶WV@¤÷D¶W6WBgV÷C·µUÒgV÷C²ÂgV÷C´Ö÷fUWgV÷C²¶gVæ7Föç2&R6×Ǥ÷D¶W6WBgV÷C·´ÄTeGÒgV÷C²ÂgV÷C´Ö÷fTÆVgBgV÷C²¶f÷"FW7FærW'÷6W0¤÷D¶W6WBgV÷C·µ$tGÒgV÷C²ÂgV÷C´Ö÷fU&vBgV÷C²¤vÆö&Âb33c´FF¢b33c¶væDuTÒuT7&VFRgV÷C´6öÆÆ6öâFW7BgV÷C²ÂCÂC¢b33c´×6öÆÆFW"ÒuT7G&Ä7&VFT'WGFöâgV÷C²gV÷C²ÂÂÂ3Â3²fÇC²ÒÒ÷W"uT6öçG&öÂFB6â6öÆÆFRvF÷FW"6öçG&öÇ0 ¢b33c´×Æ&VÂÒwV7G&Ä7&VFTÆ&VÂgV÷C³ÓÒgV÷C²ÂsÂ3Â#Â#¤uT7G&Å6WD&´6öÆ÷"ÓÃdddddb ¢b33c´×'WGFöâÒuT7G&Ä7&VFT'WGFöâgV÷C³ÓÒgV÷C²ÂSÂ#Â#Â#¤uT7G&Å6WD&´6öÆ÷"ÓÃdddddb¥ôuT7G&Å6WD6öÆÆ6öâb33c¶væDuTÂb33c´×'WGFöâ²b333²b333´Õõ%DåBb333²b333²vR6WBF2âGfæ6P ¢b33c´×÷FW$'WGFöâÒuT7G&Ä7&VFT'WGFöâgV÷C³ÓÒgV÷C²ÂÂ3´æ÷FS¢æ÷FærvÆÂVâöæ6R6öÆÆFVBvFF2'WGFöà¤uT7G&Å6WD&´6öÆ÷"ÓÃdddddb·6æ6RôuT7G&Å6WD6öÆÆ6öâ2æ÷B&VVâ6WBvFF26öçG&öÄ@¤uT7G&Ä7&VFTÆ&VÂgV÷CµF2'WGFöâvÆÂæ÷BfRçVffV7B6æ6RôuT7G&Å6WD6öÆÆ6öâv2æ÷B6WBFòF26öçG&öÄBgV÷C²ÂÂ3#RÂcÂS¤uT6WE7FFR¥vÆR 6ÆVW bôuT7G&Ä6V6´6öÆÆ6öâb33c¶væDuTÂb33c´×Æ&VÂÂb33c´×6öÆÆFW"FVà FööÅFgV÷C²b33c´×Æ&VÂæBb33c´×6öÆÆFW"fR6öÆÆFVBgV÷C² VÇ6P FööÅFgV÷C²gV÷C² VæD` ³³²6V6²6öÆÆ6öç2³³° ²b33c´6V6´6öÆÆ6öâÒÓ b33c´6V6´6öÆÆ6öâÒôuT7G&ÄvWD6öÆÆ6öâb33c¶væDuTÂb33c´×6öÆÆFW"ÂR´fæBå6öçG&öÂg&öÒôuT7G&Å6WD6öÆÆ6öà °·FB26öÆÆFVBvFb33c´×6öÆÆFW bb33c´6V6´6öÆÆ6öâfÇC²fwC²ÓFVâ´bFR6V6²FöW6âb33·BfÂÖVæærB&WGW&æVB6öçG&öÄB bb33c´6V6´6öÆÆ6öâÒb33c´×'WGFöâFVâ×6t&÷ÂgV÷C²gV÷C²ÂgV÷C²b33c´×6öÆÆFW"26öÆÆFVBvFb33c´×'WGFöâgV÷C² uT7G&ÄFVÆWFRb33c´6V6´6öÆÆ6öâ´FVÆWFRFR6öçG&öÀ VæD` ³³²uTWfVçG2³³° b33c¶×6rÒuTvWD×6r bb33c¶×6rÒÓ2FVâW@¥tVæ@ £³³²Ö÷færgVæ7Föç2³³° ¤gVæ2Ö÷fTF÷vâ b33c·÷2Ò6öçG&öÄvWE÷2b33c¶væDuTÂgV÷C²gV÷C²Âb33c´×6öÆÆFW" uT7G&Å6WE÷2b33c´×6öÆÆFW"Âb33c·÷5³ÒÂb33c·÷5³Ò³b¤VæDgVæ0 ¤gVæ2Ö÷fUW b33c·÷2Ò6öçG&öÄvWE÷2b33c¶væDuTÂgV÷C²gV÷C²Âb33c´×6öÆÆFW" uT7G&Å6WE÷2b33c´×6öÆÆFW"Âb33c·÷5³ÒÂb33c·÷5³ÒÓb¤VæDgVæ0 ¤gVæ2Ö÷fTÆVgB b33c·÷2Ò6öçG&öÄvWE÷2b33c¶væDuTÂgV÷C²gV÷C²Âb33c´×6öÆÆFW" uT7G&Å6WE÷2b33c´×6öÆÆFW"Âb33c·÷5³ÒÓbÂb33c·÷5³Ò¤VæDgVæ0 ¤gVæ2Ö÷fU&vB b33c·÷2Ò6öçG&öÄvWE÷2b33c¶væDuTÂgV÷C²gV÷C²Âb33c´×6öÆÆFW" uT7G&Å6WE÷2b33c´×6öÆÆFW"Âb33c·÷5³Ò³bÂb33c·÷5³Ò¤VæDgVæI'd like to hear some feedback on what people think of the idea, Thanks.Kurt Edited November 11, 2007 by _Kurt Awaiting Diablo III.. Link to comment Share on other sites More sharing options...
BananaFredSoft Posted October 20, 2007 Share Posted October 20, 2007 (edited) This is great! My _IsOn function isn't that good, so I've been looking for something like this for a while. Edited October 20, 2007 by BananaFredSoft -ColinSite:www.bananafredsoft.comStuff:Simple Text Editor - MediaPlayer - Animator - BananaDB - BananaNotes - Chatta - Filesearch - Excuse GeneratorMy YouTube channel:http://www.youtube.com/user/colipat Link to comment Share on other sites More sharing options...
_Kurt Posted October 20, 2007 Author Share Posted October 20, 2007 Thanks, and the best thing is: No matter how many obstacle controls you have, it won't slow it down at all since we're searching the array relative to the $Collider's position. Kurt Awaiting Diablo III.. Link to comment Share on other sites More sharing options...
Jex Posted October 20, 2007 Share Posted October 20, 2007 Im created that example but if $Block collide with $Left or $Right not work true and i cant understand what im did wrong : expandcollapse popupHotKeySet("{LEFT}", "MoveLeft") HotKeySet("{RIGHT}", "MoveRight") Global $Data, $Left = True, $Right = True $Form = GUICreate("Test", 633, 449, 193, 115) $Block = GUICtrlCreateButton("", 208, 400, 193, 25, 0) $Bottom = GUICtrlCreateButton("", 8, 432, 617, 9, 0) _GUICtrlSetCollision($Form, $Bottom) $Left = GUICtrlCreateButton("", 8, 16, 9, 417, 0) _GUICtrlSetCollision($Form, $Left) $Top = GUICtrlCreateButton("", 8, 8, 617, 9, 0) _GUICtrlSetCollision($Form, $Top) $Right = GUICtrlCreateButton("", 616, 16, 9, 417, 0) _GUICtrlSetCollision($Form, $Right) $Ball = GUICtrlCreateRadio("<--- Ball", 304, 48, 57, 17) _GUICtrlSetCollision($Form, $Ball) GUISetState() While 1 $msg = GUIGetMsg() If $msg = -3 Then Exit WEnd Func CheckCollision() Sleep(10) $CheckCollisionBall = _GUICtrlGetCollision($Form, $Ball) If $CheckCollisionBall <> -1 Then ;If $CheckCollisionBall = $Top Then Down() ;If $CheckCollisionBall = $Block Then Up() ;If $CheckCollisionBall = $Bottom Then Lose() EndIf $CheckCollisionBlock = _GUICtrlGetCollision($Form, $Block) If $CheckCollisionBlock <> -1 Then If $CheckCollisionBall = $Left Then $Left = False If $CheckCollisionBall = $Right Then $Right = False EndIf EndFunc Func MoveLeft() CheckCollision() If $Left = True Then $xPos = ControlGetPos($Form, "", $Block) GUICtrlSetPos($Block, $xPos[0]-10, $xPos[1]) $Right = True Else MsgBox("","","You can't go left!") MoveRight() EndIf EndFunc Func MoveRight() CheckCollision() If $Right = True Then $xPos = ControlGetPos($Form, "", $Block) GUICtrlSetPos($Block, $xPos[0]+10, $xPos[1]) $Left = True Else MsgBox("","","You can't go right!") MoveLeft() EndIf EndFunc My scripts : Immediate Window , My Web Browser , Travian , Text Effect , Characters & Words per minute or second , Image Editor (ImageMagick) , Matrix style background effect ( Screensaver ) , Mail Sender , Protectlinks decoder and Rapidshare links checker , Fonts Fetcher , Region determine , Compare pictures , Gradient color box , Mouse Coordinates, Colors, Pixel Search things , Encrypt/Decrypt and embeding file in jpeg thing , Hard disk space monitor , Reflex game , Multiplayer Tic Tac Toe , WLM ( MSN ) personal message changer Link to comment Share on other sites More sharing options...
_Kurt Posted October 20, 2007 Author Share Posted October 20, 2007 (edited) Note: These functions will not work with moving obstacles - See _GUICtrlCheckCollision Im created that example but if $Block collide with $Left or $Right not work true and i cant understand what im did wrong :You didn't call the function wrong, but instead your MoveLeft/MoveRight functions weren't correct, I fixed em up for you: Func CheckCollision() $CheckCollisionBlock = _GUICtrlGetCollision($Form, $Block) If $CheckCollisionBlock <> -1 Then If $CheckCollisionBlock = $Left Then $Left = False If $CheckCollisionBlock = $Right Then $Right = False EndIf EndFunc Func MoveLeft() CheckCollision() $xPos = ControlGetPos($Form, "", $Block) If $Left = True Then GUICtrlSetPos($Block, $xPos[0]-10, $xPos[1]) Else GUICtrlSetPos($Block, $xPos[0]+10, $xPos[1]) MsgBox("","","You can't go left!") $Left = True EndIf EndFunc Func MoveRight() CheckCollision() $xPos = ControlGetPos($Form, "", $Block) If $Right = True Then GUICtrlSetPos($Block, $xPos[0]+10, $xPos[1]) Else GUICtrlSetPos($Block, $xPos[0]-10, $xPos[1]) MsgBox("","","You can't go right!") $Right = True EndIf EndFunc I realized that calling CheckCollision() slows down the movement a lot, I will be working on a new feature to make this function much faster. I will post a solution within an hour, hold tight till then. Thanks for a second example, and post any other problems you have. Kurt EDIT: Just realized, in your code, you declared $Left & $Right for a button and a True/False string, that was your problem too! Edited November 11, 2007 by _Kurt Awaiting Diablo III.. Link to comment Share on other sites More sharing options...
_Kurt Posted October 21, 2007 Author Share Posted October 21, 2007 Updated, see first post. I added in the working example that Jex helped with. Kurt Awaiting Diablo III.. Link to comment Share on other sites More sharing options...
_Kurt Posted November 11, 2007 Author Share Posted November 11, 2007 Updated again for those who care Added new function: _GUICtrlCheckCollision - Will check the collision between 2 moving controls I will be coming up with a really cool game I created using these functions. Kurt Awaiting Diablo III.. Link to comment Share on other sites More sharing options...
BananaFredSoft Posted November 20, 2007 Share Posted November 20, 2007 I get an error: Array variable subscript badly formatted.: $Data[$CTRLSize[0]+$i][$CTRLSize[1]+$x] = $Ctrl $Data[^ ERROR Any help? -ColinSite:www.bananafredsoft.comStuff:Simple Text Editor - MediaPlayer - Animator - BananaDB - BananaNotes - Chatta - Filesearch - Excuse GeneratorMy YouTube channel:http://www.youtube.com/user/colipat Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now