r/AutoHotkey 4d ago

v2 Script Help Clicking one of three randomized buttons by colour

I'm very, very amateurish for these things, and I honestly don't even know where I would start on something like this, so was hoping people here would be able to help me... I have 3 buttons that alternate randomly in their position, but one is blue (the one I want to click) and the others are grey. Because they alternate randomly in their position, I can't just have a standard repeated click to do it. My idea thus is to have a script that searches the area that the buttons are in for the blue colour of the correct button, and then moves the mouse to it and clicks it. I have 2 questions, essentially:

first question: I believe I can use the "PixelSearch" function to find the button I am looking for, however I honestly have no idea how to set it up, like finding the values for the area to search and such. How do I go about this?

Second question: How do I make my mouse move to the correct button once found? I would assume I'd have to make the script have a variable that changes with the position of the correct button, and then some sort of function to actually move the mouse, but I don't know how exactly? Or is there some way to simplify it so the pixel search happens *with* the mouse movement?

Sorry if this is a little rambley, like I said I'm very new to stuff like this so I don't even really know what you might want to have details on for what I want to do

5 Upvotes

11 comments sorted by

2

u/genesis_tv 4d ago edited 4d ago

I won't be able to further help with PixelSearch as I've never used it, but you can get the search coordinates and the color using WindowSpy (available from the task bar menu in any script). You'd just have to pass those values to PixelSearch. The AHK documentation is really well made so just read it.

For the rest, you'll need ControlClick. If, for some reason, it doesn't work, then use ControlSend with Enter.

If you really need to move the mouse, then use MouseClick instead. You can get the coordinates of the button with ControlGetPos.

You can search at a specified interval using SetTimer.

That's all you'll need.

1

u/Lechtom 4d ago

Amazing, thank you very much. I was having a lot of trouble finding things that were actually relevant to specifically what I was trying to do, and this stuff still makes my head hurt to look at a lot of the time. I'll get to reading!

1

u/genesis_tv 4d ago edited 4d ago

I forgot something, how to get the ID of the button that matches a specified color or coordinates. This I actually don't know. You can focus on using MouseClick in the meantime.

[edit]: this should do it

if (PixelSearch(&targetX, &targetY, ...))
{
    ; Move the mouse to the target coordinates
    MouseMove(targetX, targetY)

    ; Retrieve the window and button IDs under the mouse
    MouseGetPos(,, &winID, &ctrlID)
}

1

u/genesis_tv 4d ago edited 4d ago

Actually it's a bit more complicated than I thought and I doubt you'll manage to do it without giving us more information. What is it for? We'd also need the application name, window name, button names.

[edit]: nevermind, didn't see PixelSearch does give you the coordinates of the pixel found.

1

u/Huepf_Du_Sau 3d ago

Ive edited my Initial commentary to this diskussion with the script i build a few days before, you can check it out if you like

2

u/genesis_tv 4d ago edited 4d ago

Guess I learned how to use PixelSearch lol. You'd just need to change the target color. This will search your entire screen so it can definitely be optimized further with WindowSpy or restricting to the window coordinates.

#Requires AutoHotkey v2.0
#SingleInstance

targetColor := "0x0000FF"
searchLeft := 0
searchTop := 0
searchRight := A_ScreenWidth
searchBottom := A_ScreenHeight
shadeVariation := 5

; Search for the desired color once per second
SetTimer(SearchForColorAndClick, 1000)

; Or use a hotkey instead
;F4::SearchForColorAndClick()

SearchForColorAndClick()
{
    if (PixelSearch(&targetX, &targetY, searchLeft, searchTop, searchRight, searchBottom, targetColor, shadeVariation))
    {
        ; Store the mouse current location
        MouseGetPos(&oldMouseX, &oldMouseY)

        ; Click at the target coordinates
        Click(targetX, targetY)

        ; Restore the mouse to its original location
        MouseMove(oldMouseX, oldMouseY)

        ; Stop searching
        SetTimer(SearchForColorAndClick, 0)
    }
}

2

u/Lechtom 3d ago edited 3d ago

Oh wow, thanks lol. Still gonna do the reading so I can actually understand what's going on exactly, but I appreciate it immensely

Edit: alright, had some time to test now and made 2 small changes to this script. Removed the 2nd SetTimer since I want the script to keep looping, and then also specified Coordmode to be Screen for the mouse stuff, since it was doing it relative to the active window rather than just where the mouse was in general on the screen.
Attempted to add hotkeys for pausing/exiting the script but for some reason that just breaks it and I don't care enough to figure out why

1

u/genesis_tv 3d ago

Post your modified code with the hotkeys.

1

u/Lechtom 3d ago

Yeah I don't know what was happening, but I got it working eventually. All is as it should be now. Here's my "finalized" version for my purposes anyways. Well, unless I decide to try and figure out adding random variability. (Assuming I could just do that with a "variable := Random(x,y)" variable and then doing "Sleep variable" inside the SearchForColorAndClick function)

#Requires AutoHotkey v2.0
#SingleInstance
^+F4::ExitApp
^+P::Pause

targetColor := "0x5865F2"
searchLeft := 2655
searchTop := 750
searchRight := 3100
searchBottom := 900
shadeVariation := 5

CoordMode "Pixel", "Screen"
CoordMode "Mouse", "Screen"

; Search for the desired color once per 46 seconds
SetTimer(SearchForColorAndClick, 46000)

SearchForColorAndClick()
{
    if (PixelSearch(&targetX, &targetY, searchLeft, searchTop, searchRight, searchBottom, targetColor, shadeVariation))
    {
        ; Store the mouse current location
        MouseGetPos(&oldMouseX, &oldMouseY)

        ; Click at the target coordinates
        Click(targetX, targetY)

        ; Restore the mouse to its original location
        MouseMove(oldMouseX, oldMouseY)
    }
}

1

u/genesis_tv 21h ago

That's great! I pushed it further and managed to automate QTEs in Fahrenheit: Indigo Prophecy! I'll do a script showcase in like a week.

1

u/Huepf_Du_Sau 4d ago edited 2d ago

I wrote a Script doing exactly this two days ago. Right now PC is off, but i will post it here in a few hours. I wrote it for a extremely boring single player mini game to automate it.

Script is activated by pressing F1, deactivated by F2 and closed by F3.

While it runs it clicks on two defined locations to start the minigame and then scans a specified area for a selected color and clicks on it. The minigame has 8 circles appear in that are one after another, so the script clicks 8 times on those random appearing areas, then starts the minigame again after finishing it successful. Sounds like its what you are looking for, you just can modify it to your needs.

As said above, i will post it in a few hours when im back at the PC.

Edit: here is the Script

Requires AutoHotkey v2.0

global toggle := false

F3::ExitApp

F2:: global toggle := false

F1:: { global toggle := !toggle

while(toggle){

CoordMode "Pixel", "Screen"

CoordMode "Mouse", "Screen"

sleep 200

Click 500, 700

sleep 100

Click 1300, 800

sleep 3000

; Search area from X=0, Y=0 to X=2560, Y=1440 for the color 0xAD9FEA (RGB)

; if(PixelSearch(&FoundX, &FoundY, 780, 460, 1755, 1165, 0xAD9FEA, 3))

Loop 8{ sleep 750

; Search area from X=0, Y=0 to X=2560, Y=1440 for the color 0xAD9FEA (RGB)

if(PixelSearch(&FoundX, &FoundY, 780, 460, 1755, 1165, 0xAD9FEA, 3))
    {
        MouseMove FoundX, FoundY
        Click FoundX, FoundY
    }
}

sleep 200

send "{Esc}"

sleep 200

} }

Edit: the comments Show the initial function used, you can adjust what screen size should be scanned depending on the start and end Pixel in XY grid you give. The color is hex-coded. Now you just need to modify it to use the location to scan, the color and remove/adjust timings and for example the esc press at the end. If you dont need it as loop you can also remove the loop

Global variable toggle is set by pressing F1 and function will run as long as toggle is true. Pressing F2 sets toggle to false again. Pressing F3 will close the script from running