Что нового

реализация pixelsearch через WinAPI_CreateCompatibleBitmap

zzonderr

Новичок
Сообщения
6
Репутация
0
Имеется скрипт

Код:
#include <Misc.au3>

$DLL = DllOpen("user32.dll")

While 1
	Sleep (100)
	If _IsPressed("02", $DLL) Then
		While _IsPressed("02", $DLL)
			Sleep (100)
			Send("{NUMPAD0}")
			PixelSearch(41, 1090, 41, 1090, 0X4CFF00)
			If Not @error Then
				Send(1)
			Else
				PixelSearch(65, 1125, 65, 1125, 0X4CFF00)
				If Not @error Then
					Send(2)
				Else
					PixelSearch(50, 1037, 50, 1037, 0X4CFF00)
					If Not @error Then
						Send(6)
					Else
						PixelSearch(70, 1037, 70, 1037, 0X4CFF00)
						If Not @error Then
							Send(7)
						EndIf
					EndIf
				EndIf
			EndIf
		WEnd
	EndIf
WEnd


Данный скрипт ищет в игре цвет одного пикселя в 4-х разных местах и нажимает на клавиши. т. е. если нашел в 1-ом, то нажимает кнопку и пускает цикл заново. если нет, то цикл идет дальше, если и во 2-ом ничего нет, то смотрит 3-ю координату.
проблема в том, что когда происходит поиск пикселя игруха чуток притормаживает и от этого неудобно играть.
вопрос. можно ли данный скрипт переделать под WinAPI_CreateCompatibleBitmap (читал что быстрее работает, но не понял как реализовать) и поможет ли это? исчезнут ли тормоза?
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
zzonderr
Смотри, например, здесь
http://autoit-script.ru/index.php?topic=14905.msg93908#msg93908

PixelSearch вообще медленный, особенно если в в Win 7 аэро включено
И области поиска надо как можно меньше выставлять
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
WSWR [?]
PixelSearch вообще медленный, особенно если в Win 7 аэро включено
Интересно. А у меня другие результаты. Вот сравнение на Win7 с аэро
Код:
#include <WinAPIEx.au3>
#include <WindowsConstants.au3>

$color = 0x123456

$iT = TimerInit()
PixelSearch(0, 0, 500, 500, $color)
ConsoleWrite("PixelSearch : " & TimerDiff($iT) & @LF)

$iT = TimerInit()
_PixelGetArray(0, 0, 500, 500, $color, 0, True)
ConsoleWrite("_PixelGetArray : " & TimerDiff($iT) & @LF)

Func _PixelGetArray($i_X, $i_Y, $i_Width, $i_Height, $i_Color, $h_Wnd = 0, $f_FirstOnly = False)
    Local $i_Size = $i_Width * $i_Height, $a_Pixels[$i_Size + 1][2] = [[0]], $h_DC, $h_MemDC, $h_Bitmap, $t_Bits, $i_Index
    $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   ;==>_PixelGetArray
Код:
PixelSearch : 30.9627226479243
_PixelGetArray : 577.934314859613
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
InnI
Интересно
Я PixelSearch редко пользуюсь, т.к. поиск пикселя меня интересует в основном в изображениях и видеокадрах
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
Ещё один пример
Код:
For $i = 0 To 2
  $t = TimerInit()
  PixelSearch(0, 0, 400, 400, 0x123456)
  ConsoleWrite($i & ":" & TimerDiff($t) & @LF)
Next

$t = TimerInit()
For $i = 0 To 19
  For $j = 0 To 19
    PixelSearch($j, $i, 400, 400, 0x123456)
  Next
Next
ConsoleWrite(TimerDiff($t) & @LF)

Код:
0:35.5964416552683
1:18.9652361241355
2:16.7039119454164
6980.50044907813
Получается, что при поиске единичного пикселя, быстрее работает PixelSearch(). А для составления массива пикселей, а также для работы с перекрытыми или "задвинутыми" окнами, лучше подходит _PixelGetArray(). Как-то так...
 
Автор
Z

zzonderr

Новичок
Сообщения
6
Репутация
0
Вот именно что дело в том, что мне нужно искать цвет точки. Но когда происходит поиск, в игрухе начинается небольшое слайдшоу. Играть можно, но глаза режет. Вот и интересно узнать, есть ли какая то альтернатива PixelSearch, чтоб не вызывало таких глюков? Где то тут читал, что вроде работает быстрее сохранение скрина в BMP и потом его анализ. Или все таки PixelSearch в моей ситуации подходит больше всего?
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
zzonderr [?]
сохранение скрина в BMP и потом его анализ
Функция _PixelGetArray() именно это и делает.

вроде работает быстрее
Зависит от конкретной ситуации (см. выше).

Или все таки PixelSearch в моей ситуации подходит больше всего?
Попробуйте обе функции - увидите разницу (или не увидите).
 
Автор
Z

zzonderr

Новичок
Сообщения
6
Репутация
0
Дело в том, что в синтаксисе не особо разбираюсь, долго пытался понять как _PixelGetArray применить к своему скрипту - безрезультатно. Не могли бы вы помочь в переделке скрипта? :smile: Хотя бы на одну координату, дальше по аналогии сам бы разобрался...
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
zzonderr
Код:
#include <Misc.au3>
#include <WinAPIEx.au3>
#include <WindowsConstants.au3>

$DLL = DllOpen("user32.dll")

While 1
    Sleep (100)
    If _IsPressed("02", $DLL) Then
        While _IsPressed("02", $DLL)
            Sleep (100)
            Send("{NUMPAD0}")
            $coord = _PixelGetArray(41, 1090, 1, 1, 0X4CFF00, 0, True)
            If $coord[0][0] Then
                Send(1)
            Else
                $coord = _PixelGetArray(65, 1125, 1, 1, 0X4CFF00, 0, True)
                If $coord[0][0] Then
                    Send(2)
                Else
                    $coord = _PixelGetArray(50, 1037, 1, 1, 0X4CFF00, 0, True)
                    If $coord[0][0] Then
                        Send(6)
                    Else
                        $coord = _PixelGetArray(70, 1037, 1, 1, 0X4CFF00, 0, True)
                        If $coord[0][0] Then
                            Send(7)
                        EndIf
                    EndIf
                EndIf
            EndIf
        WEnd
    EndIf
WEnd

Func _PixelGetArray($i_X, $i_Y, $i_Width, $i_Height, $i_Color, $h_Wnd = 0, $f_FirstOnly = False)
    Local $i_Size = $i_Width * $i_Height, $a_Pixels[$i_Size + 1][2] = [[0]], $h_DC, $h_MemDC, $h_Bitmap, $t_Bits, $i_Index
    $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   ;==>_PixelGetArray
 
Автор
Z

zzonderr

Новичок
Сообщения
6
Репутация
0
Спасибо, быстрей работать стал.


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

Решил попробовать запустить скрипт с выключенным Aero. И блин, какого черта я раньше не додумался его выключить. Игра при работе скрипта работает безо всяких тормозов даже если все Sleep'ы убрать из скрипта. В общем, извините за беспокойство, нужно было просто Aero выключить...
 
Верх