Что нового

[Автоматизация] Работа со "свёрнутой" игрой. Концепция не мешающего бота.

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Читая этот форум (особое внимание уделяя этой ветке), я встретил не одну и не две темы, которые можно объединить под названием "как сделать чтоб бот не мешал работать?". Такой же вопрос терзал и меня, и прочитав кучу тем и перелопатив кучу инфы, я его решил.
Но обо всём по порядку.
И так наша задача сделать бота который будет качать перса пока мы работаем за компом. При этом мы не можем использовать виртуальную машину из за слабого железа(ну или ещё почему то...). Какие у нас есть варианты?
  • бот работающий с пакетами и не нуждающийся ни в мышке, ни в клавиатуре
  • бот работающий с памятью клиента, и как следствие тоже не требующий нужных нам органов управления
  • бот кликер, кликающий без мышки, и видящий не видимое
Первые два варианта отметём сразу, покуда (не знаю как вы) я не достаточно умён для этого, да и во многих играх такие действия палятся администрацией.
Решено - создаём кликер! (если вы его еще не создали, и только потом заметили, что он мешается). Что нам понадобится? Да собственно сущие пустяки, а именно:
  • Функция кликающая в координаты игрового поля
  • Функция узнающая цвет в координатах игрового поля
Для первого идеально подходит ControlClick, и не будем на этом заострять внимание.
А вот второе у многих вызывает затруднения. Как считать цвет из свёрнутого окна? Отвечу сразу: НИКАК! из свёрнутого окна средствами автоита (и всего около него) нельзя!
Так как же быть? Не можем читать из свёрнутого, будем читать из развёрнутого. А чтоб оно не мешало разворачивать его будем за пределами видимой области экрана.
Встроенные функции, такие как PGC, PixelChekSum, PixelSearch..., сразу идут лесом! Ну не видят они цвета в координатах -3000,-3000 :wall_brake: Да и координаты такие нам не удобны, потому что не соответствуют тем которые нам в ControlClick нужны.
Тут нам приходит на помощь подаренная мелкомягкими функция PrintWindows, и великая библиотека http://autoit-script.ru/index.php?topic=47.0.

Не буду расписывать всех подробностей, всё можно прочитать в теме http://autoit-script.ru/index.php?topic=1057.msg7526#msg7526
Как результат всего рассмотренного в этой теме (огромный респект всем её участникам) мы получили функцию:
Код:
Func _detekt ($iX, $iY)
		Local $hDDC, $hCDC, $hBMP
		$iWidth = _WinAPI_GetWindowWidth($hWnd)
		$iHeight = _WinAPI_GetWindowHeight($hWnd)
		$hDDC = _WinAPI_GetDC($hWnd)
		$hCDC = _WinAPI_CreateCompatibleDC($hDDC)
		$hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
		_WinAPI_SelectObject($hCDC, $hBMP)
		DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
		$sColor = _WinAPI_GetPixel($hCDC, $iX, $iY)
		_WinAPI_ReleaseDC($hWnd, $hDDC)
		_WinAPI_DeleteDC($hCDC)
	   _WinAPI_DeleteObject($hBMP) ; очищаем битовый массив
;~ 	   Sleep(90)
		Return $sColor
EndFunc

Для работоспособности данной функции нам понадобится только глобально обьявленный $hWnd

В целом она хороша, но как уже говорилось железо у нас слабое, а потребности нашего бота растут, и вот уже нужно опрашивать цвета в больших цыклах, и создавать на основе этого принципа аналоги PixelSerch, и прочее. И вот тут то лежат большие агрессивные грабли. При слишком частом использовании PrintWindow железо начинает затыкаться, всё начинает тормозить, и в конце концов и вовсе перестаёт работать. Избавится от такой проблемы оказалось не сложно. Зачем снимать скриншоты с бедной игрушки на каждый наш запрос?
РАзделим функцию на две:
Код:
Global $hDDC, $hCDC, $hBMP
AdlibRegister("_BitmapWin", 500)
Func _detekt ($iX, $iY)
		$sColor = _WinAPI_GetPixel($hCDC, $iX, $iY)
		Return $sColor
EndFunc
Func _BitmapWin()
	_WinAPI_DeleteDC($hCDC)
	_WinAPI_DeleteObject($hBMP) ; очищаем битовый массив
	$iWidth = _WinAPI_GetWindowWidth($hWnd)
	$iHeight = _WinAPI_GetWindowHeight($hWnd)
	$hDDC = _WinAPI_GetDC($hWnd)
	$hCDC = _WinAPI_CreateCompatibleDC($hDDC)
	$hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iWidth, $iHeight)
	_WinAPI_SelectObject($hCDC, $hBMP)
	DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "hwnd", $hCDC, "int", 0)
	$sColor = _WinAPI_GetPixel($hCDC, $iX, $iY)
	_WinAPI_ReleaseDC($hWnd, $hDDC)
EndFunc


Теперь наш бот одним глазком раз в пол секунды поглядывает на игру, и работает с тем, что запомнил. Можно ещё написать свои аналоги для PixelSerch и прочего...

Не претендую на оригинальность просто попытался обобщить всё прочитанное по данному вопросу.
 
Автор
N

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Когда у меня возникла необходимость реализации pixelSerch за пределами экрана и в неактивном окне, я написал примитивную функцию на двух For и _WinAPI_GetPixel. Потребности снова ростут, и такое решение оказалось очень медленным. Вникнув в тему: http://autoit-script.ru/index.php?topic=3943.0 получилось несколько ускорить:

Код:
Func _SearchPix($x1, $y1, $x2, $y2, $coll, $shvar=0, $step=1)
	$ARGB = _WinAPI_IntToDWord(BitOR($coll, 0xFF000000))
	$Size = WinGetClientSize($hWnd)
	$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
		Local $coor[2] = [$x, $y]
		Return $coor
	EndIf
EndFunc


Конечно тоже медленно, но уже ощутимо быстрее чем на циклах:область поиска 100х100 пикселей, искомый последний в области:
Код:
новая
698.430107737157
X = 700
Y = 631

старая
1572.11461233201
X = 700
Y = 631
Как бы ещё shade-variation к ней приделать!? :idea:

И наконец у нас остаётся последний вопрос: как же теперь всё это сворачивать?
  • Вариант 1: делаем хот кей который перемещает окно с игрой куда нибудь за пределы экрана(лучше не использовать астрономические цифры). А при повторном нажатии возвращает.
  • Вариант 2: цепляем это действие на событие сворачивания(разворачивания) GUI нашего бота
  • Вариант 3: если нам не часто приходится смотреть на игру. сворачиваем игру обычным способом, а для каждого "взгляда" наш бот её разворачивает, ессно за пределы экрана

Используя всё выше описанное можно создать не мешающего бота, а при желании сделать так чтобы обычный обыватель поверил, что наш бот и впрямь сворачивается )) :IL_AutoIt_1:

Остался не решённым вопрос с реализацией MouseClickDrag... если у кого то есть какие то мысли, предлагаю писать в этой теме, потому как вроде логическое продолжение.

Пока использую довольно не красивую функцию:
Код:
Func _ClickDragEx($key, $x1, $y1, $x2, $y2, $speed)	;таскает грызуном(кладёт на место)
	Opt ("MouseCoordMode", 1)
	$tppp = MouseGetPos()
	Opt ("MouseCoordMode", 2)
	Opt ("PixelCoordMode", 2)
	$titAct = WinGetTitle("")
	WinActivate($titl)
	WinWaitActive($titl)
	MouseClickDrag($key, $x1, $y1, $x2, $y2, $speed)
	WinActivate($titAct)
	WinWaitActive($titAct)
	Opt ("MouseCoordMode", 1)
	MouseMove($tppp[0], $tppp[1], 0)
	Opt ("MouseCoordMode", 2)
	Opt ("PixelCoordMode", 2)
EndFunc
 

lirikmel

Продвинутый
Сообщения
225
Репутация
84
конечно спасибо особенно по первому пункту НО с теми нужными временными интервалами например для сбора информации о хп мне кажется она не справиться ...потестирую обязательно :-[
ну а по второму скрипту...может проще использовать WinMove ? :blink:

ЗЫ что касается работы в неактивном окне....все таки в 80 процентов не получается отправить controlsend и это главная проблема
 
Автор
N

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
lirikmel сказал(а):
конечно спасибо особенно по первому пункту НО с теми нужными временными интервалами например для сбора информации о хп мне кажется она не справиться ...потестирую обязательно :-[
ну а по второму скрипту...может проще использовать WinMove ? :blink:

ЗЫ что касается работы в неактивном окне....все таки в 80 процентов не получается отправить controlsend и это главная проблема
Речь не о перемещении окна (тут однозначно WinMove), а о пертаскивании предметов в игре, или перемещении игрового поля.

А по поводу интервалов... Ну тут можно сделать и чаще AdlibRegister("_BitmapWin", 250), и вот наша картинка обновляется уже 4 раза в секунду. Просто как показала практика чем реже - тем стабильнее.

Вот с ControlSend чесно говоря почти не сталкивался. Пробовал одну игруху, так она вообще теряет чувтвительность и к ControlClick, и к ControlSend при переводе фокуса на другое окно. Хотя может тут проблемма с не правильным определением хэндла.
 
Автор
N

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
edward_freedom сказал(а):
я даже знаю,где ты эти скрипты взял... :blink:
Нечего сказать - не флуди!
OffTopic:
Всё то что не написал сам, то нашёл на этом форуме, стараясь не создавать лишних тем.
 

lirikmel

Продвинутый
Сообщения
225
Репутация
84
ссори не много не понял суть второго скрипта ...ну а насчет controlsend это видимо как повезет ..мне вот не везет -))....хотя уже есть много аналогов
Код:
; send single keyboard event to non active window
; event = pressed, down, up
; kdown = key down delay
; note: supports only lower case keys + NUMx, Fx, some special keys and @
#include <WindowsConstants.au3>
#include <WinAPI.au3>
 $hwnd = WinGetHandle("IRIS ONLINE v1.18.22996")
 ConsoleWrite("Window handle is " & $hwnd & @CRLF)
Func KeySend($inkey, $evt ="pressed", $kdown = 50)
    $user32 = DllOpen("user32.dll")
    if $user32 = -1 Then
        ConsoleWrite("KeySend: cannot open user32.dll")
        Exit
    EndIf

    ; handling for special keys
    Switch StringUpper($inkey)
    Case "@"
        $skey = 0x40
        $lparam = 0x00100001
        DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYDOWN, "int", 0x71, "long", $lparam)
        DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_CHAR, "int", $skey, "long", $lparam)
        Sleep(20)
        DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYUP, "int", 0x71, "long", BitOR($lparam, 0xC0000000))
    Case "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12"
        $skey = 0x6f + Int(StringMid($inkey, 2))
        ContinueCase
    Case "NUM0", "NUM1", "NUM2", "NUM3", "NUM4", "NUM5", "NUM6", "NUM7", "NUM8" , "NUM9"
        if StringUpper(StringLeft($inkey, 3)) = "NUM" Then
            $skey = 0x60 + Int(StringMid($inkey, 4))
        EndIf
        ContinueCase
    Case "RETURN", "SPACE", "TAB", "BACK", "END", "HOME", "SNAPSHOT", "INSERT", "DELETE", "LEFT", "RIGHT", "UP", "DOWN"
        Switch StringUpper($inkey)
        Case "RETURN"
            $skey = 0x0D
        Case "SPACE"
            $skey = 0x20
        Case "TAB"
            $skey = 0x09
        Case "BACK"
            $skey = 0x08
        Case "END"
            $skey = 0x23
        Case "HOME"
            $skey = 0x24
        Case "SNAPSHOT"
            $skey = 0x2c
        Case "INSERT"
            $skey = 0x2d
        Case "DELETE"
            $skey = 0x2e
        Case "LEFT"
            $skey = 0x25
        Case "RIGHT"
            $skey = 0x27
        Case "UP"
            $skey = 0x26
        Case "DOWN"
            $skey = 0x28
        EndSwitch
        $ret = DllCall($user32, "int", "MapVirtualKey", "int", $skey, "int", 0)
        $lparam = BitShift($ret[0], -16)
        $lparam = BitOr($lparam, 1)
        DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYDOWN, "int", $skey, "long", $lparam)
        Sleep($kdown)
        DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYUP, "int", $skey, "long",   BitOR($lparam, 0xC0000000))
    Case Else ; default lower case key handling
        $key = DllCall($user32, "int", "VkKeyScan", "int", Asc(StringLower($inkey)))
        $skey = $key[0]
        $ret = DllCall($user32, "int", "MapVirtualKey", "int", $skey, "int", 0)
        $lparam = BitShift($ret[0], -16)
        $lparam = BitOr($lparam, 1)
        Select
        Case $evt = "pressed"
            DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYDOWN, "int", $skey, "long", $lparam)
            Sleep($kdown)
            DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYUP, "int", $skey, "long",   BitOR($lparam, 0xC0000000))
        Case $evt = "down"
            DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYDOWN, "int", $skey, "long", $lparam)
        Case $evt = "up"
            DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYUP, "int", $skey, "long",   BitOR($lparam, 0xC0000000))
        EndSelect
    EndSwitch

    DllClose($user32)
EndFunc



еще аналог
Код:
#include-once
#include "KeyCodes.au3"
#include <WindowsConstants.au3>

Func _PostMessage_Send($hWnd, $Key, $Delay = 10)
    If StringLen($Key) == 1 Then
        If $Key == "+" Or $Key == "^" Or $Key == "!" Then
            SetError(1)
        Else
            $Key = StringUpper($Key)
            $Key = StringToBinary($Key)
        EndIf
    Else
        $Key = _ReplaceKey($Key)
    EndIf

    $Key_ = DllCall("user32.dll", "int", "MapVirtualKey", "int", $Key, "int", 0)
    If IsArray($Key_) Then
        DllCall("user32.dll", "bool", "PostMessage", "hwnd", $hWnd, "int", $WM_KEYDOWN, "int", $Key, "long", _MakeLong(1, $Key_[0]))
        Sleep($Delay)
        DllCall("user32.dll", "bool", "PostMessage", "hwnd", $hWnd, "int", $WM_KEYUP, "int", $Key, "long", _MakeLong(1, $Key_[0]) + 0xC0000000)
    Else
        SetError(2)
    EndIf
EndFunc

Func _PostMessage_Click($hWnd, $X = Default, $Y = Default, $Button = "left", $Clicks = 1, $Delay = 10)
    If $Button == "left" Then
        $Button = $WM_LBUTTONDOWN
    ElseIf $Button == "right" Then
        $Button = $WM_RBUTTONDOWN
    ElseIf $Button == "middle" Then
        $Button = $WM_MBUTTONDOWN
        If $Delay < 100 Then $Delay = 100
    EndIf

    $WinSize = WinGetClientSize($hWnd)
    If $X == Default Then $X = $WinSize[0] / 2
    If $Y == Default Then $Y = $WinSize[1] / 2

    For $j = 1 To $Clicks
        DllCall("user32.dll", "bool", "PostMessage", "hwnd", $hWnd, "int", $Button, "int", "0", "long", _MakeLong($X, $Y))
        Sleep($Delay)
        DllCall("user32.dll", "bool", "PostMessage", "hwnd", $hWnd, "int", $Button + 1, "int", "0", "long", _MakeLong($X, $Y))
    Next
EndFunc

Func _MakeLong($LoDWORD, $HiDWORD) ;WinAPI.au3
    Return BitOR($HiDWORD * 0x10000, BitAND($LoDWORD, 0xFFFF))
EndFunc


и вот
Код:
#include-once

; #INDEX# =======================================================================================================================
; Title .........: SendMessage
; AutoIt Version : 3.1.1++
; Language ......: English
; Description ...: Functions that assist SendMessage calls.
; Author(s) .....: Valik, Gary Frost
; Dll(s) ........: user32.dll
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
;_SendMessage
;_SendMessageA
; ===============================================================================================================================

; #FUNCTION# ====================================================================================================================
; Name...........: _SendMessage
; Description ...: Wrapper for commonly used Dll Call
; Syntax.........: _SendMessage($hWnd, $iMsg[, $wParam = 0[, $lParam = 0[, $iReturn = 0[, $wParamType = "wparam"[, $lParamType = "lparam"[, $sReturnType = "lresult"]]]]]])
; Parameters ....: $hWnd       - Window/control handle
;                  $iMsg       - Message to send to control (number)
;                  $wParam     - Specifies additional message-specific information
;                  $lParam     - Specifies additional message-specific information
;                  $iReturn    - What to return:
;                  |0 - Return value from dll call
;                  |1 - $ihWnd
;                  |2 - $iMsg
;                  |3 - $wParam
;                  |4 - $lParam
;                  |<0 or > 4 - array same as dllcall
;                  $wParamType - See DllCall in Related
;                  $lParamType - See DllCall in Related
;                  $sReturnType - See DllCall in Related
; Return values .: Success      - User selected value from the DllCall() result
;                  Failure      - @error is set
; Author ........: Valik
; Modified.......: Gary Frost (GaryFrost) aka gafrost
; Remarks .......:
; Related .......: _SendMessage, DllCall
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func _SendMessage($hWnd, $iMsg, $wParam = 0, $lParam = 0, $iReturn = 0, $wParamType = "wparam", $lParamType = "lparam", $sReturnType = "lresult")
	Local $aResult = DllCall("user32.dll", $sReturnType, "SendMessageW", "hwnd", $hWnd, "uint", $iMsg, $wParamType, $wParam, $lParamType, $lParam)
	If @error Then Return SetError(@error, @extended, "")
	If $iReturn >= 0 And $iReturn <= 4 Then Return $aResult[$iReturn]
	Return $aResult
EndFunc   ;==>_SendMessage

; #FUNCTION# ====================================================================================================================
; Name...........: _SendMessageA
; Description ...: Wrapper for commonly used Dll Call (Force Ansi Call)
; Syntax.........: _SendMessageA($hWnd, $iMsg[, $wParam = 0[, $lParam = 0[, $iReturn = 0[, $wParamType = "wparam"[, $lParamType = "lparam"[, $sReturnType = "lresult"]]]]]])
; Parameters ....: $hWnd       - Window/control handle
;                  $iMsg       - Message to send to control (number)
;                  $wParam     - Specifies additional message-specific information
;                  $lParam     - Specifies additional message-specific information
;                  $iReturn    - What to return:
;                  |0 - Return value from dll call
;                  |1 - $ihWnd
;                  |2 - $iMsg
;                  |3 - $wParam
;                  |4 - $lParam
;                  |<0 or > 4 - array same as dllcall
;                  $wParamType - See DllCall in Related
;                  $lParamType - See DllCall in Related
;                  $sReturnType - See DllCall in Related
; Return values .: Success      - User selected value from the DllCall() result
;                  Failure      - @error is set
; Author ........: Valik
; Modified.......: Gary Frost (GaryFrost) aka gafrost
; Remarks .......:
; Related .......: _SendMessage, DllCall
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func _SendMessageA($hWnd, $iMsg, $wParam = 0, $lParam = 0, $iReturn = 0, $wParamType = "wparam", $lParamType = "lparam", $sReturnType = "lresult")
	Local $aResult = DllCall("user32.dll", $sReturnType, "SendMessageA", "hwnd", $hWnd, "uint", $iMsg, $wParamType, $wParam, $lParamType, $lParam)
	If @error Then Return SetError(@error, @extended, "")
	If $iReturn >= 0 And $iReturn <= 4 Then Return $aResult[$iReturn]
	Return $aResult
EndFunc   ;==>_SendMessageA


ну и с другой стороны
Код:
#FUNCTION# ======================================================================================
; Name ..........: ssend()
; Description ...: Sends a string to a specified Control
; Syntax ........: ssend($hWnd, $sString[, $iHex = 0[, $bSendMsg = True]])
; Parameters ....: $hWnd     - Control Handle to send to.
;                  $sString  - String to send
;                  $iHex     - [optional] Determines wether you want to send pure hex, or not. (default:0)
;                  |This can be handy, if you want to send special keystrokes like ENTER (0D)
;                  |0 - Convert String to Hex first
;                  |1 - Do not convert string to Hex
;                  $bSendMsg - [optional] Determines weither you want to send WM_SETFOCUS and WM_ACTIVATE messages beforehand. (default:False)
; Return values .: On Success - Returns 1
;                  On Failure - Returns 0 and sets @error to
;                  |-1 $hWnd is not a Hwnd-Type var.
;                  |>1 error(s) occured when trying to send string
; Author ........: hamburger, modified by SEuBo
; =================================================================================================
#include<winapi.au3>
#include<string.au3>

Func ssend($hWnd, $sString, $iHex = 0, $bSendMsg = False)
    If Not IsHWnd($hWnd) Then Return SetError(-1, 0, 0)
    Local $aPar, $aText, $iErr

    ; 1. Get Parent Window. 2. Send WM_ACTIVATE to Parent. 3. Send WM_SETFOCUS to Control.
    If $bSendMsg Then
        $aPar = DllCall("user32.dll", "hwnd", "GetParent", "hwnd", $hWnd)
        If @error Then Dim $aPar[1] = [WinGetHandle("rhbgn.txt — Блокнот")]
        _SendMessage($aPar[0], 0x0006, $sString, 0, 0, "int", "long")
        _SendMessage($hWnd, 0x7)
    EndIf

    ; Send WM_CHAR messages to Control.
    If $iHex Then _SendMessage($hWnd, 0x102, $sString, 0, 0, "int", "long")
    If @error Then $iErr +=1
    If Not $iHex Then
        $aText = StringSplit($sString, "", 3)
        For $i = 0 To UBound($aText) - 1
            _SendMessage($hWnd, 0x102, "0x" & Hex(StringToBinary($aText[$i])), 0, 0, "int", "long")
            If @error Then $iErr +=1
        Next
    EndIf

    If $iErr Then Return SetError($iErr,0,0)
    Return SetError(0,0,1)
;~  _SendMessage($hwnd, 0x8)
EndFunc   ;==>ssend
 
Автор
N

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
lirikmel сказал(а):
ссори не много не понял суть второго скрипта
Это про _clickDragEx? - суть примитивная - просто вернуть грызуна на то место откуда взяли, и вернуть фокус тому окну у которого он был отобран. Это хотя бы как то позволяет работать рядом с таким ботом, благо таких действий мало. Подозреваю, что если можно отправить контролу эмуляцию клика, то как то можно и эмулировать перетаскивание мышкой... Копать видимо надо в сторону API... Проблема в том что просто нажать левую кнопку в одних координатах, и отпустить в других - не достаточно :(
 

lirikmel

Продвинутый
Сообщения
225
Репутация
84
если ты отбираешь фокус- и возвращаешь его на место....ты этим как никак прерываешь процесс..уже бот мешается...как это можно назвать концепцией не мешающего бота....ммм а что касается кликов и перетаскиваний попробуй другим способом например натыкался на удф MousclickPlus ..обычно она справляется с задачами что контролсенд не подсилу.

ПС что за игра? к каждой нужен индивидуальный подход ,что касаемо нажатий -))
 
Автор
N

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
lirikmel сказал(а):
если ты отбираешь фокус- и возвращаешь его на место....ты этим как никак прерываешь процесс..уже бот мешается...как это можно назвать концепцией не мешающего бота....ммм а что касается кликов и перетаскиваний попробуй другим способом например натыкался на удф MousclickPlus ..обычно она справляется с задачами что контролсенд не подсилу.
А я как раз и сказал что пока использую такую НЕудобную функцию.
А про UDF я знаю, как раз на её основе пытался реализовать, с кликами она справляется на ура, но вот тащить пока не получается (
 
Автор
N

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Как бы реализовать собственный shade-variation см. второй пост :wall_brake:
 

Belfigor

Модератор
Локальный модератор
Сообщения
3 597
Репутация
938
Вероятнее всего Шейд - это допуск по ргб. То есть шейд 10 это будет R+-10, G+-10, B+-10. Тоесть все что тебе надо это разложить полученный RGB цвет на отдельные цвета и посмотреть входит ли каждый из цветов проверяемого пикселя в допустимую погрешность от искомого. И то что в PS максимальный шейд - 255 говорит в пользу моего предположения :smile:
 
Автор
N

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Да это видимо так... Вот только попробовал сделать простой арифметикой
Код:
If Abs($R-$eR)<=$shvar And Abs($G-$eG)<=$shvar And Abs($B-$eB)<=$shvar Then Return True
для 100х100 получил:
Код:
12014.1294494133
X = 700
Y = 631
:( Думается надо смотреть в сторону побитовых операций, вот только плохо я в школе учился :wall_brake:
 

Arei

Скриптер
Сообщения
938
Репутация
115
NoMad73rus скажи как в твоей _SearchPix сделать качество обработки пикселей.
 

MrSokol

Новичок
Сообщения
11
Репутация
0
подскажите пожалуйста, есть рабочий скрипт использующий функцию WinAPI_GetPixel. Так вот, при тестировании в Win7 и WinXp GetPixel выдает разные цвета в одной и той-же точке... Вот я и не могу понять, то ли у меня где-то проблема в скрипте (хотя использовал функцию, которая описанна в этой теме в самом начале) либо так и должно быть? Вроде API один и тот же.
 

axlwor

Скриптер
Сообщения
657
Репутация
147
Window Info выдает разные цвета или только скрипт?
 

MrSokol

Новичок
Сообщения
11
Репутация
0
Windows Info выдает разные цвета...Win7 на реальной машине - один цвет; WinXp на виртуалке в той-же точке - совершенно другой...Но есть точки которые совпадают по цвету, экспериментальным путем выяснил что больше половины точек в окне 1280х960 совпадают, а в некоторых местах - нет
 

axlwor

Скриптер
Сообщения
657
Репутация
147
Когда игрался с PixelGetColor делал для каждой машинки/оси свои пресеты. Разрешения экрана, темы винды, ось, да и сами цвета заливают по разному - все это иногда влияло.
Делаешь настройки в ини (или xml) файлы, и по какому нибудь уникальному значению (например) выбираешь.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3 597
Репутация
938
MrSokol сказал(а):
подскажите пожалуйста, есть рабочий скрипт использующий функцию WinAPI_GetPixel. Так вот, при тестировании в Win7 и WinXp GetPixel выдает разные цвета в одной и той-же точке... Вот я и не могу понять, то ли у меня где-то проблема в скрипте (хотя использовал функцию, которая описанна в этой теме в самом начале) либо так и должно быть? Вроде API один и тот же.
потому что использовать нужно не функцию определения цвета пикселя, а функцию поиска пикселя по заданному цвету с заданной погрешностью, то есть PixelSearch и аналоги.
 
Автор
N

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Windows Info выдает разные цвета...Win7 на реальной машине - один цвет; WinXp на виртуалке в той-же точке - совершенно другой...Но есть точки которые совпадают по цвету, экспериментальным путем выяснил что больше половины точек в окне 1280х960 совпадают, а в некоторых местах - нет
Это специфика 7ки, просто отключите аеро и прочие красявости, и цвета совпадут. А лучше действительно отказаться от точного сравнения цвета.

Можно использовать такую функцию
Код:
#include <Color.au3>
Func _CheckColor($x, $y, $color, $shvar=0, $hWnd='')
	$nColor = PixelGetColor($x, $y, $hWnd)
	If Abs(_ColorGetRed($nColor)-_ColorGetRed($color))<=$shvar And Abs(_ColorGetGreen($nColor)-_ColorGetGreen($color))<=$shvar And Abs(_ColorGetBlue($nColor)-_ColorGetBlue($color))<=$shvar Then Return SetError(0, 0, True)
Return SetError(1, 0, False)
EndFunc
 
Верх