LarsJ Posted July 9, 2015 Share Posted July 9, 2015 I don't think I'm using an offset (but I have not created any code). The zero point of the coordinate system corresponds to the zero point of the window. And then I'm using coordinates relative to the window. Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
nitekram Posted July 9, 2015 Author Share Posted July 9, 2015 I mean, as for the dotted lines, they are outside of the main rectangle, so is that half of the solid rectangle added to the the outside. IE solid rectangle is width = 100, height = 50, so dotted line rectangle, in your example: X1 = 50, X2 = 150, Y1 = 25, Y2 = 75? 2¢ All by me:"Sometimes you have to go back to where you started, to get to where you want to go." "Everybody catches up with everyone, eventually" "As you teach others, you are really teaching yourself." From my dad "Do not worry about yesterday, as the only thing that you can control is tomorrow." WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2 AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit Docs SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language Programming Tips Excel Changes ControlHover.UDF GDI_Plus Draw_On_Screen GDI Basics GDI_More_Basics GDI Rotate GDI Graph GDI CheckExistingItems GDI Trajectory Replace $ghGDIPDll with $__g_hGDIPDll DLL 101? Array via Object GDI Swimlane GDI Plus French 101 Site GDI Examples UEZ GDI Basic Clock GDI Detection Ternary operator Link to comment Share on other sites More sharing options...
nitekram Posted July 9, 2015 Author Share Posted July 9, 2015 (edited) I have created the code, but have the same issues as I had with my posted code - the corners seem to be off on my example as well as yours and UEZ.Func _CheckLocation($iCtrl, $iX, $iY) Local $xOffSet = 30 Static $wtf Local $aCtrlPos = ControlGetPos($g_hGUI, "", $g_aCtrls[$iCtrl][0]) For $x = 0 To UBound($g_aCtrls) - 1 If $iCtrl = $x Then ContinueLoop ; For $y = 0 To 4 #cs If _WinAPI_PtInRectEx($iX, $iY, $g_aCtrls[$x][10] - $aCtrlPos[2] - $xOffSet, $g_aCtrls[$x][11] - $aCtrlPos[3] - $xOffSet, $g_aCtrls[$x][10] + $aCtrlPos[2] + $xOffSet, $g_aCtrls[$x][11] + $aCtrlPos[3] + $xOffSet) Then ;_ Return False EndIf #ce $xOffSet = 20 Local $__X1, $__X2, $__Y1, $__Y2, $__Mx, $__My ; If $x1 < $mx And $mx < $x2 And $y1 < $my And $my < $y2 Then ; Collision $__X1 = $g_aCtrls[$x][10] - $g_aCtrls[$x][12] - $xOffSet $__X2 = $g_aCtrls[$x][10] + $g_aCtrls[$x][12] + $xOffSet $__Y1 = $g_aCtrls[$x][11] - $g_aCtrls[$x][13] - $xOffSet $__Y2 = $g_aCtrls[$x][11] + $g_aCtrls[$x][13] + $xOffSet $__Mx = $iX $__My = $iY If $__X1 < $__Mx And $__Mx < $__X2 And $__Y1 < $__My And $__My < $__Y2 Then Return False ;If $g_aCtrls[$x][10] - $g_aCtrls[$x][12] / 2 < $iX And $iX < $g_aCtrls[$x][10] + $g_aCtrls[$x][12] * 2 And $g_aCtrls[$x][13] - < $iY And $iY < $y2 Then ; Collision Next ; Next Return True EndFunc ;==>_CheckLocation ..EDITI do not know what my thoughts were, so I cleared it up Edited July 9, 2015 by nitekram cleared it up 2¢ All by me:"Sometimes you have to go back to where you started, to get to where you want to go." "Everybody catches up with everyone, eventually" "As you teach others, you are really teaching yourself." From my dad "Do not worry about yesterday, as the only thing that you can control is tomorrow." WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2 AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit Docs SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language Programming Tips Excel Changes ControlHover.UDF GDI_Plus Draw_On_Screen GDI Basics GDI_More_Basics GDI Rotate GDI Graph GDI CheckExistingItems GDI Trajectory Replace $ghGDIPDll with $__g_hGDIPDll DLL 101? Array via Object GDI Swimlane GDI Plus French 101 Site GDI Examples UEZ GDI Basic Clock GDI Detection Ternary operator Link to comment Share on other sites More sharing options...
nitekram Posted July 10, 2015 Author Share Posted July 10, 2015 Actually, I think I had the your code wrong, as I was taking it from the upper left hand corner and not the middle, but now I am unable to get the conditions correct? 2¢ All by me:"Sometimes you have to go back to where you started, to get to where you want to go." "Everybody catches up with everyone, eventually" "As you teach others, you are really teaching yourself." From my dad "Do not worry about yesterday, as the only thing that you can control is tomorrow." WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2 AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit Docs SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language Programming Tips Excel Changes ControlHover.UDF GDI_Plus Draw_On_Screen GDI Basics GDI_More_Basics GDI Rotate GDI Graph GDI CheckExistingItems GDI Trajectory Replace $ghGDIPDll with $__g_hGDIPDll DLL 101? Array via Object GDI Swimlane GDI Plus French 101 Site GDI Examples UEZ GDI Basic Clock GDI Detection Ternary operator Link to comment Share on other sites More sharing options...
nitekram Posted July 11, 2015 Author Share Posted July 11, 2015 (edited) @LarsJAny ideas, if I leave the conditions the way they are, the image never moves. So I added your idea to the existing code - using the center as the condition, and the _WinAPI_PtInRectEx(), as with using your initial condition, the images never moved? (I think I am doing it right), but the issue with the corners is worse than it was with the other examples. Func _CheckLocation($iCtrl, $iX, $iY) If $iCtrl < 0 Then Return Local $xOffSet = 30 Static $wtf Local $aCtrlPos = ControlGetPos($g_hGUI, "", $g_aCtrls[$iCtrl][0]) For $x = 0 To UBound($g_aCtrls) - 1 If $iCtrl = $x Then ContinueLoop ; For $y = 0 To 4 $__X1 = $g_aCtrls[$x][10] - $g_aCtrls[$x][12] - $xOffSet $__X2 = $g_aCtrls[$x][10] + $g_aCtrls[$x][12] + $xOffSet $__Y1 = $g_aCtrls[$x][11] - $g_aCtrls[$x][13] - $xOffSet / 2 $__Y2 = $g_aCtrls[$x][11] + $g_aCtrls[$x][13] + $xOffSet / 2 $__Mx = $aCtrlPos[0] + $aCtrlPos[2] / 2; $iX $__My = $aCtrlPos[1] + $aCtrlPos[3] / 2; $iY If _WinAPI_PtInRectEx($iX, $iY, $__X1, $__Y1, $__X2, $__Y2) Then ;_ Return False EndIf Next ; Next Return True EndFunc ;==>_CheckLocation ;EDITNothing to edit...I was checking if I could edit it - yeah, no more period after all my code, as that was the only way I could edit it since the last update (if my code was the last entry FF) Edited July 11, 2015 by nitekram 2¢ All by me:"Sometimes you have to go back to where you started, to get to where you want to go." "Everybody catches up with everyone, eventually" "As you teach others, you are really teaching yourself." From my dad "Do not worry about yesterday, as the only thing that you can control is tomorrow." WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2 AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit Docs SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language Programming Tips Excel Changes ControlHover.UDF GDI_Plus Draw_On_Screen GDI Basics GDI_More_Basics GDI Rotate GDI Graph GDI CheckExistingItems GDI Trajectory Replace $ghGDIPDll with $__g_hGDIPDll DLL 101? Array via Object GDI Swimlane GDI Plus French 101 Site GDI Examples UEZ GDI Basic Clock GDI Detection Ternary operator Link to comment Share on other sites More sharing options...
LarsJ Posted July 12, 2015 Share Posted July 12, 2015 (edited) This is the way I would implement rectangle collision detection.I have changed the strategy a little bit. Instead of using the midpoint for collision detection I'm using upper/left corner. But I'm still only using one point. When you divide by two to calculate the midpoint, you have to deal with half pixels every second time. Half a pixel is not a good thing. Using upper/left corner all calculations are simple integer calculations.Using upper/left corner the dotted rectangle to test collisions looks like this:And this is the example code to illustrate the method:expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> AutoItSetOption( "GUIOnEventMode", 1 ) AutoItSetOption( "MouseCoordMode", 2 ) ; Relative to window AutoItSetOption( "MustDeclareVars", 1 ) AutoItSetOption( "WinWaitDelay", 10 ) ; Only used to draw debug info Global Const $iTitleBarHeight = 30 Global Const $iBorderWidth = _WinAPI_GetSystemMetrics( $SM_CXFRAME ) Global $hGui, $iGuiWidth, $iGuiHeight, $aInfo, $fRedraw = False Global $idGuiMenuItem0, $idGuiMenuItem1, $idGuiMenuItem2, $idGuiMenuItem3, $idGuiMenuItem4, _ $idGuiMenuItem5, $idGuiMenuItem6, $idGuiMenuItem7, $idGuiMenuItem8, $idGuiMenuItem9 ; Information about the rectangles Global $aRects[1000][8], $iRects = 0 ; 0: $idLabel ; 1 - 4: $x, $y, $w, $h ; Pos, size ; 5 - 6: $wx, $wy ; Window collision boundaries ; 7: $iColor Example() Func Example() ; Create GUI $hGui = GUICreate( "Rectangle collision detection", 800, 600, -1, -1, $WS_OVERLAPPEDWINDOW - $WS_MAXIMIZEBOX + $WS_CLIPCHILDREN ) GUISetOnEvent( $GUI_EVENT_RESIZED, "Resized" ) GUISetOnEvent( $GUI_EVENT_CLOSE, "Close" ) ; Window context menu Local $idGuiMenu = GUICtrlCreateContextMenu() $idGuiMenuItem0 = GUICtrlCreateMenuItem( "Create rectangle", $idGuiMenu ) $idGuiMenuItem1 = GUICtrlCreateMenuItem( "Create 5 rects", $idGuiMenu ) $idGuiMenuItem2 = GUICtrlCreateMenuItem( "Create 10 rects", $idGuiMenu ) $idGuiMenuItem3 = GUICtrlCreateMenuItem( "Create 20 rects", $idGuiMenu ) $idGuiMenuItem4 = GUICtrlCreateMenuItem( "Create 30 rects", $idGuiMenu ) $idGuiMenuItem5 = GUICtrlCreateMenuItem( "Create 40 rects", $idGuiMenu ) $idGuiMenuItem6 = GUICtrlCreateMenuItem( "Create 50 rects", $idGuiMenu ) $idGuiMenuItem7 = GUICtrlCreateMenuItem( "Create 100 rects", $idGuiMenu ) $idGuiMenuItem8 = GUICtrlCreateMenuItem( "Create 1000 rects", $idGuiMenu ) $idGuiMenuItem9 = GUICtrlCreateMenuItem( "Delete all rectangles", $idGuiMenu ) GUICtrlSetOnEvent( $idGuiMenuItem0, "CreateRectangle" ) GUICtrlSetOnEvent( $idGuiMenuItem1, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem2, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem3, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem4, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem5, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem6, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem7, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem8, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem9, "DeleteAllRects" ) ; Window size Local $aSize = WinGetClientSize( $hGui ) $iGuiWidth = $aSize[0] $iGuiHeight = $aSize[1] ; Show GUI GUISetState() MsgBox( 0, "Rectangle collision detection", _ "Secondary click to open context menu with items to create rectangles (random colored labels)." & @CRLF & _ "Click and drag with primary mouse button to define size of rectangle (limited to 4x4 - 200x200)." & @CRLF & @CRLF & _ "Click and drag a rectangle with primary mouse button to check collisions against window borders" & @CRLF & _ "and stationary rectangles." & @CRLF & @CRLF & _ "Secondary click a rectangle to open context menu to draw lines that shows collision boundaries." & @CRLF & _ "Collisions against window borders and stationary rectangles are detected with moving rectangle" & @CRLF & _ "upper/left corner. Click in free area to erase the red dotted lines that shows collision boundaries.", 0, $hGui ) Local $idLabel, $iCurRect, $aDotRects[1000][4] While 1 ; Wait for primary mouse click $aInfo = GUIGetCursorInfo() While Sleep(10) And IsArray( $aInfo ) And Not $aInfo[2] $aInfo = GUIGetCursorInfo() WEnd If Not IsArray( $aInfo ) Then ContinueLoop ; Redraw window? ; (Erase dotted rectangles) If $fRedraw Then ; Erase dotted rectangles _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) ; Repaint labels For $i = 0 To $iRects - 1 GUICtrlSetState( $aRects[$i][0], $GUI_HIDE ) ; Force a label repaint GUICtrlSetState( $aRects[$i][0], $GUI_SHOW ) Next $fRedraw = False EndIf ; Current label $idLabel = $aInfo[4] If Not $idLabel Then ContinueLoop ; Current rectangle (moving rectangle) $iCurRect = ( $idLabel - $aRects[0][0] ) / 5 ConsoleWrite( "Current rectangle: " & $iCurRect & @CRLF ) ; Calculate boundaries (red dotted lines) for all stationary rectangles to detect collisions. ; Collisions against stationary rectangles are detected with moving rectangle upper/left corner. Local $iStatRects = 0, $j = 0 For $i = 0 To $iRects - 1 If $i = $iCurRect Then ContinueLoop $aDotRects[$j][0] = $aRects[$i][1] - $aRects[$iCurRect][3] ; $x1 $aDotRects[$j][1] = $aRects[$i][2] - $aRects[$iCurRect][4] ; $y1 $aDotRects[$j][2] = $aRects[$i][1] + $aRects[$i][3] ; $x2 $aDotRects[$j][3] = $aRects[$i][2] + $aRects[$i][4] ; $y2 $j += 1 Next $iStatRects = $j ; Calculate boundaries (red dotted lines) to detect collisions against window edges. ; Collisions against window edges are detected with moving rectangle upper/left corner. Local $wx = $aRects[$iCurRect][5] + 2, $wy = $aRects[$iCurRect][6] + 2 ; Variables to calculate upper/left corner ($x,$y) of moving rectangle Local $x0 = $aInfo[0], $y0 = $aInfo[1], $x, $y Local $x1 = $aRects[$iCurRect][1] - $x0, $y1 = $aRects[$iCurRect][2] - $y0 ; Variables for collision action (flashing black/white rectangle) Local $hTimer = 0, $iCollRect, $idLblCollision, $idLblColor, $iColor = 0xFFFFFF ; Move current rectangle While $aInfo[2] $aInfo = GUIGetCursorInfo() $x = $x1 + $aInfo[0] $y = $y1 + $aInfo[1] ; Collision against window edges? ; (Collision if upper/left corner of moving rectangle ($x,$y) is outside the (0,0,$wx,$wy) rectangle) If Not ( 0 <= $x And $x < $wx And 0 <= $y And $y < $wy ) Then ContinueLoop ; Collision against stationary rectangles? ; (Collision if upper/left corner of moving rectangle ($x,$y) is inside the $aDotRects rectangles) For $i = 0 To $iStatRects - 1 If $aDotRects[$i][0] < $x And $x < $aDotRects[$i][2] And $aDotRects[$i][1] < $y And $y < $aDotRects[$i][3] Then ExitLoop Next If $i < $iStatRects Then ; Collision ($i < $iStatRects => ExitLoop has been executed) If Not $hTimer Then ; Information about the collision $iCollRect = $i < $iCurRect ? $i : $i + 1 CollisionInfo( $x, $y, $iCurRect, $iCollRect ) ; Start collision action (flashing rectangle) $idLblCollision = $aRects[$iCollRect][0] $idLblColor = $aRects[$iCollRect][7] GUICtrlSetBkColor( $idLblCollision, $iColor ) GUICtrlSetState( $idLblCollision, $GUI_HIDE ) ; Force a label repaint GUICtrlSetState( $idLblCollision, $GUI_SHOW ) $iColor = $iColor ? 0x000000 : 0xFFFFFF $hTimer = TimerInit() ElseIf TimerDiff( $hTimer ) > 200 Then ; Continue flashing the rectangle GUICtrlSetBkColor( $idLblCollision, $iColor ) GUICtrlSetState( $idLblCollision, $GUI_HIDE ) ; Force a label repaint GUICtrlSetState( $idLblCollision, $GUI_SHOW ) $iColor = $iColor ? 0x000000 : 0xFFFFFF $hTimer = TimerInit() EndIf ; Add code to execute on collision here ;ContinueLoop ; Skip GUICtrlSetPos below ElseIf $hTimer Then ; No collision ; If collision action is started then stop it $hTimer = 0 GUICtrlSetBkColor( $idLblCollision, $idLblColor ) GUICtrlSetState( $idLblCollision, $GUI_HIDE ) ; Flashing rectangle GUICtrlSetState( $idLblCollision, $GUI_SHOW ) ; Force a label repaint GUICtrlSetBkColor( $idLabel, $aRects[$iCurRect][7] ) ; Moving rectangle GUICtrlSetState( $idLabel, $GUI_HIDE ) ; Force a label repaint GUICtrlSetState( $idLabel, $GUI_SHOW ) EndIf ; Set new position of current rectangle GUICtrlSetPos( $idLabel, $x, $y ) WEnd ; Store new position of current rectangle $aRects[$iCurRect][1] += $aInfo[0] - $x0 $aRects[$iCurRect][2] += $aInfo[1] - $y0 WEnd EndFunc Func CollisionInfo( $x, $y, $iCurRect, $iCollRect ) ConsoleWrite( "Collision against rect: " & $iCollRect & @CRLF ) Select Case $x + $aRects[$iCurRect][3] - $aRects[$iCollRect][1] < 4 ; Left edge Select Case $y + $aRects[$iCurRect][4] - $aRects[$iCollRect][2] < 4 ; Upper edge ConsoleWrite( " At upper/left corner" & @CRLF ) Case $aRects[$iCollRect][2] + $aRects[$iCollRect][4] - $y < 4 ; Lower edge ConsoleWrite( " At lower/left corner" & @CRLF ) Case Else ConsoleWrite( " At left edge" & @CRLF ) EndSelect Case $y + $aRects[$iCurRect][4] - $aRects[$iCollRect][2] < 4 ; Upper edge Select Case $x + $aRects[$iCurRect][3] - $aRects[$iCollRect][1] < 4 ; Left edge ConsoleWrite( " At upper/left corner" & @CRLF ) Case $aRects[$iCollRect][1] + $aRects[$iCollRect][3] - $x < 4 ; Right edge ConsoleWrite( " At upper/right corner" & @CRLF ) Case Else ConsoleWrite( " At upper edge" & @CRLF ) EndSelect Case $aRects[$iCollRect][1] + $aRects[$iCollRect][3] - $x < 4 ; Right edge Select Case $y + $aRects[$iCurRect][4] - $aRects[$iCollRect][2] < 4 ; Upper edge ConsoleWrite( " At upper/right corner" & @CRLF ) Case $aRects[$iCollRect][2] + $aRects[$iCollRect][4] - $y < 4 ; Lower edge ConsoleWrite( " At lower/right corner" & @CRLF ) Case Else ConsoleWrite( " At right edge" & @CRLF ) EndSelect Case $aRects[$iCollRect][2] + $aRects[$iCollRect][4] - $y < 4 ; Lower edge Select Case $x + $aRects[$iCurRect][3] - $aRects[$iCollRect][1] < 4 ; Left edge ConsoleWrite( " At lower/left corner" & @CRLF ) Case $aRects[$iCollRect][1] + $aRects[$iCollRect][3] - $x < 4 ; Right edge ConsoleWrite( " At lower/right corner" & @CRLF ) Case Else ConsoleWrite( " At lower edge" & @CRLF ) EndSelect EndSelect EndFunc Func CreateRectangle() If $fRedraw Then ; Erase red dotted rectangles if any exists _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) $fRedraw = False EndIf ; Wait max. 2 seconds to start rectangle creation WinSetTitle( $hGui, "", "Click and drag rectangle with primary mouse button" ) Local $iWait = 0 While Sleep(10) $iWait += 1 If $iWait = 200 Then WinSetTitle( $hGui, "", "Rectangle collision detection" ) Return EndIf If GUIGetCursorInfo()[2] Then ExitLoop WEnd WinSetTitle( $hGui, "", "Rectangle collision detection" ) ; Create rectangle (label control) Local $aInfo = GUIGetCursorInfo(), $x = $aInfo[0], $y = $aInfo[1], $w = 0, $h = 0, $dw, $dh Local $iColor = Random(0,255,1)*256*256 + Random(0,255,1)*256 + Random(0,255,1) Local $idLabel = GUICtrlCreateLabel( "", $x, $y, $w, $h ) GUICtrlSetResizing( $idLabel, $GUI_DOCKALL ) GUICtrlSetBkColor( $idLabel, $iColor ) ; Drag with mouse to define rectangle size until it's at least 4x4 pixels While $aInfo[2] And ( $dw < 4 Or $dh < 4 ) $aInfo = GUIGetCursorInfo() $dw = $aInfo[0] - $x $dh = $aInfo[1] - $y If $dw < 200 Then $w = $dw If $dh < 200 Then $h = $dh GUICtrlSetPos( $idLabel, $x, $y, $w, $h ) Sleep(10) WEnd ; Drag with mouse to define rectangle size between 4x4 and 200x200 pixels While $aInfo[2] $aInfo = GUIGetCursorInfo() $dw = $aInfo[0] - $x $dh = $aInfo[1] - $y If 4 < $dw And $dw < 200 Then $w = $dw If 4 < $dh And $dh < 200 Then $h = $dh GUICtrlSetPos( $idLabel, $x, $y, $w, $h ) Sleep(10) WEnd ; Cancel if not rectangle size is between 4x4 and 200x200 pixels If Not ( 4 < $w And $w < 200 And 4 < $h And $h < 200 And $iRects < 100 ) Then GUICtrlDelete( $idLabel ) Return EndIf ; Create and store rectangle info in $aRects CreateRectInfo( $x, $y, $w, $h, $idLabel, $iColor ) EndFunc Func CreateMultipleRects() If $fRedraw Then ; Erase red dotted rectangles if any exists _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) $fRedraw = False EndIf ; Delete all rectangles DeleteAllRects() ; Number of rectangles Local $n, $hw = 200 Switch @GUI_CtrlId Case $idGuiMenuItem1 $n = 5 Case $idGuiMenuItem2 $n = 10 Case $idGuiMenuItem3 $n = 20 Case $idGuiMenuItem4 $n = 30 Case $idGuiMenuItem5 $n = 40 Case $idGuiMenuItem6 $n = 50 Case $idGuiMenuItem7 $n = 100 $hw = 100 Case $idGuiMenuItem8 $n = 1000 $hw = 20 EndSwitch ; Create rectangles Local $x = 10, $y = 10, $yMax = 0, $w, $h For $i = 0 To $n - 1 ; Rectangle width/height $w = Random(4,$hw,1) $h = Random(4,$hw,1) If $x + $w > $iGuiWidth Then ; New row of rectangles $x = 10 $y = $yMax + 10 EndIf If $y + $h > $iGuiHeight Then ; Cancel if GUI too small for all rectangles ConsoleWrite( "Created rectangles: " & $i & @CRLF ) Return EndIf ; Create rectangle Local $iColor = Random(0,255,1)*256*256 + Random(0,255,1)*256 + Random(0,255,1) Local $idLabel = GUICtrlCreateLabel( "", $x, $y, $w, $h ) GUICtrlSetResizing( $idLabel, $GUI_DOCKALL ) GUICtrlSetBkColor( $idLabel, $iColor ) CreateRectInfo( $x, $y, $w, $h, $idLabel, $iColor ) GUICtrlSetState( $idLabel, $GUI_HIDE ) ; Force a label repaint GUICtrlSetState( $idLabel, $GUI_SHOW ) ; Update $yMax and $x If $y + $h > $yMax Then $yMax = $y + $h $x += $w + 10 Next ConsoleWrite( "Created rectangles: " & $n & @CRLF ) EndFunc ; Create and store rectangle info in $aRects Func CreateRectInfo( $x, $y, $w, $h, $idLabel, $iColor ) Local $idMenu = GUICtrlCreateContextMenu( $idLabel ) ; Debug menu Local $idMenuItem1 = GUICtrlCreateMenuItem( "Rectangle information", $idMenu ) Local $idMenuItem2 = GUICtrlCreateMenuItem( "Window collision boundaries", $idMenu ) Local $idMenuItem3 = GUICtrlCreateMenuItem( "Rectangles collision boundaries", $idMenu ) GUICtrlSetOnEvent( $idMenuItem1, "RectangleInformation" ) GUICtrlSetOnEvent( $idMenuItem2, "DrawWinCollisionBounds" ) GUICtrlSetOnEvent( $idMenuItem3, "DrawRectsCollisionBounds" ) $aRects[$iRects][0] = $idLabel $aRects[$iRects][1] = $x ; Pos $aRects[$iRects][2] = $y $aRects[$iRects][3] = $w ; Size $aRects[$iRects][4] = $h $aRects[$iRects][5] = $iGuiWidth - $w ; Window collision boundaries $aRects[$iRects][6] = $iGuiHeight - $h $aRects[$iRects][7] = $iColor $iRects += 1 EndFunc Func DeleteAllRects() For $i = 0 To $iRects - 1 GUICtrlDelete( $aRects[$i][0] ) ; $idLabel GUICtrlDelete( $aRects[$i][0]+1 ) ; $idMenu GUICtrlDelete( $aRects[$i][0]+2 ) ; $idMenuItem1 GUICtrlDelete( $aRects[$i][0]+3 ) ; $idMenuItem2 GUICtrlDelete( $aRects[$i][0]+4 ) ; $idMenuItem3 Next $iRects = 0 EndFunc ; If the window is resized, the col- ; lision boundaries must be recalculated. Func Resized() Local $aSize = WinGetClientSize( $hGui ) $iGuiWidth = $aSize[0] $iGuiHeight = $aSize[1] For $i = 0 To $iRects - 1 $aRects[$i][5] = $iGuiWidth - $aRects[$i][3] ; Window collision boundaries $aRects[$i][6] = $iGuiHeight - $aRects[$i][4] Next EndFunc Func Close() GUIDelete() Exit EndFunc ; --- Debug functions -------------------------------------------------------------------------------------------------- ; Rectangle information in SciTE console Func RectangleInformation() If Not $aInfo[4] Then Return ; $idLabel (current rectangle) Local $iCurRect = ( $aInfo[4] - $aRects[0][0] ) / 5 ; Current rectangle as index in $aRects If $fRedraw Then _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) ; Erase previous red dotted rectangles ConsoleWrite( "Current rectangle: " & $iCurRect & @CRLF ) ConsoleWrite( " $idLabel: " & $aRects[$iCurRect][0] & @CRLF ) ConsoleWrite( " ($x,$y): (" & $aRects[$iCurRect][1] & "," & $aRects[$iCurRect][2] & ")" & @CRLF ) ConsoleWrite( " ($w,$h): (" & $aRects[$iCurRect][3] & "," & $aRects[$iCurRect][4] & ")" & @CRLF ) ConsoleWrite( " $iColor: " & "0x" & Hex( $aRects[$iCurRect][7], 6 ) & @CRLF ) $fRedraw = False EndFunc ; Draw red dotted lines that shows the ; collision boundaries to the window edges. Func DrawWinCollisionBounds() If Not $aInfo[4] Then Return ; $idLabel (current rectangle) Local $iCurRect = ( $aInfo[4] - $aRects[0][0] ) / 5 ; Current rectangle as index in $aRects If $fRedraw Then _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) ; Erase previous red dotted rectangles DrawRedDottedRect( 0, 0, $aRects[$iCurRect][5], $aRects[$iCurRect][6] ) ; 0, 0, $wx, $wy EndFunc ; Draw red dotted lines that shows the ; collision boundaries to other rectangles. Func DrawRectsCollisionBounds() If Not $aInfo[4] Then Return ; $idLabel (current rectangle) Local $iCurRect = ( $aInfo[4] - $aRects[0][0] ) / 5 ; Current rectangle as index in $aRects If $fRedraw Then _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) ; Erase previous red dotted rectangles For $i = 0 To $iRects - 1 If $i = $iCurRect Then ContinueLoop DrawRedDottedRect( $aRects[$i][1] - $aRects[$iCurRect][3], _ ; $x1 $aRects[$i][2] - $aRects[$iCurRect][4], _ ; $y1 $aRects[$i][1] + $aRects[$i][3], _ ; $x2 $aRects[$i][2] + $aRects[$i][4] ) ; $y2 Next EndFunc Func DrawRedDottedRect( $p1x, $p1y, $p2x, $p2y ) Local $x1 = $p1x + $iBorderWidth - 1, $y1 = $p1y + $iTitleBarHeight - 1, $x2 = $p2x + $iBorderWidth, $y2 = $p2y + $iTitleBarHeight Local $hDC = _WinAPI_GetWindowDC( $hGui ), $hPen = _WinAPI_CreatePen( $PS_DOT, 1, 0x0000FF ), $hObj = _WinAPI_SelectObject( $hDC, $hPen ) _WinAPI_DrawLine( $hDC, $x1, $y1, $x2, $y1 ) _WinAPI_DrawLine( $hDC, $x2, $y1, $x2, $y2 ) _WinAPI_DrawLine( $hDC, $x2, $y2, $x1, $y2 ) _WinAPI_DrawLine( $hDC, $x1, $y2, $x1, $y1 ) _WinAPI_SelectObject( $hDC, $hObj ) _WinAPI_DeleteObject( $hPen ) _WinAPI_ReleaseDC( $hGui, $hDC ) $fRedraw = True EndFuncSecondary click in window to create rectangles.Secondary click a rectangle to draw red dotted collision boundaries.Primary click and drag to move a rectangle.The loop to test collisions with the moving rectangle against the stationary rectangles is very simple and very fast:; Collision against stationary rectangles? ; (Collision if upper/left corner of moving rectangle ($x,$y) is inside the $aDotRects rectangles) For $i = 0 To $iStatRects - 1 If $aDotRects[$i][0] < $x And $x < $aDotRects[$i][2] And $aDotRects[$i][1] < $y And $y < $aDotRects[$i][3] Then ExitLoop NextOn my old XP i can test collisions against 1000 stationary rectangles in about 2.5 milliseconds. Edited July 12, 2015 by LarsJ UEZ 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
UEZ Posted July 12, 2015 Share Posted July 12, 2015 LarsJ,very nice example. Thanks for sharing. Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
nitekram Posted July 14, 2015 Author Share Posted July 14, 2015 Thanks for your very cool example. I have not been able to figure it all out, but believe I got the basic understanding. But I still have the same issue. I believe your way is probably faster, though I have not tested any for quickness.The issue, is that the when you stop the interaction, the moving box (rectangle) from hitting the stationary box, the issue arises, where to put the box. If I use your ContinueLoop, in the for loop, it stops the box from hitting, but as in the other examples the box does not always stop at the same place - like there is a lag, and the mouse continues to move across the box, while the box stops short or right next to the collision point. Meaning there is no consistent resting point for the moving box and it will stop anywhere near the collision point. Maybe the issue might be resolved by keeping the mouse stationary during moving (and primary button pressed), and stop moving at point of collision? If not, I am still looking at the conditions being meant to move the moving box, to its final resting point, not to exceed the boundaries of the collision.I have no clue if I am making it clear what I am seeing. 2¢ All by me:"Sometimes you have to go back to where you started, to get to where you want to go." "Everybody catches up with everyone, eventually" "As you teach others, you are really teaching yourself." From my dad "Do not worry about yesterday, as the only thing that you can control is tomorrow." WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2 AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit Docs SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language Programming Tips Excel Changes ControlHover.UDF GDI_Plus Draw_On_Screen GDI Basics GDI_More_Basics GDI Rotate GDI Graph GDI CheckExistingItems GDI Trajectory Replace $ghGDIPDll with $__g_hGDIPDll DLL 101? Array via Object GDI Swimlane GDI Plus French 101 Site GDI Examples UEZ GDI Basic Clock GDI Detection Ternary operator Link to comment Share on other sites More sharing options...
LarsJ Posted July 14, 2015 Share Posted July 14, 2015 There is a lag. The rectangle will always be slightly behind the mouse. This is a consequence of AutoIt as an interpreted language. AutoIt is not fast enough. You need a compiled language to avoid the lag.You have to set the position of the rectangle when you detect a collision to make sure that the rectangle is in a consistent state.UEZ, You are welcome. Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
nitekram Posted July 17, 2015 Author Share Posted July 17, 2015 I have had no luck setting the position, as it is still off one way or the other. I think the best bet is to have the mouse attach itself to the object/image/rectangle and then allow the mouse to move the object - this I believe would deal with the lag. I have done it by accident, a couple times, though I have no way to replicate it.Does anyone know how to make the mouse attach, and then de-attach itself once set in the position (meaning the mouse if released)? 2¢ All by me:"Sometimes you have to go back to where you started, to get to where you want to go." "Everybody catches up with everyone, eventually" "As you teach others, you are really teaching yourself." From my dad "Do not worry about yesterday, as the only thing that you can control is tomorrow." WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2 AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit Docs SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language Programming Tips Excel Changes ControlHover.UDF GDI_Plus Draw_On_Screen GDI Basics GDI_More_Basics GDI Rotate GDI Graph GDI CheckExistingItems GDI Trajectory Replace $ghGDIPDll with $__g_hGDIPDll DLL 101? Array via Object GDI Swimlane GDI Plus French 101 Site GDI Examples UEZ GDI Basic Clock GDI Detection Ternary operator Link to comment Share on other sites More sharing options...
LarsJ Posted July 18, 2015 Share Posted July 18, 2015 (edited) When I set the position of the rectangle with this code, I can do it quite accurate and consistent. Even for rapid mouse movements.expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> AutoItSetOption( "GUIOnEventMode", 1 ) AutoItSetOption( "MouseCoordMode", 2 ) ; Relative to window AutoItSetOption( "MustDeclareVars", 1 ) AutoItSetOption( "WinWaitDelay", 10 ) ; Only used to draw debug info Global Const $iTitleBarHeight = 30 Global Const $iBorderWidth = _WinAPI_GetSystemMetrics( $SM_CXFRAME ) Global $hGui, $iGuiWidth, $iGuiHeight, $aInfo, $fRedraw = False Global $idGuiMenuItem0, $idGuiMenuItem1, $idGuiMenuItem2, $idGuiMenuItem3, $idGuiMenuItem4, _ $idGuiMenuItem5, $idGuiMenuItem6, $idGuiMenuItem7, $idGuiMenuItem8, $idGuiMenuItem9 ; Information about the rectangles Global $aRects[1000][8], $iRects = 0 ; 0: $idLabel ; 1 - 4: $x, $y, $w, $h ; Pos, size ; 5 - 6: $wx, $wy ; Window collision boundaries ; 7: $iColor Example() Func Example() ; Create GUI $hGui = GUICreate( "Rectangle collision detection", 800, 600, -1, -1, $WS_OVERLAPPEDWINDOW - $WS_MAXIMIZEBOX + $WS_CLIPCHILDREN ) GUISetOnEvent( $GUI_EVENT_RESIZED, "Resized" ) GUISetOnEvent( $GUI_EVENT_CLOSE, "Close" ) ; Window context menu Local $idGuiMenu = GUICtrlCreateContextMenu() $idGuiMenuItem0 = GUICtrlCreateMenuItem( "Create rectangle", $idGuiMenu ) $idGuiMenuItem1 = GUICtrlCreateMenuItem( "Create 5 rects", $idGuiMenu ) $idGuiMenuItem2 = GUICtrlCreateMenuItem( "Create 10 rects", $idGuiMenu ) $idGuiMenuItem3 = GUICtrlCreateMenuItem( "Create 20 rects", $idGuiMenu ) $idGuiMenuItem4 = GUICtrlCreateMenuItem( "Create 30 rects", $idGuiMenu ) $idGuiMenuItem5 = GUICtrlCreateMenuItem( "Create 40 rects", $idGuiMenu ) $idGuiMenuItem6 = GUICtrlCreateMenuItem( "Create 50 rects", $idGuiMenu ) $idGuiMenuItem7 = GUICtrlCreateMenuItem( "Create 100 rects", $idGuiMenu ) $idGuiMenuItem8 = GUICtrlCreateMenuItem( "Create 1000 rects", $idGuiMenu ) $idGuiMenuItem9 = GUICtrlCreateMenuItem( "Delete all rectangles", $idGuiMenu ) GUICtrlSetOnEvent( $idGuiMenuItem0, "CreateRectangle" ) GUICtrlSetOnEvent( $idGuiMenuItem1, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem2, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem3, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem4, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem5, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem6, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem7, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem8, "CreateMultipleRects" ) GUICtrlSetOnEvent( $idGuiMenuItem9, "DeleteAllRects" ) ; Window size Local $aSize = WinGetClientSize( $hGui ) $iGuiWidth = $aSize[0] $iGuiHeight = $aSize[1] ; Show GUI GUISetState() MsgBox( 0, "Rectangle collision detection", _ "Secondary click to open context menu with items to create rectangles (random colored labels)." & @CRLF & _ "Click and drag with primary mouse button to define size of rectangle (limited to 4x4 - 200x200)." & @CRLF & @CRLF & _ "Click and drag a rectangle with primary mouse button to check collisions against window borders" & @CRLF & _ "and stationary rectangles." & @CRLF & @CRLF & _ "Secondary click a rectangle to open context menu to draw lines that shows collision boundaries." & @CRLF & _ "Collisions against window borders and stationary rectangles are detected with moving rectangle" & @CRLF & _ "upper/left corner. Click in free area to erase the red dotted lines that shows collision boundaries.", 0, $hGui ) Local $idLabel, $iCurRect, $aDotRects[1000][4] While 1 ; Wait for primary mouse click $aInfo = GUIGetCursorInfo() While Sleep(10) And IsArray( $aInfo ) And Not $aInfo[2] $aInfo = GUIGetCursorInfo() WEnd If Not IsArray( $aInfo ) Then ContinueLoop ; Redraw window? ; (Erase dotted rectangles) If $fRedraw Then ; Erase dotted rectangles _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) ; Repaint labels For $i = 0 To $iRects - 1 GUICtrlSetState( $aRects[$i][0], $GUI_HIDE ) ; Force a label repaint GUICtrlSetState( $aRects[$i][0], $GUI_SHOW ) Next $fRedraw = False EndIf ; Current label $idLabel = $aInfo[4] If Not $idLabel Then ContinueLoop ; Current rectangle (moving rectangle) $iCurRect = ( $idLabel - $aRects[0][0] ) / 5 ConsoleWrite( "Current rectangle: " & $iCurRect & @CRLF ) ; Calculate boundaries (red dotted lines) for all stationary rectangles to detect collisions. ; Collisions against stationary rectangles are detected with moving rectangle upper/left corner. Local $iStatRects = 0, $j = 0 For $i = 0 To $iRects - 1 If $i = $iCurRect Then ContinueLoop $aDotRects[$j][0] = $aRects[$i][1] - $aRects[$iCurRect][3] ; $x1 $aDotRects[$j][1] = $aRects[$i][2] - $aRects[$iCurRect][4] ; $y1 $aDotRects[$j][2] = $aRects[$i][1] + $aRects[$i][3] ; $x2 $aDotRects[$j][3] = $aRects[$i][2] + $aRects[$i][4] ; $y2 $j += 1 Next $iStatRects = $j ; Calculate boundaries (red dotted lines) to detect collisions against window edges. ; Collisions against window edges are detected with moving rectangle upper/left corner. Local $wx = $aRects[$iCurRect][5] + 2, $wy = $aRects[$iCurRect][6] + 2 ; Variables to calculate upper/left corner ($x,$y) of moving rectangle Local $x0 = $aInfo[0], $y0 = $aInfo[1], $x, $y Local $x1 = $aRects[$iCurRect][1] - $x0, $y1 = $aRects[$iCurRect][2] - $y0 ; Variables for collision action (position moving rectangle at collision edge) Local $fCollision = 0, $iCollRect, $iCollEdge, $xColl, $yColl ; Move current rectangle While $aInfo[2] $aInfo = GUIGetCursorInfo() $x = $x1 + $aInfo[0] $y = $y1 + $aInfo[1] ; Collision against window edges? ; (Collision if upper/left corner of moving rectangle ($x,$y) is outside the (0,0,$wx,$wy) rectangle) If Not ( 0 <= $x And $x < $wx And 0 <= $y And $y < $wy ) Then ContinueLoop ; Collision against stationary rectangles? ; (Collision if upper/left corner of moving rectangle ($x,$y) is inside the $aDotRects rectangles) For $i = 0 To $iStatRects - 1 If $aDotRects[$i][0] < $x And $x < $aDotRects[$i][2] And $aDotRects[$i][1] < $y And $y < $aDotRects[$i][3] Then ExitLoop Next If $i < $iStatRects Then ; Collision ($i < $iStatRects => ExitLoop has been executed) If Not $fCollision Then ; Information about the collision $iCollRect = $i < $iCurRect ? $i : $i + 1 $iCollEdge = CollisionInfo( $x, $y, $iCurRect, $iCollRect ) Switch $iCollEdge Case 1 ; Left $xColl = $aRects[$iCollRect][1] - $aRects[$iCurRect][3] Case 2 ; Upper $yColl = $aRects[$iCollRect][2] - $aRects[$iCurRect][4] Case 3 ; Right $xColl = $aRects[$iCollRect][1] + $aRects[$iCollRect][3] Case 4 ; Lower $yColl = $aRects[$iCollRect][2] + $aRects[$iCollRect][4] EndSwitch $fCollision = 1 EndIf Switch $iCollEdge Case 1, 3 ; Left, Right GUICtrlSetPos( $idLabel, $xColl, $y ) Case 2, 4 ; Upper, Lower GUICtrlSetPos( $idLabel, $x, $yColl ) EndSwitch ContinueLoop ElseIf $fCollision Then ; No collision $fCollision = 0 EndIf ; Set new position of current rectangle GUICtrlSetPos( $idLabel, $x, $y ) WEnd ; Store new position of current rectangle If $fCollision Then Switch $iCollEdge Case 1, 3 ; Left, Right $aRects[$iCurRect][1] = $xColl $aRects[$iCurRect][2] += $aInfo[1] - $y0 Case 2, 4 ; Upper, Lower $aRects[$iCurRect][1] += $aInfo[0] - $x0 $aRects[$iCurRect][2] = $yColl EndSwitch Else $aRects[$iCurRect][1] += $aInfo[0] - $x0 $aRects[$iCurRect][2] += $aInfo[1] - $y0 EndIf WEnd EndFunc Func CollisionInfo( $x, $y, $iCurRect, $iCollRect ) ConsoleWrite( "Collision against rect: " & $iCollRect & @CRLF ) Select Case $x + $aRects[$iCurRect][3] - $aRects[$iCollRect][1] < 20 ; Left edge ; Use a high value (20) to compensate for rapid mouse movements ConsoleWrite( " At left edge" & @CRLF ) Return 1 Case $y + $aRects[$iCurRect][4] - $aRects[$iCollRect][2] < 20 ; Upper edge ConsoleWrite( " At upper edge" & @CRLF ) Return 2 Case $aRects[$iCollRect][1] + $aRects[$iCollRect][3] - $x < 20 ; Right edge ConsoleWrite( " At right edge" & @CRLF ) Return 3 Case $aRects[$iCollRect][2] + $aRects[$iCollRect][4] - $y < 20 ; Lower edge ConsoleWrite( " At lower edge" & @CRLF ) Return 4 EndSelect EndFunc Func CreateRectangle() If $fRedraw Then ; Erase red dotted rectangles if any exists _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) $fRedraw = False EndIf ; Wait max. 2 seconds to start rectangle creation WinSetTitle( $hGui, "", "Click and drag rectangle with primary mouse button" ) Local $iWait = 0 While Sleep(10) $iWait += 1 If $iWait = 200 Then WinSetTitle( $hGui, "", "Rectangle collision detection" ) Return EndIf If GUIGetCursorInfo()[2] Then ExitLoop WEnd WinSetTitle( $hGui, "", "Rectangle collision detection" ) ; Create rectangle (label control) Local $aInfo = GUIGetCursorInfo(), $x = $aInfo[0], $y = $aInfo[1], $w = 0, $h = 0, $dw, $dh Local $iColor = Random(0,255,1)*256*256 + Random(0,255,1)*256 + Random(0,255,1) Local $idLabel = GUICtrlCreateLabel( "", $x, $y, $w, $h ) GUICtrlSetResizing( $idLabel, $GUI_DOCKALL ) GUICtrlSetBkColor( $idLabel, $iColor ) ; Drag with mouse to define rectangle size until it's at least 4x4 pixels While $aInfo[2] And ( $dw < 4 Or $dh < 4 ) $aInfo = GUIGetCursorInfo() $dw = $aInfo[0] - $x $dh = $aInfo[1] - $y If $dw < 200 Then $w = $dw If $dh < 200 Then $h = $dh GUICtrlSetPos( $idLabel, $x, $y, $w, $h ) Sleep(10) WEnd ; Drag with mouse to define rectangle size between 4x4 and 200x200 pixels While $aInfo[2] $aInfo = GUIGetCursorInfo() $dw = $aInfo[0] - $x $dh = $aInfo[1] - $y If 4 < $dw And $dw < 200 Then $w = $dw If 4 < $dh And $dh < 200 Then $h = $dh GUICtrlSetPos( $idLabel, $x, $y, $w, $h ) Sleep(10) WEnd ; Cancel if not rectangle size is between 4x4 and 200x200 pixels If Not ( 4 < $w And $w < 200 And 4 < $h And $h < 200 And $iRects < 100 ) Then GUICtrlDelete( $idLabel ) Return EndIf ; Create and store rectangle info in $aRects CreateRectInfo( $x, $y, $w, $h, $idLabel, $iColor ) EndFunc Func CreateMultipleRects() If $fRedraw Then ; Erase red dotted rectangles if any exists _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) $fRedraw = False EndIf ; Delete all rectangles DeleteAllRects() ; Number of rectangles Local $n, $hw = 200 Switch @GUI_CtrlId Case $idGuiMenuItem1 $n = 5 Case $idGuiMenuItem2 $n = 10 Case $idGuiMenuItem3 $n = 20 Case $idGuiMenuItem4 $n = 30 Case $idGuiMenuItem5 $n = 40 Case $idGuiMenuItem6 $n = 50 Case $idGuiMenuItem7 $n = 100 $hw = 100 Case $idGuiMenuItem8 $n = 1000 $hw = 20 EndSwitch ; Create rectangles Local $x = 10, $y = 10, $yMax = 0, $w, $h For $i = 0 To $n - 1 ; Rectangle width/height $w = Random(4,$hw,1) $h = Random(4,$hw,1) If $x + $w > $iGuiWidth Then ; New row of rectangles $x = 10 $y = $yMax + 10 EndIf If $y + $h > $iGuiHeight Then ; Cancel if GUI too small for all rectangles ConsoleWrite( "Created rectangles: " & $i & @CRLF ) Return EndIf ; Create rectangle Local $iColor = Random(0,255,1)*256*256 + Random(0,255,1)*256 + Random(0,255,1) Local $idLabel = GUICtrlCreateLabel( "", $x, $y, $w, $h ) GUICtrlSetResizing( $idLabel, $GUI_DOCKALL ) GUICtrlSetBkColor( $idLabel, $iColor ) CreateRectInfo( $x, $y, $w, $h, $idLabel, $iColor ) GUICtrlSetState( $idLabel, $GUI_HIDE ) ; Force a label repaint GUICtrlSetState( $idLabel, $GUI_SHOW ) ; Update $yMax and $x If $y + $h > $yMax Then $yMax = $y + $h $x += $w + 10 Next ConsoleWrite( "Created rectangles: " & $n & @CRLF ) EndFunc ; Create and store rectangle info in $aRects Func CreateRectInfo( $x, $y, $w, $h, $idLabel, $iColor ) Local $idMenu = GUICtrlCreateContextMenu( $idLabel ) ; Debug menu Local $idMenuItem1 = GUICtrlCreateMenuItem( "Rectangle information", $idMenu ) Local $idMenuItem2 = GUICtrlCreateMenuItem( "Window collision boundaries", $idMenu ) Local $idMenuItem3 = GUICtrlCreateMenuItem( "Rectangles collision boundaries", $idMenu ) GUICtrlSetOnEvent( $idMenuItem1, "RectangleInformation" ) GUICtrlSetOnEvent( $idMenuItem2, "DrawWinCollisionBounds" ) GUICtrlSetOnEvent( $idMenuItem3, "DrawRectsCollisionBounds" ) $aRects[$iRects][0] = $idLabel $aRects[$iRects][1] = $x ; Pos $aRects[$iRects][2] = $y $aRects[$iRects][3] = $w ; Size $aRects[$iRects][4] = $h $aRects[$iRects][5] = $iGuiWidth - $w ; Window collision boundaries $aRects[$iRects][6] = $iGuiHeight - $h $aRects[$iRects][7] = $iColor $iRects += 1 EndFunc Func DeleteAllRects() For $i = 0 To $iRects - 1 GUICtrlDelete( $aRects[$i][0] ) ; $idLabel GUICtrlDelete( $aRects[$i][0]+1 ) ; $idMenu GUICtrlDelete( $aRects[$i][0]+2 ) ; $idMenuItem1 GUICtrlDelete( $aRects[$i][0]+3 ) ; $idMenuItem2 GUICtrlDelete( $aRects[$i][0]+4 ) ; $idMenuItem3 Next $iRects = 0 EndFunc ; If the window is resized, the col- ; lision boundaries must be recalculated. Func Resized() Local $aSize = WinGetClientSize( $hGui ) $iGuiWidth = $aSize[0] $iGuiHeight = $aSize[1] For $i = 0 To $iRects - 1 $aRects[$i][5] = $iGuiWidth - $aRects[$i][3] ; Window collision boundaries $aRects[$i][6] = $iGuiHeight - $aRects[$i][4] Next EndFunc Func Close() GUIDelete() Exit EndFunc ; --- Debug functions -------------------------------------------------------------------------------------------------- ; Rectangle information in SciTE console Func RectangleInformation() If Not $aInfo[4] Then Return ; $idLabel (current rectangle) Local $iCurRect = ( $aInfo[4] - $aRects[0][0] ) / 5 ; Current rectangle as index in $aRects If $fRedraw Then _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) ; Erase previous red dotted rectangles ConsoleWrite( "Current rectangle: " & $iCurRect & @CRLF ) ConsoleWrite( " $idLabel: " & $aRects[$iCurRect][0] & @CRLF ) ConsoleWrite( " ($x,$y): (" & $aRects[$iCurRect][1] & "," & $aRects[$iCurRect][2] & ")" & @CRLF ) ConsoleWrite( " ($w,$h): (" & $aRects[$iCurRect][3] & "," & $aRects[$iCurRect][4] & ")" & @CRLF ) ConsoleWrite( " $iColor: " & "0x" & Hex( $aRects[$iCurRect][7], 6 ) & @CRLF ) $fRedraw = False EndFunc ; Draw red dotted lines that shows the ; collision boundaries to the window edges. Func DrawWinCollisionBounds() If Not $aInfo[4] Then Return ; $idLabel (current rectangle) Local $iCurRect = ( $aInfo[4] - $aRects[0][0] ) / 5 ; Current rectangle as index in $aRects If $fRedraw Then _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) ; Erase previous red dotted rectangles DrawRedDottedRect( 0, 0, $aRects[$iCurRect][5], $aRects[$iCurRect][6] ) ; 0, 0, $wx, $wy EndFunc ; Draw red dotted lines that shows the ; collision boundaries to other rectangles. Func DrawRectsCollisionBounds() If Not $aInfo[4] Then Return ; $idLabel (current rectangle) Local $iCurRect = ( $aInfo[4] - $aRects[0][0] ) / 5 ; Current rectangle as index in $aRects If $fRedraw Then _WinAPI_RedrawWindow( $hGui, 0, 0, $RDW_INVALIDATE + $RDW_ERASE ) ; Erase previous red dotted rectangles For $i = 0 To $iRects - 1 If $i = $iCurRect Then ContinueLoop DrawRedDottedRect( $aRects[$i][1] - $aRects[$iCurRect][3], _ ; $x1 $aRects[$i][2] - $aRects[$iCurRect][4], _ ; $y1 $aRects[$i][1] + $aRects[$i][3], _ ; $x2 $aRects[$i][2] + $aRects[$i][4] ) ; $y2 Next EndFunc Func DrawRedDottedRect( $p1x, $p1y, $p2x, $p2y ) Local $x1 = $p1x + $iBorderWidth - 1, $y1 = $p1y + $iTitleBarHeight - 1, $x2 = $p2x + $iBorderWidth, $y2 = $p2y + $iTitleBarHeight Local $hDC = _WinAPI_GetWindowDC( $hGui ), $hPen = _WinAPI_CreatePen( $PS_DOT, 1, 0x0000FF ), $hObj = _WinAPI_SelectObject( $hDC, $hPen ) _WinAPI_DrawLine( $hDC, $x1, $y1, $x2, $y1 ) _WinAPI_DrawLine( $hDC, $x2, $y1, $x2, $y2 ) _WinAPI_DrawLine( $hDC, $x2, $y2, $x1, $y2 ) _WinAPI_DrawLine( $hDC, $x1, $y2, $x1, $y1 ) _WinAPI_SelectObject( $hDC, $hObj ) _WinAPI_DeleteObject( $hPen ) _WinAPI_ReleaseDC( $hGui, $hDC ) $fRedraw = True EndFuncI have been testing with two rectangles like these:The large rectangle is stationary.nitekram, Have you tried to test collision detection only with the mouse pointer. When the mouse pointer is inside the rectangle, there is a collision. If you move the mouse really fast, you'll probably see, that the mouse pointer can be 20 - 30 pixels inside the rectangle, before the collision is detected. I don't think there is anything to do about this problem. You will need to address the problem in the code. Edited July 18, 2015 by LarsJ Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
nitekram Posted July 21, 2015 Author Share Posted July 21, 2015 I will have to take a look at this, as it has much better response than anything I tried. 2¢ All by me:"Sometimes you have to go back to where you started, to get to where you want to go." "Everybody catches up with everyone, eventually" "As you teach others, you are really teaching yourself." From my dad "Do not worry about yesterday, as the only thing that you can control is tomorrow." WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2 AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit Docs SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language Programming Tips Excel Changes ControlHover.UDF GDI_Plus Draw_On_Screen GDI Basics GDI_More_Basics GDI Rotate GDI Graph GDI CheckExistingItems GDI Trajectory Replace $ghGDIPDll with $__g_hGDIPDll DLL 101? Array via Object GDI Swimlane GDI Plus French 101 Site GDI Examples UEZ GDI Basic Clock GDI Detection Ternary operator 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