Jump to content

Wall Collision Question


aquila
 Share

Recommended Posts

Hello,

i have to push this topic here again.

Now,

the algorithim of martins does only work, if I have 2 rooms by 90° each other? Well. The map could be a little different.

Like this:

post-32742-12654746081744_thumb.jpg

Now i thought, I could make "areas" in this map. So i check if the coords of the ppl are in the same area and so I know, that they see each other. But if they aren't in the same area, they could see each other too. So I try to use the function you posted some posts ago but I don't rly know, how to use it :D I need a function with parameters of the area coords and the player coords, or sth. like that.

post-32742-12654747487139_thumb.jpg

Link to comment
Share on other sites

I have possibly a better solution. I have written a script to do wall detection and its UDF for the most part. Here it is:

Basically you pass in the whole square that your needing to search and the function calculates everything inside. $object is what your searching for so basically the other green dot. $arrayColorCheck is an array variable which basically is your wall. The reason I made it an array is because a wall can have multiple colors on it. $shade is of course your shade variation. And this is a handle based function so handle to the window your searching. This will return a true or false value letting you know if you can make it to $object. So set $object to a Global variable so that your other functions can see it and utilize the coords that it returns upon success.

Func searchforObject($x1, $y1, $x2, $y2, $object, $shade, $handle, $arrayColorcheck)
    $center_x = Int(($x2 - $x1) / 2); + $x2                                                                             ;Calculate center the center of two given points
    $center_y = Int(($y2 - $y1) / 2); + $y2                                                                             ;Calculate center the center of two given points
    $coords = PixelSearch($x1, $y1, $x2, $y2, $object, 0, 0, $handle)                                               ;Search new gui map that was created for an object with the color $object
    If Not @error Then
        $origObjectX = $coords[0] 
        $origObjectY = $coords[1]
        $screenPos = determineScreenPos($center_x, $center_y, $coords)                                              ;Determine the quadrant of a square with the division being the center position of that square
        $pathClear = startWalking($coords, $center_x, $center_y, $screenPos, $shade, $handle, $arrayColorcheck)     ;Start the function that will start walking to the found object
        Return $pathClear
    EndIf
EndFunc


Func determineScreenPos($center_x, $center_y, $coords)
    If $coords[0] >= $center_x And $coords[1] >= $center_y Then 
        $screenPos = 1  ; Lower right quadrant
    ElseIf  $coords[0] >= $center_x And $coords[1] <= $center_y Then 
        $screenPos = 2      ; Upper right quadrant
    ElseIf  $coords[0] <= $center_x And $coords[1] >= $center_y Then 
        $screenPos = 3      ; Lower left quadrant
    ElseIf  $coords[0] <= $center_x And $coords[1] <= $center_y Then 
        $screenPos = 4      ; Upper Left quadrant
    EndIf
    Return $screenPos
EndFunc


Func startWalking($coords, $center_x, $center_y ,$screenPos, $shade, $handle, $arrayColorcheck)
    Select                                                                                          ;Setup the modifier x and y coordinates to determine which way to walk
        Case $screenPos = 1
            $center_x_modify = 1
            $center_y_modify = 1
        Case $screenPos = 2
            $center_x_modify = 1
            $center_y_modify = -1
        Case $screenPos = 3
            $center_x_modify = -1
            $center_y_modify = 1
        Case $screenPos = 4
            $center_x_modify = -1
            $center_y_modify = -1
    EndSelect

    Do                                                                                                                                      
        Sleep(10)                                                                                                                           ;Don't overwhelm the system
        $orig_center_x = $center_x                                                                                                          ;Keep the modified center_x position for later use
        $orig_center_y = $center_y                                                                                                          ;Keep the modified center_y position for later use
        If $center_x = $coords[0] And $center_y = $coords[1] Then ExitLoop                                                                  ;Determine if we have reached the object if we have then exit the do loop
        If $center_x <> $coords[0] Then $center_x = $center_x + $center_x_modify                                                            ;Are we horizontally in line with the object if not increment by $center_x_modify
        If $center_y <> $coords[1] Then $center_y = $center_y + $center_y_modify                                                            ;Are we vertically in line with the object if not increment by $center_y_modify
        $blockage = checkBlockage($orig_center_x, $orig_center_y, $center_x, $center_y, $shade, $handle, $screenPos, $arrayColorcheck)      ;Check if we have run into an object with the color array $arrayColorcheck
        If  $screenPos = 1  Then 
;~          _WinAPI_DrawLine($drawHandle,$orig_center_x, $orig_center_y, $center_x, $center_y)                                  ;Lower right quadrant
        ElseIf  $screenPos = 2  Then 
;~          _WinAPI_DrawLine($drawHandle,$orig_center_x, $center_y, $center_x, $orig_center_y)                                  ;Upper right quadrant
        ElseIf  $screenPos = 3  Then 
;~          _WinAPI_DrawLine($drawHandle,$center_x, $orig_center_y, $orig_center_x, $center_y)                                  ;Lower left quadrant
        ElseIf  $screenPos = 4  Then 
;~          _WinAPI_DrawLine($drawHandle,$center_x, $center_y, $orig_center_x, $orig_center_y)                                  ;Upper Left quadrant
        EndIf
    Until IsArray($blockage)
    
    If IsArray($blockage) Then                                                                                                              ;If we hit a blockage then draw a marker on the found object so that the next pixel search will skip it
        _WinAPI_DrawLine($drawHandle,$coords[0],$coords[1],$coords[0],$coords[1])
        Return False                                                                                                                        ;Return False stating that we could not get to object
    Else    
        Return True                                                                                                                         ;If we did not reach a blockage then we got to the object, return true
    EndIf
EndFunc


Func checkBlockage($orig_center_x, $orig_center_y, $center_x, $center_y, $shade, $handle, $screenPos, $arrayColorcheck)
    For $i = 0 To $arrayColorcheck[0] Step 1                                                                                                                    ;Step through each color of the array $arrayColorcheck
        If $screenPos = 1 Then
            $blockage = PixelSearch($orig_center_x, $orig_center_y, $center_x, $center_y, $arrayColorcheck[$i], $shade, 0, $handle) ;Lower right quadrant if you find a blockage then $blockage will have an array of coordinates else it will have a 1
        ElseIf  $screenPos = 2  Then 
            $blockage = PixelSearch($orig_center_x, $center_y, $center_x, $orig_center_y, $arrayColorcheck[$i], $shade, 0, $handle) ;Upper right quadrant if you find a blockage then $blockage will have an array of coordinates else it will have a 1
        ElseIf  $screenPos = 3  Then 
            $blockage = PixelSearch($center_x, $orig_center_y, $orig_center_x, $center_y, $arrayColorcheck[$i], $shade, 0, $handle) ;Lower left quadrant if you find a blockage then $blockage will have an array of coordinates else it will have a 1
        ElseIf  $screenPos = 4  Then 
            $blockage = PixelSearch($center_x, $center_y, $orig_center_x, $orig_center_y, $arrayColorcheck[$i], $shade, 0, $handle) ;Upper Left quadrant if you find a blockage then $blockage will have an array of coordinates else it will have a 1
        EndIf
        If Not @error Then
            Return $blockage
        EndIf
    Next
EndFunc
Link to comment
Share on other sites

Also, you can turn on the WinAPIDrawLine cmd's and it will draw out the line that its searching. It does this in a diagonal fashion until it reaches the destination which is of course your green dot. Keep in mind drawline will not succeed on a window that is constantly re-drawing itself. So you may not see that lines that its drawing. If this is the case the only option is a new gui of your own with a screenshot of what your searching.

It will also blot out with a red pixel the first green pixel that it found. So as not to go that way again, but keep in mind that will only happen if the window is not constantly refreshing itself. This is the part where it says If _IsArray($blockage) Then. So if you dont want it to do that then just comment out the _WinAPI_DrawLine thats in that If statement

Edited by smcombs
Link to comment
Share on other sites

Now i thought, I could make "areas" in this map. So i check if the coords of the ppl are in the same area and so I know, that they see each other. But if they aren't in the same area, they could see each other too. So I try to use the function you posted some posts ago but I don't rly know, how to use it :huggles: I need a function with parameters of the area coords and the player coords, or sth. like that.

I knew it was bound to make this turn :D

It simply isn't really the same story.

Is it for a game of something? How a given your walls?

@smcombs: the whole idea was / is to avoid any use of PixelSearch. Think of it as a theoritical problem, with no actual bitmap available: how would you then do it?

Edited by jchd

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Hello,

i have to push this topic here again.

Now,

the algorithim of martins does only work, if I have 2 rooms by 90° each other? Well. The map could be a little different.

Like this:

post-32742-12654746081744_thumb.jpg

Now i thought, I could make "areas" in this map. So i check if the coords of the ppl are in the same area and so I know, that they see each other. But if they aren't in the same area, they could see each other too. So I try to use the function you posted some posts ago but I don't rly know, how to use it :huggles: I need a function with parameters of the area coords and the player coords, or sth. like that.

post-32742-12654747487139_thumb.jpg

The basic idea was not really to do with the shape of the room as I recall, although Mat and I did produce a solution which relied on the L shape.

The basic idea is

get an equation for eac wall.

get an equation for the line between two players

if the lines intersect within the end points then they can't see each other.

So what you need is a function that has parameters like this,

Func CanSee($iPlayer1X, $iPlayer1Y, $iPlayer2X,$iPlayer2Y, $aRoom) ;returns True if can see

;Room is an array of lines like this

[0]= $m

[1]=$k;where x=my+k

[2]=Endx1;ends of line for wall

[3]=Endy1

[4]=Endx2

[5]=Endy2

Edit:I suppose if this gets done then aquilla will come back next week and say "Well I have put mirrors in some of the rooms so.." :D

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

The basic idea was not really to do with the shape of the room as I recall, although Mat and I did produce a solution which relied on the L shape.

I did as well :D

Edit:I suppose if this gets done then aquilla will come back next week and say "Well I have put mirrors in some of the rooms so.." :huggles:

Or jump to 3-D or, more elegantly, to 4-D space-time with a varying gravity field... Possibilities are endless.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

I knew it was bound to make this turn :D

It simply isn't really the same story.

Is it for a game of something? How a given your walls?

@smcombs: the whole idea was / is to avoid any use of PixelSearch. Think of it as a theoritical problem, with no actual bitmap available: how would you then do it?

Ah ok I didnt catch that. I just saw wall and green dot. And all that function does is just go from center of your square to your destination.

Link to comment
Share on other sites

  • Moderators

Hi all,

This piqued my interest and I have been trying to produce an "intervisibility" script to meet aquila's needs - it also filled in the time while I wait for my twisted knee to heal up enough to resume playing golf! :huggles:

First - some definitions:

The total area is a 100x100 grid - this is then scaled up to fit the size of the GUI.

"Players" - the 12 small red squares. The top-left corner of each "player" is the point from which all calulations are made.

"No-go area" - the grey area where players cannot go. This area can only have vertical and horizontal edges.

"Vertex" - the points where the "no-go" area changes direction.

"Zones" - these are the coloured areas on the map. They are created by the intersection of the horizontal and vertical lines extending from the "vertices".

Second - the limitations of the script:

1. I believe that the "no-go zone" must be a continous zone as shown - it cannot be broken into multiple areas.

2. The "zones" must flow in a clockwise direction - the calculations depend on the relative positions of the "Players" - and the "zone" in which they are located forms part of this. The order in which the "Players" are located has no effect. (Of interest this was the biggest problem in getting the script to work).

3. The "map" must be determined by the user beforehand and the coordinates of every "zone" and "vertex" entered in the relevent arrays. The "zones" array is made up of the "Left, Top, Right, Bottom" points of the zone - the "vertex" array is made up of the "X, Y" coordinates of the point.

4. The "Inter" array also needs to be completed by the user - it defines the vertices that are critical in determining intervisibility and also in deciding which "zones" are always/never intervisible (to save on processing time). The elements of the "Inter" array are as follows:

-2 = Never intervisible

-1 = Always intervisible

0-13 = The vertex which determines the critical point for intervisibility

If there is a "concave" area between the "zones", as is the case with zones 2 & 7, there are 2 vertices which can hide "players" from each other - in order to be intervisible, neither vertex must block. This is why there are 2 elements of this array with a floating point number - I used the decimal point as a delimiter to separate the 2 "vertex" values.

Third - how to use it!

1. Use the mouse to drag the "Players" to their required positions on the GUI. The top-left corners of the "Players" must be within a "zone" - the script wil report an error if not and exit.

2. Once the "players" are positioned, press "Calculate" to determine the intervisibility of the players. If you are interested the time taken will be displayed in the SciTE console.

3. You can now select pairs of "players" in the comboboxes and press "Check" to see if they are intervisible. The response appears just below the combos - "Visible" or "Hidden". If there is a following "*" this means that the outcome was predetermined by the "inter" array - the user had already decided the result.

4. "Reset" replaces the "Players" in their initial positions. It serves no useful purpose here, but it was already coded in the script from which i copied the "player" code and I thought "Why not?".

Finally, how it works.

The script calculates the angle each "player" makes with the critical "vertex". For the 2 "players" to be intervisible, the the angel between them must be a maximum of 180 degrees. As the vertex is a right angle, it follows that the total of the angles made by the players with the vertex must be at least 90 degress (or Pi / 2 radians). This is why the script needs to determine the correct order of the "players" to feed into the calculation - in one case the Tan of the relevant angle is (difference in x-coord) / (difference in y coord), while the other is the reverse. I hope this diagram makes it clearer - and if any mathematicians out there have a better idea - code it yourself!

post-38576-12656257571246_thumb.png

If you have stuck with me this far - here is the script:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <StaticConstants.au3>
#include <Array.au3>
#include <WinAPI.au3>

Global Const $PiOver2 = (3.14159265358979 / 2)
Global $aIntervisibility, $aLocation
Global $iZones = 13, $iVertices = 13, $iPlayers = 12

#Region
; Define Zones - the user must create this array
Global $aZones[$iZones][4] = _
                       [[70, 40,  90,  80], _  ; 0
                        [70, 80,  90, 100], _  ; 1
                        [60, 80,  70, 100], _  ; 2
                        [30, 80,  60, 100], _  ; 3
                        [30, 70,  60,  80], _  ; 4
                        [ 0, 80,  30, 100], _  ; 5
                        [ 0, 70,  30,  80], _  ; 6
                        [ 0, 20,  30,  70], _  ; 7
                        [ 0,  0,  30,  20], _  ; 8
                        [30,  0,  40,  20], _  ; 9
                        [40,  0,  60,  20], _  ; 10
                        [40, 20,  60,  50], _  ; 11
                        [60,  0, 100,  20]]    ; 12

; The colours for teh zones
Global $aColours[$iZones] = _
                       [0xFFC0C0, _ ; 0
                        0xFFFFC0, _ ; 1
                        0xC0FFC0, _ ; 2
                        0xC0C0FF, _ ; 3
                        0xFFC0C0, _ ; 4
                        0xFFFFC0, _ ; 5
                        0xC0FFC0, _ ; 6
                        0xC0C0FF, _ ; 7
                        0xFFC0C0, _ ; 8
                        0xFFFFC0, _ ; 9
                        0xC0FFC0, _ ; 10
                        0xC0C0FF, _ ; 11
                        0xFFC0C0]   ; 12

; Define critical points - the user must create this array
Global $aVertex[$iVertices][2] = _
                       [[ 90, 100], _  ; A - 0
                        [ 90,  40], _  ; B - 1
                        [ 70,  40], _  ; C - 2
                        [ 70,  80], _  ; D - 3
                        [ 60,  80], _  ; E - 4
                        [ 60,  70], _  ; F - 5
                        [ 30,  70], _  ; G - 6
                        [ 30,  20], _  ; H - 7
                        [ 40,  20], _  ; I - 8
                        [ 40,  50], _  ; J - 9
                        [ 60,  50], _  ; K - 10
                        [ 60,  20], _  ; L - 11
                        [100,  20]]    ; M - 12

; Set intervisibility matrix - the user must create this array

                    ;   0       1       2       3       4       5       6       7       8       9       10      11      12
Global $aInter[$iVertices][$iVertices] = _
                      [[-1,     -1 ,     3,     3,      -2,     3,      -2,     -2,     -2,     -2,     -2,     -2,     -2 ], _ ; 0
                       [-1,     -1,     -1,     -1,      4,     -1,      4,      4,     -2,     -2,     -2,     -2,     -2 ], _ ; 1
                       [ 3,     -1,     -1,     -1,      4,     -1,      4,      4.6,   -2,     -2,     -2,     -2,     -2 ], _ ; 2
                       [ 3,     -1,     -1,     -1,     -1,     -1,     -1,      6,      6,     -2,     -2,     -2,     -2 ], _ ; 3
                       [-2,      4,      4,     -1,     -1,     -1,     -1,      6,      6,     -2,     -2,     -2,     -2 ], _ ; 4
                       [ 3,     -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,      7,     -2,     -2,     -2 ], _ ; 5
                       [-2,      4,      4,     -1,     -1,     -1,     -1,     -1,     -1,      7,      7,     -2,     -2 ], _ ; 6
                       [-2,      4,      4.6,    6,      6,     -1,     -1,     -1,     -1,      7,      7,     -2,      7 ], _ ; 7
                       [-2,     -2,     -2,      6,      6,     -1,     -1,     -1,     -1,     -1,     -1,      8,     -1 ], _ ; 8
                       [-2,     -2,     -2,     -2,     -2,      7,      7,      7,     -1,     -1,     -1,      8,     -1 ], _ ; 9
                       [-2,     -2,     -2,     -2,     -2,     -2,      7,      7,     -1,     -1,     -1,     -1,     -1 ] , _ ; 10
                       [-2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,      8,      8,     -1,     -1,      11 ], _ ; 11
                       [-2,     -2,     -2,     -2,     -2,     -2,     -2,      7,     -1,     -1,     -1,     11,      -1]]   ; 12

#EndRegion
#Region
; Create GUI
$hGUI = GUICreate("Intervisibility Test", 500, 580, 1100, 10, -1, $WS_EX_COMPOSITED)

; Notet that as the GUI has the COMPOSITED extended style, the overlapping labels must be created in the reverse order to normal

; Show vertex corrdinates - 0 and 12 are separate to keep them fully on the main GUI
GUICtrlCreateLabel("1", ($aVertex[0][0] * 5) - 7, ($aVertex[0][1] * 5) - 13, 13, 13, BitOR($SS_CENTER, $SS_CENTERIMAGE))
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
For $i = 1 To UBound($aVertex) - 2
    GUICtrlCreateLabel($i, ($aVertex[$i][0] * 5) - 7, ($aVertex[$i][1] * 5) - 7, 13, 13, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
Next
GUICtrlCreateLabel("12", ($aVertex[$i][0] * 5) - 13, ($aVertex[$i][1] * 5) - 7, 13, 13, BitOR($SS_CENTER, $SS_CENTERIMAGE))
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)

; Show zones
For $i = 0 To $iZones - 1
    GUICtrlCreateLabel($i, $aZones[$i][0] * 5, $aZones[$i][1] * 5, ($aZones[$i][2] - $aZones[$i][0]) * 5, ($aZones[$i][3] - $aZones[$i][1]) * 5, BitOR($SS_CENTER, $SS_CENTERIMAGE))
    GUICtrlSetBkColor(-1, $aColours[$i])
Next

; Show no-go area
GUICtrlCreateLabel("", 0, 0, 500, 502)
GUICtrlSetBkColor(-1, 0xC0C0C0)

; Cretae controls at the bottom of the GUI
$hCheck_Button = GUICtrlCreateButton("Check", 10, 520, 100, 50)

$hCombo_1 = GUICtrlCreateCombo("", 140, 520, 40)
GUICtrlSetData(-1, "0|1|2|3|4|5|6|7|8|9|10|11|12")
$hCombo_2 = GUICtrlCreateCombo("", 200, 520, 40)
GUICtrlSetData(-1, "0|1|2|3|4|5|6|7|8|9|10|11|12")

$hLabel = GUICtrlCreateLabel("", 140, 550, 100, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE))

$hCalc_Button = GUICtrlCreateButton("Calculate InterVisibility", 270, 520, 100, 50, $BS_MULTILINE)
$hReset_Button = GUICtrlCreateButton("Reset", 380, 520, 50, 50)
$hExit_Button = GUICtrlCreateButton("Exit", 440, 520, 50, 50)

GUISetState()

; Create players
Global $aPlayers[$iPlayers][5] ; [0] = handle, [1] = Org X, [2] = Org Y, [3] = Curr X, [4] = Curr Y
For $i = 0 To $iPlayers - 1

    $aPlayers[$i][1] = 10
    $aPlayers[$i][2] = $i*20 + 10
    ; Creat small player GUI
    $aPlayers[$i][0] = GUICreate("", 13, 13, 10, $i*20 + 10, BitOR($WS_POPUP, $WS_BORDER), $WS_EX_TOPMOST)
    ; Use the label to drag the GUI
    GUICtrlCreateLabel(StringFormat("%2s", $i), 0, 0, 13, 13, -1, $GUI_WS_EX_PARENTDRAG)
        GUICtrlSetBkColor(-1, 0xFF0000)
        GUICtrlSetColor(-1, 0xFFFFFF)
    GUISetState()
    ; Set as child - this way the palyer can only be moved within main GUI area
    _WinAPI_SetParent($aPlayers[$i][0], $hGUI)

Next

; Get possible permutations of pairs of players to calculate
Global $aPlayer_List[$iPlayers]
For $i = 0 To $iPlayers - 1
    $aPlayer_List[$i] = $i
Next
Global $aPlayer_Perms = _ArrayCombinations($aPlayer_List, 2, ",")

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE, $hExit_Button
            Exit
        Case $hReset_Button
            ; Move all the players back to their positions, which we carefully stored on creation
            For $i = 0 To $iPlayers -1
                WinMove($aPlayers[$i][0], "", $aPlayers[$i][1], $aPlayers[$i][2])
            Next
        Case $hCalc_Button
            ; Get positions of the players on screen
            For $i = 0 To $iPlayers -1
                $aPos = WinGetPos($aPlayers[$i][0])
                $aPlayers[$i][3] = $aPos[0]
                $aPlayers[$i][4] = $aPos[1]
            Next
            ; Determine players' zones and convert screen coordinates to grid coordinates
            Global $aLocation[$iPlayers]
            _Zone_Players()
            ; Create array to hold player visibility info
            Global $aIntervisibility[$aPlayer_Perms[0]][2]
            ; Start timer
            $iBegin = TimerInit()
            ; Check intervisibility for each pair of players
            For $i = 1 To $aPlayer_Perms[0]
                $aIntervisibility[$i - 1][0] = $aPlayer_Perms[$i]
                Global $aPlayer_Pair = StringSplit($aPlayer_Perms[$i], ",")
                $aIntervisibility[$i - 1][1] = _Check_Intervisibility($aPlayer_Pair[1], $aPlayer_Pair[2])
            Next
            ; Write time
            ConsoleWrite(TimerDiff($iBegin) & @CRLF)
            ; Display overall result if required
            ;_ArrayDisplay($aInterVisibility)
        Case $hCheck_Button
            ; Get required player pair
            $sPlayer_A = GUICtrlRead($hCombo_1)
            $sPlayer_B = GUICtrlRead($hCombo_2)
            ; Check it is a valid pair
            If $sPlayer_A <> $sPlayer_B Then
                ; Get pair in correct order
                $sPlayer_Pair = $sPlayer_A & "," & $sPlayer_B
                If Number($sPlayer_A) > Number($sPlayer_B) Then $sPlayer_Pair = $sPlayer_B & "," & $sPlayer_A
                ; Search the location array for the pairing
                $iIndex = _ArraySearch($aInterVisibility, $sPlayer_Pair)
                If @error Then
                    MsgBox(0, "Error", "Pairing not found")
                Else
                    GUICtrlSetData($hLabel, $aInterVisibility[$iIndex][1])
                EndIf
            EndIf
    EndSwitch

WEnd
#EndRegion

Func _Check_Intervisibility($iPlayer_A, $iPlayer_B)

    Local $aAngles, $fSingle_Vertex, $iCrit_Vertex, $iCrit_Vertex_0, $iCrit_Vertex_1

    ; Determine critical vertex/vertices
    Local $nCrit_Vertex = $aInter[$aLocation[$iPlayer_A]][$aLocation[$iPlayer_B]]
    ; Check if predetermined decision
    If $nCrit_Vertex = -2 Then
        Return "Hidden *"
        Exit
    ElseIf $nCrit_Vertex = -1 Then
         Return "Visible! *"
        Exit
    EndIf
    ; Determine if single vertex
    Global $aCrit_Vertex[2], $iCrit_Vertex
    If Int($nCrit_Vertex) = $nCrit_Vertex Then
        $fSingle_Vertex = True
        $iCrit_Vertex = Int($nCrit_Vertex)
        ;ConsoleWrite($iCrit_Vertex & @CRLF)
    Else
        $fSingle_Vertex = False
        $iCrit_Vertex_0 = Int($nCrit_Vertex)
        $iCrit_Vertex_1 = Int(($nCrit_Vertex - Int($nCrit_Vertex)) * 10)
        ;ConsoleWrite($iCrit_Vertex_0 & " - " & $iCrit_Vertex_1 & @CRLF)
    EndIf

    ; Determine relation of players

    ; Check zone order and reverse player order if necessary
    If $aLocation[$iPlayer_A] > $aLocation[$iPlayer_B] Then
        Local $iTemp = $iPlayer_A
        $iPlayer_A = $iPlayer_B
        $iPlayer_B = $iTemp
    EndIf

    ; Now check which order to place players in vertex formula
    $iDiff_X = $aPlayers[$iPlayer_B][3] -  $aPlayers[$iPlayer_A][3]
    $iDiff_Y = $aPlayers[$iPlayer_B][4] -  $aPlayers[$iPlayer_A][4]
    $fOrder = True
    Select
        Case $iDiff_X > 0 And $iDiff_Y > 0
            $fOrder = False
        Case $iDiff_X < 0 And $iDiff_Y < 0
            $fOrder = False
    EndSelect

    ; Now calculate angles
    If $fSingle_Vertex = True Then

        Local $aAngle[2]
        ; Check which player is used first to calculate the angle
        If $fOrder = True Then
            ;ConsoleWrite("Single Vertex " & $iCrit_Vertex & " - " & $iPlayer_A & " first" & @CRLF)
            $nAngle = _Calc_Angles($iPlayer_A, $iPlayer_B, $iCrit_Vertex)
        Else
            ;ConsoleWrite("Single Vertex " & $iCrit_Vertex & " - " & $iPlayer_B & " first" & @CRLF)
            $nAngle = _Calc_Angles($iPlayer_B, $iPlayer_A, $iCrit_Vertex)
        EndIf
        ; Check visibility
        If $nAngle >= $PiOver2 Then
            Return "Visible!"
        Else
            Return "Hidden"
        EndIf
    Else ; Multiple vertices
        ; Check which player is used first to calculate the angle
        If $fOrder = True Then
            ; Calculate for both vertices
            $nAngle_0 = _Calc_Angles($iPlayer_A, $iPlayer_B, $iCrit_Vertex_0)
            ;If $nAngle_0 < $PiOver2 Then ConsoleWrite("Partially hidden" & @CRLF)
            $nAngle_1 = _Calc_Angles($iPlayer_A, $iPlayer_B, $iCrit_Vertex_1)
            ;If $nAngle_1 < $PiOver2 Then ConsoleWrite("Partially hidden" & @CRLF)
        Else
            ; Calculate for both vertices
            $nAngle_0 = _Calc_Angles($iPlayer_B, $iPlayer_A, $iCrit_Vertex_0)
            ;If $nAngle_0 < $PiOver2 Then ConsoleWrite("Partially hidden" & @CRLF)
            $nAngle_1 = _Calc_Angles($iPlayer_B, $iPlayer_A, $iCrit_Vertex_1)
            ;If $nAngle_1 < $PiOver2 Then ConsoleWrite("Partially hidden" & @CRLF)
        EndIf
        ; Check visibility
        If $nAngle_0 < $PiOver2 Or $nAngle_1 < $PiOver2 Then
            Return "Hidden"
        Else
            Return "Visible!"
        EndIf
    EndIf
EndFunc

Func _Calc_Angles($iFirst_Player, $iSecond_Player, $iVertex)

    ;ConsoleWrite("Calc" & " - " & $iFirst_Player & " - " & $iSecond_Player & @CRLF)

    Local $aAngle[2]
    $aAngle[0] = Abs($aPlayers[$iFirst_Player][3] - $aVertex[$iVertex][0]) / Abs($aPlayers[$iFirst_Player][4] - $aVertex[$iVertex][1])
    $aAngle[1] = Abs($aPlayers[$iSecond_Player][4] - $aVertex[$iVertex][1]) / Abs($aPlayers[$iSecond_Player][3] - $aVertex[$iVertex][0 ])
    Return (ATan($aAngle[0]) + ATan($aAngle[1]))

EndFunc

Func _Zone_Players()

    ; Find main screen origin
    Local $tPoint = DllStructCreate("int X;int Y")
    DllStructSetData($tpoint, "X", 0)
    DllStructSetData($tpoint, "Y", 0)
    _WinAPI_ClientToScreen($hGUI, $tPoint)
    $iGUI_X = DllStructGetData($tPoint, "X")
    $iGUI_Y = DllStructGetData($tPoint, "Y")

    ; Find Player Zone
    For $i = 0 To $iPlayers - 1
        ; Player position relative to GUI and convert to grid coordinates
        $aPlayers[$i][3] = ($aPlayers[$i][3] - $iGUI_X) / 5
        $aPlayers[$i][4] = ($aPlayers[$i][4] - $iGUI_Y) / 5
        ; Look at zone in turn
        For $j = 0 To $iZones - 1
            ; If any point is outside zone limits then skip
            If $aPlayers[$i][3] < $aZones[$j][0] Then ContinueLoop
            If $aPlayers[$i][3] > $aZones[$j][2] Then ContinueLoop
            If $aPlayers[$i][4] < $aZones[$j][1] Then ContinueLoop
            If $aPlayers[$i][4] > $aZones[$j][3] Then ContinueLoop
            ; We are here so player is in this zone
            $aLocation[$i] = $j
            ExitLoop
        Next
        ; Error if we get here
        If $j = $iZones Then
            MsgBox(0, "Error", "Player " & $i & " not in a zone")
            Exit
        EndIf
    Next

EndFunc
#EndRegion

I have taken this script as far as I am going to and I am not going to support or amend it further - so feel free to alter it as you wish. But I hope some of you might find it of interest! :D

M23

Edit: Speeling - what else!

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...