Что нового

Поиск пикселя вне экрана

st@rter

Новичок
Сообщения
15
Репутация
0
Здравствуйте, уважаемые форумчане. Такая вот проблема: надо сделать поиск пикселя по цвету вне экрана, лазил по форуму нашел функцию на поиск:
Код:
Func _SearchPix($x1, $y1, $x2, $y2, $coll, $shvar=0, $step=1)
    $ARGB = _WinAPI_IntToDWord(BitOR($coll, 0xFF000000))
    $Size = WinGetClientSize($nWnd)
    $L1 = $Size[0]*($y1-1)+$x1
    $L2 = $Size[0]*($y2-1)+$x2
    $L = $Size[0] * $Size[1]
    $tBits = DllStructCreate('dword[' & $L & ']')
    _WinAPI_GetBitmapBits($hBMP, 4 * $L, DllStructGetPtr($tBits))
    $Offset = -1
    For $i = $L1 To $L2 Step $step
        If DllStructGetData($tBits, 1, $i) = $ARGB Then
            $Offset = $i
            ExitLoop
        EndIf
    Next
    If $Offset = -1 Then
        Return SetError(1)
    Else
        $x = Mod($Offset, $Size[0]) - 1
        $y = Ceiling($Offset / $Size[0]) - 1
        ;$coor[2] = [$x, $y]
        Return $coor=1
    EndIf
EndFunc

слегка видоизменил, что б при условии, если пиксель будет найдет то coor будет равен 1.
Вот мой скрипт:
Код:
func Position_hide()
	WinActivate($TWnd,$hWnd)
	opt("PixelCoordMode",0)
	$width = 21* $aPos[2] / 100
	$Pos_HP = PixelSearch($x1=$width-$HP,$y1=53,$x2=$width-$HP+3,$y2=80,$coll=0x372A11) ;,0x372A11)
	_SearchPix($coor)
	$abby[0]=$coor
	$Pos_Monst = PixelGetColor(573,65)
	$Pos = PixelSearch( $x1=$width-$HP, $y1=53, $x2=310, $y2=84, $coll=0x5E9438)
	$abby[1]=$coor
	$PosMonster = PixelSearch( $x1=499, $y1=48, $x2=980, $y2=86, $coll=0x6A3838)
	_SearchPix($coor)
	$abby[2]=$coor
	$PosMonster2 = PixelSearch( $x1=499, $y1=48, $x2=980, $y2=86, $coll= 0x8D2322)
	_SearchPix($coor)
	$abby[3]=$coor
	$PosMonster3 = PixelSearch( $x1=499, $y1=48, $x2=980, $y2=86, $coll= 0x861D1D)
	_SearchPix($coor)
	$abby[4]=$coor
	if $abby[0]=1 and  $abby[2]=1 and $abby[3]=1 and $abby[4]=1 Then
		ActivateHealth_hide()
	EndIf
EndFunc


Вылетает ошибка связанная с функцией, может библиотеку какую не подключил? (На этот момент подключена библиотека: WinAPIEx.au3)
В заранее спасибо
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
Вроди, разобрался, ошибка на самом деле глупая.. Но вот морочусь сейчас с другой
Код:
Subscript used with non-Array variable.:
$L1 = $Size[0]*($y1-1)+$x1
$L1 = $Size^ ERROR
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
В $Size у тебя записывается результат WinGetClientSize. В случае успеха в [0] и [1] возвращаются ширина и высота клиентской части окна. В случае ошибки в $Size возвращается 0. Все просто, скрипт не может определить ширину и высоту клиентской части окна
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
Belfigor сказал(а):
В $Size у тебя записывается результат WinGetClientSize. В случае успеха в [0] и [1] возвращаются ширина и высота клиентской части окна. В случае ошибки в $Size возвращается 0. Все просто, скрипт не может определить ширину и высоту клиентской части окна
Спасибо за совет, решил проблему.
Возникла следующая проблема.. Подскажите, как устранить.
Все нажимается, но проверка не происходит, вот скрипт:
Функция проверки вне экрана:
Код:
Func _PixelGetArray($i_X, $i_Y, $i_Width, $i_Height, $i_Color, $h_Wnd, $f_FirstOnly = True)
    Local $i_Size = $i_Width * $i_Height, $a_Pixels[$i_Size + 1][2] = [[0]], $h_DC, $h_MemDC, $h_Bitmap, $t_Bits, $i_Index
	;WinActivate($HWnd)
    ;If Not $h_Wnd Then $h_Wnd = _WinAPI_GetShellWindow()
    $h_DC = _WinAPI_GetDC($h_Wnd)
    $h_MemDC = _WinAPI_CreateCompatibleDC($h_DC)
    $h_Bitmap = _WinAPI_CreateCompatibleBitmap($h_DC, $i_Width, $i_Height)
    _WinAPI_SelectObject($h_MemDC, $h_Bitmap)
    _WinAPI_BitBlt($h_MemDC, 0, 0, $i_Width, $i_Height, $h_DC, $i_X, $i_Y, $SRCCOPY)
    _WinAPI_DeleteDC($h_MemDC)
    _WinAPI_ReleaseDC($h_Wnd, $h_DC)
    $t_Bits = DllStructCreate('dword[' & $i_Size & ']')
    $p_Bits = DllStructGetPtr($t_Bits)
    _WinAPI_GetBitmapBits($h_Bitmap, 4 * $i_Size, $p_Bits)
    _WinAPI_DeleteObject($h_Bitmap)
    For $i = 0 To $i_Height - 1
        For $j = 0 To $i_Width - 1
            $i_Index += 1
            If BitAND(DllStructGetData($t_Bits, 1, $i_Index), 0x00FFFFFF) = $i_Color Then
                $a_Pixels[0][0] += 1
                $a_Pixels[$a_Pixels[0][0]][0] = $j + $i_X
                $a_Pixels[$a_Pixels[0][0]][1] = $i + $i_Y
                If $f_FirstOnly Then ExitLoop 2
            EndIf
        Next
    Next
    ReDim $a_Pixels[$a_Pixels[0][0] + 1][2]
    Return $a_Pixels
EndFunc

Вызов фукции и условие
Код:
func regen_HP_hide()
	$width =21 * $aPos[2] / 100
	$x1=$width-$HP
	$y1=60
	$x2=$width-$HP+3
	$y2=75
	$coll=0x372A11
	;_PixelGetArray($x1, $y1, $x2, $y2, $coll,$TWnd)
	$tmp = _PixelGetArray($x1, $y1, $x2-$x1, $y2-$y1, $coll, $HWnd, True)
	$abby[0]=$tmp[0][0]
	   If $abby[0]=1 Then
		  heal_hide()
		  sleep(200)
		  heal_hide()
		  sleep(300)
	  EndIf
EndFunc

Параметры берутся пока окно активно, потом пользователь может его "свернуть" через хоткеевские клавиши, которые которые передвигают окно на координаты -2000, 0
Код:
$aPos = WinGetPos("[ACTIVE]")
$HWnd=WinGetHandle("[ACTIVE]")
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Надо дебажить в живую. Потыкай после каждой строки ConsoleWrite, и смотри в выводе, что скрипт тебе пишет.
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
Пробовал через msgbox постоянно нули выдает...
 

InnI

AutoIT Гуру
Сообщения
4,958
Репутация
1,448
st@rter
Провёл эксперимент на блокноте: развернул на весь экран (1280х1024) и искал белый пиксель ($coll=0xFFFFFF) следующим образом
Код:
Global $tmp
WinActivate("Безым")
$aPos = WinGetPos("[ACTIVE]")
$HWnd=WinGetHandle("[ACTIVE]")
$HP = 283
regen_HP_hide()
ConsoleWrite($tmp[0][0] & @CRLF)


Что такое $HP? У меня при значениях 283 и ниже пиксель находит, а 284 и выше - не находит. Другими словами функции рабочие, а ошибка, скорее всего, в расчётах. Проверяйте.
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
InnI сказал(а):
st@rter
Провёл эксперимент на блокноте: развернул на весь экран (1280х1024) и искал белый пиксель ($coll=0xFFFFFF) следующим образом
Код:
Global $tmp
WinActivate("Безым")
$aPos = WinGetPos("[ACTIVE]")
$HWnd=WinGetHandle("[ACTIVE]")
$HP = 283
regen_HP_hide()
ConsoleWrite($tmp[0][0] & @CRLF)


Что такое $HP? У меня при значениях 283 и ниже пиксель находит, а 284 и выше - не находит. Другими словами функции рабочие, а ошибка, скорее всего, в расчётах. Проверяйте.
Спасибо за наводку, сейчас буду пробовать, $HP это параметр который пользователь выбирает в окне при каком %е бот начинает регенить ХП


Добавлено:
Сообщение автоматически объединено:

$HP переделал, там действительно была ошибка и что самое интересное, когда окно было не активным там брались значения 2500, сейчас расчет добавил в начало после инициализации параметров:
Код:
$hWnd = WinGetText("[ACTIVE]")
	$TWnd = WinGetTitle("[ACTIVE]")
	$aPos = WinGetPos("[ACTIVE]")
	$HWnd=WinGetHandle("[ACTIVE]")
	opt("MouseCoordMode",0)
	opt("PixelCoordMode",2);0 тоже пробовал результат тот же
	$width = 21 * $aPos[2] / 100
	$HP = $HP*$width/100

$HP находится посредством селектора в окне. В общем значение он выдает верное.. 267.2202
А вот пиксель не видит
Может тут что-то не так? :(
Код:
func regen_HP_hide()
	;$width =21 * $aPos[2] / 100
	;$HP = $HP*$width/100
	$x1=$HP
	$y1=60
	$x2=$HP+3
	$y2=75
	$coll=0x372A11
	;_PixelGetArray($x1, $y1, $x2, $y2, $coll,$TWnd)
	$tmp = _PixelGetArray($x1, $y1, $x2-$x1, $y2-$y1, $coll, $HWnd, True)
	$abby[0]=$tmp[0][0]
	;$abby[0]=$coor
	local $vif = $abby[0] 
	MsgBox(64,"1",$vif)
	MsgBox(64,"1",$HP)
	MsgBox(64,"1",$HWnd)
	   If $abby[0]=1 Then
		  heal_hide()
		  sleep(200)
		  heal_hide()
		  sleep(300)
	  EndIf
EndFunc
 

InnI

AutoIT Гуру
Сообщения
4,958
Репутация
1,448
st@rter
Код:
$hWnd = WinGetText("[ACTIVE]")
$HWnd=WinGetHandle("[ACTIVE]")

Для AutoIt $hWnd и $HWnd - это одна и та же переменная и в данном случае там будет хэндл окна, а не текст. Зачем вам вообще текст из окна игры? Обычно там его просто нет.

А вот пиксель не видит
А вы не допускаете, что его там действительно нет? Если вы уверены, что он там есть, зачем вы его ищете?

Может тут что-то не так?
Логика выглядит правильно. А правильность значений можете проверить только вы сами.


Добавлено:
Сообщение автоматически объединено:

Добавил в вашу функцию снимок той части окна, где производится поиск пикселя. Убедитесь, что он там есть
Код:
func regen_HP_hide()
    ;$width =21 * $aPos[2] / 100
    ;$HP = $HP*$width/100
    $x1=$HP
    $y1=60
    $x2=$HP+3
    $y2=75
    ;------------------------
    _ScreenCapture_CaptureWnd(@ScriptDir & "\scr.bmp", $HWnd, $x1, $y1, $x2, $y2, False)
    ;------------------------
    $coll=0x372A11
    ;_PixelGetArray($x1, $y1, $x2, $y2, $coll,$TWnd)
    $tmp = _PixelGetArray($x1, $y1, $x2-$x1, $y2-$y1, $coll, $HWnd, True)
    $abby[0]=$tmp[0][0]
    ;$abby[0]=$coor
    local $vif = $abby[0]
    MsgBox(64,"1",$vif)
    MsgBox(64,"1",$HP)
    MsgBox(64,"1",$HWnd)
       If $abby[0]=1 Then
          heal_hide()
          sleep(200)
          heal_hide()
          sleep(300)
      EndIf
EndFunc

И не забудьте добавить в начало скрипта
Код:
#include <ScreenCapture.au3>
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
Скрин делает верно, а нужно для того как раз, что б понять появился или нет, если он появился то выполняются определенные действия.. Так ошибку и не могу найти, вычисления вродь проверил - верно все.
 

InnI

AutoIT Гуру
Сообщения
4,958
Репутация
1,448
st@rter
Попробуйте стандартную
Код:
PixelSearch($x1, $y1, $x2, $y2, $coll, 0, 1, $HWnd)
If @error then ConsoleWrite("Не найден" & @CRLF)
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
Вот стандартная то работает в активном окне все путем..
 

InnI

AutoIT Гуру
Сообщения
4,958
Репутация
1,448
st@rter
Добавил отладку. Покажите скриншот и вывод в консоль
Код:
Func _PixelGetArray($i_X, $i_Y, $i_Width, $i_Height, $i_Color, $h_Wnd, $f_FirstOnly = True)
    Opt("PixelCoordMode", 2) ; <= debug
    Local $i_Size = $i_Width * $i_Height, $a_Pixels[$i_Size + 1][2] = [[0]], $h_DC, $h_MemDC, $h_Bitmap, $t_Bits, $i_Index
    ;WinActivate($HWnd)
    ;If Not $h_Wnd Then $h_Wnd = _WinAPI_GetShellWindow()
    $h_DC = _WinAPI_GetDC($h_Wnd)
    $h_MemDC = _WinAPI_CreateCompatibleDC($h_DC)
    $h_Bitmap = _WinAPI_CreateCompatibleBitmap($h_DC, $i_Width, $i_Height)
    _WinAPI_SelectObject($h_MemDC, $h_Bitmap)
    _WinAPI_BitBlt($h_MemDC, 0, 0, $i_Width, $i_Height, $h_DC, $i_X, $i_Y, $SRCCOPY)
    _ScreenCapture_SaveImage(@ScriptDir & "\PixelGetArray.bmp", $h_Bitmap, False) ; <= debug
    _WinAPI_DeleteDC($h_MemDC)
    _WinAPI_ReleaseDC($h_Wnd, $h_DC)
    $t_Bits = DllStructCreate('dword[' & $i_Size & ']')
    $p_Bits = DllStructGetPtr($t_Bits)
    _WinAPI_GetBitmapBits($h_Bitmap, 4 * $i_Size, $p_Bits)
    _WinAPI_DeleteObject($h_Bitmap)
    For $i = 0 To $i_Height - 1
        For $j = 0 To $i_Width - 1
            $i_Index += 1
            ConsoleWrite(Hex(DllStructGetData($t_Bits, 1, $i_Index), 8) & ":") ; <= debug
            ConsoleWrite(Hex(BitAND(DllStructGetData($t_Bits, 1, $i_Index), 0x00FFFFFF), 8) & @CRLF) ; <= debug
            If BitAND(DllStructGetData($t_Bits, 1, $i_Index), 0x00FFFFFF) = $i_Color Then
                $a_Pixels[0][0] += 1
                $a_Pixels[$a_Pixels[0][0]][0] = $j + $i_X
                $a_Pixels[$a_Pixels[0][0]][1] = $i + $i_Y
                If $f_FirstOnly Then ExitLoop 2
            EndIf
        Next
    Next
    ReDim $a_Pixels[$a_Pixels[0][0] + 1][2]
    ConsoleWrite("Color " & Hex($i_Color, 8) & " : " & $a_Pixels[0][0] & @CRLF) ; <= debug
    PixelSearch($i_X, $i_Y, $i_X + $i_Width, $i_Y + $i_Height, $i_Color, 0, 1, $h_Wnd) ; <= debug
    ConsoleWrite("PixelSearch error : " & @error & @CRLF) ; <= debug
    Return $a_Pixels
EndFunc


Добавлено:
Сообщение автоматически объединено:

st@rter [?]
стандартная то работает в активном окне
Для проверки стандартной нужно установить
Код:
Opt("PixelCoordMode", 2)
Возможно, ваша проблема как раз в разнице отсчёта координат - экранные, оконные или клиентские. Для функции _PixelGetArray() нужно указывать координаты относительно клиентской области окна.
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
Все перебровал и 0 и 2.. не так ни сяк...
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
1 скриншот это при варианте без отладки, все фотает, нужную область тоже.
2 показывает хп при котором он должен нажимать
3 при варианте с отладкой
 

Вложения

  • scr.png
    scr.png
    125 байт · Просмотры: 90
  • Безымянный.jpg
    Безымянный.jpg
    5.5 КБ · Просмотры: 5
  • PixelGetArray.jpg
    PixelGetArray.jpg
    1.2 КБ · Просмотры: 6

InnI

AutoIT Гуру
Сообщения
4,958
Репутация
1,448
st@rter [?]
это при варианте без отладки
Это тот, который использует _ScreenCapture_CaptureWnd() ? Если в этом варианте "все фотает, нужную область тоже", то координаты вы передаёте оконные, т.е. относительно левого верхнего угла окна. А в функцию _PixelGetArray() - ещё раз повторяю - нужно передавать координаты относительно клиентской области окна (это без учёта заголовка, меню и рамок окна).

при варианте с отладкой
Где вывод в консоль? Почему у вас разные размеры снимков "без отладки" и с отладкой?


Добавлено:
Сообщение автоматически объединено:

И почему у вас скриншоты png и jpg? В коде я прописал bmp - именно в этом формате нужно проверять правильность поиска пикселя.
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
InnI сказал(а):
Где вывод в консоль? Почему у вас разные размеры снимков "без отладки" и с отладкой?
Сам не понимаю, дак выходит вместо WinGetPos надо использовать WinGetClientSize ?
Код:
$x1=$HP
	$y1=65
	$x2=$HP+6
	$y2=75
	$coll=0x372A11
	$tmp = _PixelGetArray($x1, $y1, $x2-$x1, $y2-$y2, $coll, $HWnd, True)
	$abby[0]=$tmp[0][0]
	;$abby[0]=$coor
	local $vif = $abby[0] 
	MsgBox(64,"1",$vif)
	MsgBox(64,"1",$HP)

$HP выводит верно 267.2207 вродь, а вот $vif постоянно нуль
 

InnI

AutoIT Гуру
Сообщения
4,958
Репутация
1,448
st@rter [?]
надо использовать
Не надо ничего использовать. Просто запускаете Au3Info и включаете в меню опцию "Options - Coord Mode - Client". Теперь на вкладке "Mouse" координаты будут относительно клиентской части - вот их и используйте.
 
Автор
S

st@rter

Новичок
Сообщения
15
Репутация
0
Все получилось! Ура!!! InnI Спасибо огромное Вам!! За то что помогли и не прошли ммимо!! Ошибка была и вправлду в клиентской области!! Еще раз спасибо снимаю перед Вами шляпу!
 
Верх