Reinn Posted May 23, 2009 Posted May 23, 2009 (edited) Is it possible to make a pixelsearch that clicks in the middle of this:Normal PixelSearch function:$Left=0 $Top=0 $Right=1279 $Bottom=1023 While 1 $Search=PixelSearch ($Left,$Top,$Right,$Bottom,0xFFFFFF,1,1) If Not @error Then MouseClick ("Left",$Search[0],$Search[1],1,10) Sleep(20) WEndThe normal pixelsearch won't work because this has the red color 2 times before it has the one in the midle... It isn't possible to know the exact position as it's supposed to be a game, and you must hit in the midle, and it isn't allways at the same place.I don't even know which game it is, I just wonder if it is possible to hit the one in the midle.Hope some of you know the answer! Edited May 23, 2009 by Reinn
Mat Posted May 23, 2009 Posted May 23, 2009 Is it always a perfect circle?? Then you can find the 4 points on the edges (where it becomes white) and find the middle from there... Else you can count red, then white, then red then white then red kind of thing... So you search till you find red, then youserch till white etc. I'm sure its possible, you just gotta work out the logistics. MDiesel AutoIt Project Listing
Reinn Posted May 23, 2009 Author Posted May 23, 2009 expandcollapse popup;========================================================= ;Reinn's 'Shooting gallery' bot ;========================================================= ;Version 1.0 ;========================================================= ;Made by: ;Reinn at www.Fleud.com ;Reinn at www.Autoitscript.com ;FleudReinn at www.Youtube.com ;========================================================= ;www.Fleud.com for updates ;========================================================= ;Credits to: Fleud.com, AutoItscript.com for making AutoIt ;========================================================= ;Extra credits to: MDiesel, More to come! ;========================================================= #include <GUIConstants.au3> HotKeySet('^A', 'Search') $Form1 = GUICreate("Reinn's 'Shooting gallery' bot", 354, 179, 193, 125) $Combo1 = GUICtrlCreateCombo("1280 * 1024", 112, 112, 121, 25) GUICtrlSetData(-1, "1024 * 768") $Label1 = GUICtrlCreateLabel("Resolution:", 144, 88, 57, 17) $Edit1 = GUICtrlCreateEdit("", 16, 8, 321, 73) GUICtrlSetData(-1, StringFormat("This bot was made by Reinn from www.Fleud.com\r\n\r\n1. Start your web browser, and go to the "&Chr(34)&"Shooting gallery"&Chr(34)&" url.\r\n2. Start a game.\r\n3. Hold down CTRL, SHIFT & press on "&Chr(34)&"S"&Chr(34)&".\r\n\r\nFleud.com nor Reinn are responsible for what this is used for - Educational purposes only.")) GUISetState(@SW_SHOW) $Left=200 $Top=1000 $Right=800 $Bottom=500 While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch $Search=PixelSearch ($Left,$Top,$Right,$Bottom,#ff0000,1,1) Switch $Search If Not @error Then MouseClick ("Left",$Search[0],$Search[1],1,10) Sleep(20) ;After you've shoot 5 times it needs to reload by clicking at: MouseClick("Left",598,549,1) if you use 1024*768 & at: MouseClick("Left",760,713,1) if you use 1280*768 EndSwitch WEnd I've got this so far... And I don't care if it presses in the complete mid, just that it hits the circle...
Mat Posted May 24, 2009 Posted May 24, 2009 That switch statement is wrong. Switch Var Case Statement ;;; EndSwitch So that won't work. As far as Clicking in different places for reloading, Use macros where possible. MDesel AutoIt Project Listing
Reinn Posted May 24, 2009 Author Posted May 24, 2009 That switch statement is wrong. Switch Var Case Statement ;;; EndSwitch So that won't work. As far as Clicking in different places for reloading, Use macros where possible. MDeselIt's the same place you reload, it's just the resolution of your screen... Some have 1024 * 768 & some have 1280 * 1024 (I use the seconds one ^^)
Spiff59 Posted May 24, 2009 Posted May 24, 2009 (edited) Well, this looked like a fun one to play with, but I've changed my mind! It's my first time playng with pixels and is a pain-in-the-butt! I thought you'd first want to locate a group of consecutive white pixels on a horizontal line. Since PixelSearch() works in a rectange, I realized that, for instance, a white square on the left of the screen, would register a hit, and I'd need special handling to continue the search on the same line. So I dropped PixelSearch(). The image quality came to be a problem, there's a wide variety of "red" in that image, and colors other than red and white. Maybe you uploaded it in low-quality, but I had to widen the definition of "red" considerably, and still do cleanup on the image. I got the following routine to get a "hit" on the bullseye, but it currently only has a paragraph to vertically scan the image, so the red and whites stripes in an Amerian flag would also get a hit as a bullseye. It would be easy to add a horizontal scan (a Find_Hbands paragraph) after the vertical to be more precise, but then an image of concentric red and whites squares would still be considered a hit. You'd have to delve into geometry and test points along the radius to truly confirm a circle. So attaining perfection seems a lot of work. Anyway, the following is my really-rough first draft that does get a hit on the cleaned-up bullseye image attached to this post. I'm sure there are better ways to go about it, and lots of room for refinement. I just stuck an abrupt exit in it when it thinks it's found a bullseye. After 90 minutes, and realizing the headaches involved, I somewhat lost interest. The function is rather slow as well. I suppose there's API stuff out there that would help... expandcollapse popupHotKeySet("{ESC}", "Abort") Global $v, $h, $HCenter, $VCenter, $bands, $VBandCenter[10] Global $white = 0xFFFFFF, $red = 0xFF0000 $xy = WinGetPos("Program Manager") Global $Left=0 Global $Top=0 Global $Right=$xy[2] - 1 Global $Bottom=$xy[3] - 1 $v = $top -1 While 1 $v += 2 If $v > $Bottom Then ExitLoop $h = $left - 1 While 1 $h += 2 If $h > $Right Then ExitLoop ; ToolTip($v & " " & $h) If PixelGetShade($h, $v) = $white Then Find_HCenter() EndIf WEnd WEnd Func Find_HCenter() For $x = $h to $Right If PixelGetShade($x, $v) <> $white Or $x = $Right Then If $x - $h > 7 Then; minimum length of white line to review $HCenter = ($h + $x) / 2 Find_VBands() EndIf $h = $x ExitLoop EndIf Next EndFunc Func Find_VBands() Local $band = 0, $bandcolor = $white, $bandstart = $v For $x = $v to $Bottom Step 2 $y = PixelGetShade($HCenter, $x) ; MouseMove($HCenter, $x, 0) Switch $y Case $white If $bandcolor = $red Then $VBandCenter[$band] = ($bandstart + $x) / 2 $band += 1 $bandcolor = $white $bandstart = $x Endif Case $red If $bandcolor = $white Then $VBandCenter[$band] = ($bandstart + $x) / 2 $band += 1 $bandcolor = $red $bandstart = $x Endif Case Else $VBandCenter[$band] = ($bandstart + $x) / 2 Exitloop EndSwitch Next If $band = 6 Then; # of bands (white/red or red/white transitions) (0-based) MouseMove($HCenter, $VBandCenter[3],5) Beep(800,100) Sleep(200) Exit EndIf EndFunc ;------------------------------------------------------------------------------- Func PixelGetShade($xloc, $yloc) $color = Hex(PixelGetColor($xloc, $yloc)) $Rcolor = StringMid($color, 3, 2) $Gcolor = StringMid($color, 5, 2) $BColor = StringMid($color, 7, 2) If $Rcolor > "F0" And $Gcolor > "F0" And $BColor > "F0" Then Return $white EndIf If $Rcolor > "F0" And $Gcolor < "DF" And $BColor < "DF" Then Return $red EndIf Return $color EndFunc Func Abort() Exit EndFunc Edited May 25, 2009 by Spiff59
Reinn Posted May 24, 2009 Author Posted May 24, 2009 This is my code so far, I think if I get help with the counter, I'm almost done expandcollapse popup;========================================================= ;Reinn's 'Shooting gallery' bot ;========================================================= ;Version 1.0 ;========================================================= ;Made by: ;Reinn at www.Fleud.com ;Reinn at www.Autoitscript.com ;FleudReinn at www.Youtube.com ;========================================================= ;www.Fleud.com for updates ;========================================================= ;Credits to: Fleud.com, AutoItscript.com for making AutoIt ;========================================================= ;Extra credits to: MDiesel, More to come! ;========================================================= #include <GUIConstants.au3> HotKeySet('{F8}', 'Search') HotKeySet('{ESC}', 'Stop') $Form1 = GUICreate("Reinn's 'Shooting gallery' bot", 354, 179, 193, 125) $Combo1 = GUICtrlCreateCombo("1280 * 1024", 112, 112, 121, 25) GUICtrlSetData(-1, "1024 * 768") $Label1 = GUICtrlCreateLabel("Resolution:", 144, 88, 57, 17) $Edit1 = GUICtrlCreateEdit("", 16, 8, 321, 73) GUICtrlSetData(-1, StringFormat("This bot was made by Reinn from www.Fleud.com\r\n\r\n1. Start your web browser, and go to the "&Chr(34)&"Shooting gallery"&Chr(34)&" url.\r\n2. Start a game.\r\n3. Hold down CTRL, SHIFT & press on "&Chr(34)&"S"&Chr(34)&".\r\n\r\nFleud.com nor Reinn are responsible for what this is used for - Educational purposes only.")) GUISetState(@SW_SHOW) $Left=0 $Top=0 $Right=1000 $Bottom=800 While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Dim $Count = 0 Func Search() $Search=PixelSearch ($Left,$Top,$Right,$Bottom,0xFF0000,5,2) If Not @error Then MouseClick ("Left",$Search[0],$Search[1],1,10) Sleep(20) $Count =+ 1 MsgBox(1, "Test", $Count) ;The MsgBox comes up with 1 each time, help me to fix... (The MsgBox is only to see if it works - will delete when it works) EndFunc If $Count = 5 Then Reload() Func Reload() If $Combo1 = "1024 * 768" Then MouseClick("Left",598,549,1) ElseIf $Combo1 = "1280 * 1024" Then MouseClick("left",754,716,1) EndIf EndFunc Func Stop() ;ShellExecute("http://www.Fleud.com") Exit EndFunc
Mat Posted May 24, 2009 Posted May 24, 2009 As i've already said, you can get the resolution of your screen using macros, which will make it easier. Also, how about loading the game first, using IE funcitons, just to be extra professional. I think its a spiffing idea (see what I did there? ) if you count the pixels of colour ... and then see if its a line, but make it speedy, and go up in 3's or 4's. MDiesel AutoIt Project Listing
Reinn Posted May 25, 2009 Author Posted May 25, 2009 As i've already said, you can get the resolution of your screen using macros, which will make it easier.Also, how about loading the game first, using IE funcitons, just to be extra professional.I think its a spiffing idea (see what I did there? ) if you count the pixels of colour ... and then see if its a line, but make it speedy, and go up in 3's or 4's.MDieselI have a headache and I can't concentrate much right now... But what are Macro(s) ? (Haven't worked with them) And the IE could be easy, I think I'll use ShellExecute, so it uses the standard browser And what about the count thing... I still don't get how to fix it ...
Spiff59 Posted May 26, 2009 Posted May 26, 2009 (edited) Got bored (again) so messed with this some more. Made some speed improvements, some color range recognition improvements (it'll nail the original image in the post now), and added a horizontal scan for the bars/stripes/bands in the target in addition to the vertical scan already in my first play script. expandcollapse popupHotKeySet("{ESC}", "Abend") Global $v, $h, $HCenter, $VCenter, $band, $VBandCenter[10] Global $white = 0xFFFFFF, $red = 0xFF0000, $found = 0 $xy = WinGetPos("Program Manager") Global $Left=0 Global $Top=0 Global $Right=$xy[2] - 1 Global $Bottom=$xy[3] - 1 $v = $Top $timer = TimerInit() While 1 $v += 2 $x = PixelSearch($Left,$v,$Right,$Bottom,$red,20,2) $v = $x[1] If $v > $Bottom Then ExitLoop $h = $Left - 2 While 1 $h += 2 If $h > $Right Then ExitLoop ; ToolTip($v & " " & $h) If PixelGetShade($h, $v) = $red and PixelGetShade($h, $v - 2) = $white Then Find_HCenter() If $found Then ExitLoop(2) EndIf WEnd WEnd $timer = TimerDiff($timer) MsgBox(1,"","Time: " & $timer/1000) Func Find_HCenter() For $x = $h to $Right If PixelGetShade($x, $v) <> $red Or $x = $Right Then If $x - $h > 7 Then; minimum length of line to review $HCenter = ($h + $x) / 2 Find_VBands() EndIf $h = $x ExitLoop EndIf Next EndFunc Func Find_VBands() Local $band = 1, $bandcolor = $red, $bandstart = $v $y = $v + 70; Attempt to increase speed by limiting to height of target If $y > $Bottom Then $y = $Bottom For $x = $v to $y Step 2 $y = PixelGetShade($HCenter, $x) ; MouseMove($HCenter, $x, 0) Switch $y Case $white If $bandcolor = $red Then $VBandCenter[$band] = ($bandstart + $x) / 2 $band += 1 $bandcolor = $white $bandstart = $x Endif Case $red If $bandcolor = $white Then $VBandCenter[$band] = ($bandstart + $x) / 2 $band += 1 $bandcolor = $red $bandstart = $x Endif Case Else $VBandCenter[$band] = ($bandstart + $x) / 2 Exitloop EndSwitch Next If $band = 6 Then; # of bands (white/red or red/white transitions, 0-based) Find_HBands() EndIf EndFunc Func Find_HBands() Local $band = 0, $bandcolor = $red $y = $HCenter + 35; limit to radius of target If $y > $Right Then $y = $Right For $x = $HCenter to $y Step 2 $y = PixelGetShade($x, $VBandCenter[3]) Switch $y Case $white If $bandcolor = $red Then $band += 1 $bandcolor = $white Endif Case $red If $bandcolor = $white Then $band += 1 $bandcolor = $red Endif Case Else Exitloop EndSwitch Next If $band <> 3 Then Return; not 3 bands to right $band = 0 $bandcolor = $red $y = $HCenter - 35; limit to radius of target If $y < $Left Then $y = $left For $x = $HCenter to $y Step -2 $y = PixelGetShade($x, $VBandCenter[3]) Switch $y Case $white If $bandcolor = $red Then $band += 1 $bandcolor = $white Endif Case $red If $bandcolor = $white Then $band += 1 $bandcolor = $red Endif Case Else Exitloop EndSwitch Next If $band = 3 Then; 3 bands to left MouseMove($HCenter, $VBandCenter[3],0) Beep(800,100) $found = 1 EndIf EndFunc ;------------------------------------------------------------------------------- Func PixelGetShade($xloc, $yloc) $color = Hex(PixelGetColor($xloc, $yloc)) $Rcolor = Dec(StringMid($color, 3, 2)) $Gcolor = Dec(StringMid($color, 5, 2)) $BColor = Dec(StringMid($color, 7, 2)) If $Rcolor > 176 And $Gcolor > 176 And $BColor > 176 Then Return $white EndIf If $Rcolor - $Gcolor > 20 and $Rcolor - $Bcolor > 20 Then Return $red EndIf Return $color EndFunc Func Abend() Exit EndFunc Edited May 27, 2009 by Spiff59
ofLight Posted May 26, 2009 Posted May 26, 2009 This works for me on all three symbols... .. . but ofcourse I cheated and used a checksum expandcollapse popupHotKeySet("`","_find") HotKeySet("~","record") HotKeySet('{esc}', '_Exit') Global $msg = "Press Shift+tilde to Record " & @LF & _ "Press tilde to Find " & @LF & _ "info saved in Pixel.ini" Global $xy,$currentpixel While 1 $xy = MouseGetPos() $currentpixel = PixelGetColor($xy[0],$xy[1]) ToolTip("Pixel color = " & $currentpixel & @LF & $msg) Sleep(100) WEnd Func record() IniWrite(".\Pixel.ini","Main","PixelColor",$currentpixel) Local $chksum = PixelChecksum($xy[0]-4, $xy[1]-20, $xy[0]+4, $xy[1]+20) IniWrite(".\Pixel.ini","Main","PixelCheckSum",$chksum) ToolTip("SAVED") Sleep(1000) ;Exit EndFunc Func _find() Local $pixel = Int(IniRead(".\Pixel.ini","Main","PixelColor","-1")) Local $chksum = Int(IniRead(".\Pixel.ini","Main","PixelCheckSum","-1")) $x = 5 ;LEFT pixel of Total Area to Search for $pixel $y = 5 ;TOP $xpixel = @DesktopWidth - 5 ;Right $ypixel = @DesktopHeight - 5 ;Bottom While 1 $xy = PixelSearch($x,$y,$xpixel,$ypixel,$pixel, 0) If @error And $ypixel = (@DesktopHeight - 5)Then MsgBox(4096,"@Error ","Could not find Checksum" & @LF & ' Finished Searching all of Screen', 4) exit ElseIf @error Then $y = $ypixel + 1 $ypixel = (@DesktopHeight - 5) $x = 0 ElseIf $chksum = PixelCheckSum($xy[0]-4, $xy[1]-20, $xy[0]+4, $xy[1]+20) Then ToolTip("Found Checksum") MouseMove($xy[0],$xy[1], 20) Sleep(1000) Exit Else $y = $xy[1] $ypixel = $y $x = $xy[0] + 1 EndIf WEnd EndFunc Func _Exit() ToolTip(' '&@CRLF&' EXITING '&@CRLF&' ') Sleep(500) Exit EndFunc There is always a butthead in the crowd, no matter how hard one tries to keep them out.......Volly
Moderators SmOke_N Posted May 27, 2009 Moderators Posted May 27, 2009 http://www.autoitscript.com/forum/index.php?showtopic=95623 Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
Spiff59 Posted May 27, 2009 Posted May 27, 2009 (edited) I see that PixelCheckSum() does the trick and quickly. It does have it's drawbacks as well. You have to know the exact value of all your target pixels prior to the search. So if an image were rendered differently depending on it's location on the screen, or what colors it borders, or screen resolution, etc, you're not going to get a match. I suppose there's also a minute chance that an entirely different image pattern could generate the same checksum. This other method, a rudimentary attempt at pattern-recognition has it's flaws too (especially my kludgy first attempt here at playing with pixels). I worked a pixelsearch into the routine and a cheesy test to detect a circle versus a square and it finds a bullseye now in about a 1/10th of a second if it's near the top of the screen, and .6 seconds if it's near the bottom. It tries to ignore the size of the target pattern, or shade variations, but it's imperfect. Bumping $pixel_increment to 4 brings the max scan time down to .4 seconds, but rules out finding smaller targets. Anyway, were this my project, I'd probably take what I've learned, then pitch out my beta routine, and rewrite the whole thing. expandcollapse popupHotKeySet("{ESC}", "Abend") Global $v, $h, $HCenter, $VCenter, $band, $Vbandstart[10], $VBandCenter[10] Global $white = 0xFFFFFF, $red = 0xFF0000, $found = 0 $xy = WinGetPos("Program Manager") Global $Left=0 Global $Top=0 Global $Right=$xy[2] - 1 Global $Bottom=$xy[3] - 1 $v = $Top $Pixel_Increment = 3; frequency of pixels to scan $timer = TimerInit() While 1 $v += $Pixel_Increment $x = PixelSearch($Left,$v,$Right,$Bottom,$red,20,2) If @error Then ExitLoop $v = $x[1] If $v > $Bottom Then ExitLoop $h = $Left While 1 $h += $Pixel_Increment If $h > $Right Then ExitLoop ; ToolTip($v & " " & $h) If PixelGetShade($h, $v) = $red and PixelGetShade($h, $v - 3) = $white Then Find_HCenter() If $found Then ExitLoop(2) EndIf WEnd WEnd $timer = TimerDiff($timer) MsgBox(1,"","Time: " & $timer/1000) Func Find_HCenter() For $x = $h to $Right If PixelGetShade($x, $v) <> $red Or $x = $Right Then If $x - $h > 7 Then; minimum length of line to review $HCenter = ($h + $x) / 2 Find_VBands() EndIf $h = $x ExitLoop EndIf Next EndFunc Func Find_VBands() Local $band = 1, $bandcolor = $red $VbandStart[$band] = $v $y = $v + 70; Attempt to increase speed by limiting to height of target If $y > $Bottom Then $y = $Bottom For $x = $v to $y Step $Pixel_Increment $y = PixelGetShade($HCenter, $x) ; MouseMove($HCenter, $x, 0) Switch $y Case $white If $bandcolor = $red Then $VBandCenter[$band] = ($VbandStart[$band] + $x) / 2 $band += 1 $VbandStart[$band] = $x $bandcolor = $white Endif Case $red If $bandcolor = $white Then $VBandCenter[$band] = ($VbandStart[$band] + $x) / 2 $band += 1 $VbandStart[$band] = $x $bandcolor = $red Endif Case Else $VBandCenter[$band] = ($VbandStart[$band] + $x) / 2 Exitloop EndSwitch Next If $band = 6 Then; # of bands (white/red or red/white transitions, 0-based) Find_HBands() EndIf EndFunc Func Find_HBands() Local $band = 0, $bandcolor = $red $y = $HCenter + 35; limit to radius of target If $y > $Right Then $y = $Right For $x = $HCenter to $y Step 2 $y = PixelGetShade($x, $VBandCenter[3]) Switch $y Case $white If $bandcolor = $red Then $band += 1 $bandcolor = $white Endif Case $red If $bandcolor = $white Then $band += 1 $bandcolor = $red Endif Case Else Exitloop EndSwitch Next If $band <> 3 Then Return; not 3 bands to right $band = 0 $bandcolor = $red $y = $HCenter - 35; limit to radius of target If $y < $Left Then $y = $left For $x = $HCenter to $y Step -2 $y = PixelGetShade($x, $VBandCenter[3]) Switch $y Case $white If $bandcolor = $red Then $band += 1 $bandcolor = $white Endif Case $red If $bandcolor = $white Then $band += 1 $bandcolor = $red Endif Case Else Exitloop EndSwitch Next If $band = 3 Then; 3 bands to left $x = $VBandCenter[3] - ($VBandStart[3] + 1) If PixelGetShade($HCenter + $x, $VBandStart[3]) = $white Then MouseMove($HCenter, $VBandCenter[3],0) Beep(800,100) $found = 1 EndIf EndIf EndFunc ;------------------------------------------------------------------------------- Func PixelGetShade($xloc, $yloc) $color = Hex(PixelGetColor($xloc, $yloc)) $Rcolor = Dec(StringMid($color, 3, 2)) $Gcolor = Dec(StringMid($color, 5, 2)) $BColor = Dec(StringMid($color, 7, 2)) If $Rcolor > 176 And $Gcolor > 176 And $BColor > 176 Then Return $white EndIf If $Rcolor - $Gcolor > 20 and $Rcolor - $Bcolor > 20 Then Return $red EndIf Return $color EndFunc Func Abend() Exit EndFunc Edited May 27, 2009 by Spiff59
Mat Posted May 27, 2009 Posted May 27, 2009 Sorry to say but... Smoke_N wins there! Very nice work though, pointless, but nice! MDiesel AutoIt Project Listing
Reinn Posted May 27, 2009 Author Posted May 27, 2009 Wow, a lot of replies, will look them thru one by one when I have the time... Thanks folks!
junkew Posted May 27, 2009 Posted May 27, 2009 imagesearching can do the trick (although background changing can be an attention point)http://www.autoitscript.com/forum/index.php?showtopic=66545 FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
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