Что нового

[World Of Warplanets] Написание достойного бота

ivanius

Знающий
Сообщения
74
Репутация
5
OffTopic:
Старый пост:
Предисловие :
Я программист Delphi\C++ после начала кризиса и сокращения фрилансер-программист VBA\VBS, специализируюсь на автоматизации Excel, Windows, Internet процессов т.е. парсинг, структуризация данных, автоматизация расчетов, залитие данных в интернет, какие-то смешаные парсинг+структуризация+отправка на почту и это все по таймеру и с параметрами и т.д. Но отдыхать, сбрасывать стресс нужно и делаем мы это чаще в играх.

Игра:
World Of Warplanets - Авиасимулятор от разработчиков WOT и соответственно на том-же движке что и танки.
Сложность состоит в том что есть очень много параметров которые нужно учитывать в полете - скорость, высота (барометрическая - ур моря и радиометрическая - реальная), ландшафт, объекты и т.д.
Из того что облегчает нам жизнь - самолет уже на старте имеет достаточную высоту и скорость, направление тоже можно не менять.

Задача:
Минимум - поднимаемся еще чуть выше чем все, если долетим до базы живыми бомбим, стреляем или врезамся в обьекты, чтобы получить профит.
Средняя - минимум + небольшое маневрирование от атак самолетов, точное прицеливание бомб\ракет\пулеметов на обьекты, выжить летая по краям карты.
Максимум - Средняя + стрельба по самолетам после бомбежки обстрела зданий или если во время бомбежки нас кто-то атакует.

Ход выполнения:
Работаю уже в течении месяца небольшими шагами.
Первую неделю потратил на поиск статического указателя, который так и не был найден на параметры самолета (4-5 ур. дл 8192 смещения).
На UOPilot написал поиск макс, мин значений высоты\скорости - что как в итоге оказалось по геймплею не особо нужно было, нашел стрелочку указывающую на текущее положение скорости и высоты, определил ее уникальные цвета и точную область поиска этого пикселя, изменение положения GUI в зависимости от разрешения.
Положение на карте - текущее мое, врагов, союзников, обьектов.

Ну и пока все, дальше я нашел уже написанный очень небольшой и не работающий скрипт, но в котором были заложены небольшие основы, а самое главное показано что можно изменить GUI на свой - чем упростить задачу поиска многих ВАЖНЫХ вещей - чем собственно сейчас и занимаюсь + изучение нюансов синтаксиса нового языка.

Теперь по пунктам:
-1)Переписать то что уже написано на новый язык, исправить и разобрать уже написанный не работающий скрипт.
0)Сам полет, в зависимости от разрешение вычислять кол-во пикселей для смещения указателя в нужную сторону, использование "форсажа"(ускорения) и "0й тяги"(тормоза).
1)Определение статических обьектов (после захвата цели и на достаточном расстоянии появляются желтые квадратики) для атаки разными типами оружия. Можно для начала врезатся в него, главное определить по картинке\цвету сам обьект.
2)Определение "Опасной высоты", "опасного крена", "низкой скорости" и др. чтобы избежать падения, хотя бы симулировать попытки выжить.
3)Определение направления нашего движения (тоненькая прямая на карте от носа самолета - стрелочки на карте).
4)Маневрирование от самолетов - небольшие повороты влево\право или вверх\вниз.
5)Маневрирование к самолетам, а лучше дальше заняться уже написанием собственного GUI.

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

Скриншоты:

скрипт любезно предоставленный "DIMONPC2010":
Код:
#include <Misc.au3>
 ;Функци для наведени прицела на нужный цвет
 Func MouseMove_for_color($x,$y,$Window_posX,$Window_posY,$Window_width,$Window_height)

   $aPos = MouseGetPos()
   $MidleX=$Window_posX+($Window_width/2)
   $MidleY=$Window_posY+(($Window_height-38)/2)+30
   $toX = $x - $MidleX
   $toY = $y - $MidleY
   $aX = ( 100 / ($Window_width-16) ) * $toX
   $aY = ( 100 / ($Window_height-38) ) * $toY
   $dX=( 192 / 360 ) * $aX
   $dY=( 108 / 360 ) * $aY
   $X=$aPos[0]+$dX
   $Y=$aPos[1]+$dY
   MouseMove($X,$Y ,100);192,108

 EndFunc


$aWinPos = WinGetPos("World of Warplanes");  1.6.1
If @error Then
   MsgBox(48, 'Error!', 'World of Warplanes не запущен!')
EndIf
$EndX=$aWinPos[0]+$aWinPos[2]
$EndY=$aWinPos[1]+$aWinPos[3]
$hWnd = WinGetHandle("World of Warplanes  1.6.1")
$Flag_Ground_attack=1
MsgBox(0, 'BOT', 'Для запуска нажмите "ОК" / Для остановки удерживайте "X"')
MsgBox(0, 'BOT', 'Наведите указатель на первый самолет и нажмите 1')
While 1
   Sleep(1)
    If _IsPressed("31") Then
	   $new_plane_1 = MouseGetPos()
	   ExitLoop
	Else
	EndIf
 WEnd
 MsgBox(0, 'BOT', 'Наведите указатель на второй самолет и нажмите 2')
 While 1
	Sleep(1)
    If _IsPressed("32") Then
	   $new_plane_2 = MouseGetPos()
	   ExitLoop
	Else
	EndIf
 WEnd
 MsgBox(0, 'BOT', 'Наведите указатель на третий самолет и нажмите 3')
While 1
   Sleep(1)
    If _IsPressed("33") Then
	   $new_plane_3 = MouseGetPos()
	   ExitLoop
	Else
	EndIf
WEnd
$FLAG=1
;Sleep( 15000 )
While 1
    If _IsPressed("58") Then
	   Exit
	Else
	   EndIf
   ;Нажимаем В бой!
   $GoX=(581+$aWinPos[0]+8)
   $GoY=(570+$aWinPos[1]+30)
   $GoXEnd=(706+$aWinPos[0]+8)
   $GoYEnd=(615+$aWinPos[1]+30)
   $GO = PixelSearch($GoX, $GoY, $GoXEnd, $GoYEnd, 0xB0370B, 1, 1, hWnd)
   If Not @error Then
	  MouseMove(680+$aWinPos[0]+8,595+$aWinPos[1]+30 ,100)
	  MouseClick("left")
	  MouseMove($aWinPos[0]+($aWinPos[2]/2),$aWinPos[1]+(($aWinPos[3]-38)/2)+30-5 ,100)
   Else
	  ;Очередь самолетов
	  $GO = PixelSearch($GoX, $GoY, $GoXEnd, $GoYEnd, 0x828282, 1, 1, hWnd)
	  If Not @error Then
		 If $FLAG=1 Then
		 MouseMove($new_plane_1[0],$new_plane_1[1],100)
		 MouseClick("left")
		 $FLAG=2
		 Else
			EndIf
		 If $FLAG=2 Then
		 MouseMove($new_plane_2[0],$new_plane_2[1],100)
		 MouseClick("left")
		 $FLAG=3
		 Else
			EndIf
		 If $FLAG=3 Then
		 MouseMove($new_plane_3[0],$new_plane_3[1],100)
		 MouseClick("left")
		 $FLAG=1
		 Else
			EndIf
	  EndIf
   ;Ждем начало боя, установка начального направления полета
   $StartBattle = PixelSearch((1055+$aWinPos[0]+8), (125+$aWinPos[1]+30), (1189+$aWinPos[0]+8), (179+$aWinPos[1]+30), 0x75E100, 5, 1, hWnd)
   If Not @error Then
	  Sleep( 70000 )
	  $NewPos0=MouseGetPos()
	  $rand0=Random(0, 2, 1)
	  If $rand0>1 Then
	  MouseMove($NewPos0[0]+20,$NewPos0[1]-3 ,100)
	  Sleep( 3500 )
	  Else
		 EndIf
	  If $rand0<1 Then
		 MouseMove($NewPos0[0]-20,$NewPos0[1]-3 ,100)
		 Sleep( 3000 )
	  Else
		 EndIf
	  Sleep( 3000 )
   Else
	  EndIf
   ;Выход из боя если самолет сбили
   $GoAway = PixelSearch((654+$aWinPos[0]), (600+$aWinPos[1]), (685+$aWinPos[0]), (631+$aWinPos[1]), 0xFFFF00, 5, 1, hWnd)
   If Not @error Then
	  Send("{ESC}")
	  Sleep(100)
	  MouseMove(633+$aWinPos[0]+8,319+$aWinPos[1]+30 ,10)
	  Sleep(100)
	  MouseClick("left")
	  Sleep(100)
	  MouseMove(637+$aWinPos[0]+8,421+$aWinPos[1]+30 ,10)
	  Sleep(100)
	  MouseClick("left")
	  Sleep(5000)
   Else
	  EndIf
   ;Если самолет выжил то закрываем результаты боя
   $CloseRes = PixelSearch($GoX, $GoY, $GoXEnd, $GoYEnd, 0x0E1318, 1, 1, hWnd)
   If Not @error Then
	  Send("{ESC}")
   Else
   EndIf
   ;Реагируем если по нам стреляют
   $Damage = PixelSearch((531+$aWinPos[0]), (274+$aWinPos[1]), (783+$aWinPos[0]), (573+$aWinPos[1]), 0xFF0000, 10, 1, hWnd)
	  If Not @error Then
		 MouseMove_for_color($Damage[0]+5,$Damage[1],$aWinPos[0],$aWinPos[1],$aWinPos[2],$aWinPos[3])
	  Else
		 EndIf
   ;Стреляем если видим синий цвет
$coord = PixelSearch(($aWinPos[0]), ($aWinPos[1]), ($EndX), ($EndY), 0x0000FF, 10, 10, hWnd)
If Not @error Then
   MouseMove_for_color($coord[0],$coord[1],$aWinPos[0],$aWinPos[1],$aWinPos[2],$aWinPos[3])
   Sleep ( 500 )
   MouseDown("left")
Else
   MouseUp("left")
   ;Если не стреляем то чего нибуть делаем
   $NewPos=MouseGetPos()
   $rand=Random(0, 2, 1)
   If $rand>1 Then
	  MouseMove($NewPos[0]+10,$NewPos[1], 100)
	  Sleep( 100 )
	  MouseMove($NewPos[0]+10,$NewPos[1], 100)
	  Sleep( 100 )
   Else
	  EndIf
   If $rand<1 Then
	  MouseMove($NewPos[0]-10,$NewPos[1], 100)
	  Sleep( 100 )
	  MouseMove($NewPos[0]-10,$NewPos[1], 100)
	  Sleep( 100 )
   Else
	  EndIf
   Sleep( 300 )
EndIf
EndIf
WEnd

П.С. Сильно не пинайте, если что - пишите я все поправлю.
Как говорится: "Прогресс не стоит на месте" и мой код этому соответствует.​

Прогресс написание бота: 75-80%.
Использовано: FastFind Библиотека для увеличения скорости поиска информации на экране, WinAPI для отображения Debug сообщений и отрисовки линий, сам AutoIt.

Работает
Авто Пилот: управляет рандомно самолетом - просто летает не врезаясь, не падая, пока не маневрирует от стрельбы (маневрирует но в 30%).
Авто Стрельба: стреляет в нужный момент в точку упреждения, очередями (избегает перегрева), стреляет в обьекты в нужный момент (работает не всегда правильно).
Авто Наводка: Наводит прицел на точку упреждения, на строения или самолет (под маркер обьекта) очень хорошо гоняется за самолетом, если нашел точку упреждения (из проблем - часто переключается между обьектами).
При включении авто стрельбы и авто наводки - ведет себя как 9-10 летний школьник (очень агрессивен и часто переключается, пока не захватит цель) , но разбивается частенько.
Debug режим: отображает все что находит текущие значения вычисленных высоты, скорости, их пределов и др.

чего не хватает или "в планах"
GUI - очень сильно не хватает, хотя бы минимального, уже начинаю раздавать бота на тестирование и постоянно перезапускать EXE - не вариант, а были-бы кнопочки:
"В бой", "Доиграй за меня", "Задать самолет", "Выбор тактики самолета" + небольшая информация (парочка Label`ов) и все.
Тактики: ну изначально конечно понятно что разные типы самолетов для разных целей предназначены, но нужна тактика не в общем смысле, а алгоритм т.е. нужна блок-схема действий в зависимости от:
1)Типа самолета
2)Количества Противников\Союзников
3)Активной Цели
4)Поставленной задачи или приоритетам (Самолеты\Наземные цели)

Все настолько надоело что сел и за ночь сделал вот такой GUI:
IzPqrRj.png
 

winstan

Эксплотатор)
Сообщения
406
Репутация
79
Не понимаю зачем использовать офсеты если можно было написать мод, а моды для движка биг ворлд пишуться на AS3 и Питоне, знающему С++ и делфи это не составит проблем
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Возможно вы и правы и я просто плохо искал инструмент, но процесс запущен и как видите запущен он "в лоб", сейчас конечно погуглю, посмотрю что найду, а там посмотрим, пока продолжаю изменять скрипт постом выше.
 

nowost

Знающий
Сообщения
178
Репутация
17
навигацию боту, я думаю, можно на основе миникарты сделать. по ищи тему про бота для танков, там все расписано.
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Вот наконец я все разобрал и застопорился на проблеме за вчерашний день не смог найти достойного решения.
Задача - хочу для тестирования отображать некоторые вещи прямо в игре т.е. как в старой CS1.6 Выводились ХитБоксы и подобное, в моем случае выводить высоту и скорость которую я нахожу + еще некоторый текст, сейчас очень убогое решение, найденное на забугорном форме + переписано мною.

Посмотрите кто разбирается поправьте, хочу сделать более работоспособным как минимум не рисовать заново линию, а менять уже нарисованную + может есть лучший способ через GDI+
вот что у меня получилось _DrawTextEx - не работает, а значения в пикселях от начала шкалы:
2ksBq5r.png

Код:
Global $hDC, $hPen,$hGUIWnd, $g_hFont

$GUI = GuiCreate("GUI",@DesktopWidth,@DesktopHeight,0, 0,$WS_POPUP, bitor($WS_EX_LAYERED,$WS_EX_TRANSPARENT,$WS_EX_TOPMOST,$WS_EX_TOOLWINDOW))
GuiSetBkColor(0x0,$GUI)
_WinAPI_SetLayeredWindowAttributes($GUI,0x0,255,0x01)
WinSetOnTop($GUI, "", 1)
GuiSetState(@SW_SHOW,$GUI)

...тут используем как хотим..............

 _Delete_Objects()
GUIDelete($GUI)
exit

Func _DrawLineEx($hGUI, $LeftValue, $TopValue, $RightValue, $BottomValue, $RectWidth, $RectColour)
    Local $obj_orig
    $hGUIWnd = $hGUI
		$hDC = _WinAPI_GetWindowDC($hGUIWnd)
    $hPen = _WinAPI_CreatePen($PS_SOLID, $RectWidth, $RectColour)
    $obj_orig = _WinAPI_SelectObject($hDC, $hPen)
    _WinAPI_DrawLine($hDC,$LeftValue, $TopValue,$RightValue, $BottomValue)
    Return $hDC
EndFunc   ;==>DrawLineEx

Func _DrawTextEx($hGUI, $Text ,$LeftValue, $TopValue, $RightValue, $BottomValue, $Colour)
    Local $obj_orig
    $hGUIWnd = $hGUI
	$hDC = _WinAPI_GetWindowDC($hGUIWnd)
	$g_tRECT = DllStructCreate($tagRect)
	DllStructSetData($g_tRECT, "Left", $LeftValue)
	DllStructSetData($g_tRECT, "Top", $TopValue)
	DllStructSetData($g_tRECT, "Right", $RightValue)
	DllStructSetData($g_tRECT, "Bottom", $BottomValue)
	$g_hFont = _WinAPI_CreateFont(50, 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _
	$OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Arial')
	$g_hOldFont = _WinAPI_SelectObject($hDC, $g_hFont)
	_WinAPI_SetTextColor($hDC, $Colour)
    $obj_orig = _WinAPI_SelectObject($hDC, $hPen)
    _WinAPI_DrawText($hDC,$Text,$g_tRECT,$DT_CENTER)
    Return $hDC
EndFunc   ;==>DrawLineEx

Func _GUIClearEx($Color)
		$hDC = _WinAPI_GetWindowDC($hGUIWnd)
		$g_tRECT = DllStructCreate($tagRect)
		DllStructSetData($g_tRECT, "Left", 0)
		DllStructSetData($g_tRECT, "Top", 0)
		DllStructSetData($g_tRECT, "Right", @DesktopWidth)
		DllStructSetData($g_tRECT, "Bottom",@DesktopHeight)
		$hPen = _WinAPI_CreateSolidBrush($Color)
		_WinAPI_FillRect($hDC,$g_tRECT,$hPen)
		Return $hDC
EndFunc   ;==>DrawLineEx

Func _Delete_Objects()
	_WinAPI_DeleteObject($hPen)
	_WinAPI_DeleteObject($g_hFont)
	_WinAPI_ReleaseDC($hGUIWnd, $hDC)
EndFunc


Я пока буду продолжать писать, но отладку проводить без этого - очень тяжело...
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
ivanius
https://code.google.com/p/g-engin/downloads/list

В свое время он достаточно сильно подтолкнул меня, уж очень грамотно разработчик все в нем реализовал. Из старых бэкапов приметил парочку дополнительных функций под твою задачу. ( их нет в оригинальной версии )
Код:
Func _GEng_ScrUpdateLayered()
	Local $gdibitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($__GEng_hBitmap)
	Local $hdestsv = _WinAPI_SelectObject($__GEng_hCompatibleDC, $gdibitmap)
	_WinAPI_DeleteObject($gdibitmap)

	DllCall('user32.dll', 'int', 'UpdateLayeredWindow', 'hwnd', $__GEng_hGui, 'hwnd', $__GEng_hDC, 'ptr', 0, 'ptr', $__GEng_pSize, 'hwnd', $__GEng_hCompatibleDC, 'ptr', $__GEng_pPoint, 'dword', 0, 'ptr', $__GEng_pBlend, 'dword', 0x02)
	DllCall('gdi32.dll', 'ptr', 'SelectObject', 'hwnd', $__GEng_hCompatibleDC, 'ptr', $hdestsv)
EndFunc

Func _GEng_ScrUpdateLayered2()
	_GDIPlus_GraphicsDrawImageRect($__GEng_hGraphic,$__GEng_hBuffer,$__GEng_WinX,$__GEng_WinY,$__GEng_WinW,$__GEng_WinH)
EndFunc


Создаешь Layred окно размером с клиентскую область окна @ рисуешь.
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Спасибо сейчас буду смотреть.
Вот как я делаю это в данный момент:
Код:
Get_Globals()
	$GUI = GuiCreate("GUI",@DesktopWidth,@DesktopHeight,0, 0,$WS_POPUP, bitor($WS_EX_LAYERED,$WS_EX_TRANSPARENT,$WS_EX_TOPMOST,$WS_EX_TOOLWINDOW))
	GuiSetBkColor(0xFFFFFF,$GUI)
	_WinAPI_SetLayeredWindowAttributes($GUI,0xFFFFFF);,255,0x01)
	WinSetOnTop($GUI, "", 1)
	GuiSetState(@SW_SHOW,$GUI)
	$hDC = _WinAPI_GetWindowDC($hGUIWnd)
	WinActivate($hWnd)
	
	Local $hTimer = TimerInit()
	While TimerDiff($hTimer) < 10000
		_GUIClearEx(0x0)
		Get_Current_S_H()
		Sleep(250)
		_Delete_Objects()
		If _IsPressed("58") Then
			GUIDelete($GUI)
			_Delete_Objects()
			Exit
		EndIf
	WEnd
	GUIDelete($GUI)
	_Delete_Objects()
	Exit

С гуи и WIN_API не сталкивался, обычно писал оконные приложения, просто бордеры скрывал все остальное на картинки + XML меню
UPD:
Пока делаю все руками и вспоминаю азы которые когда-то учил, сделал BackBuffer - убрал моргание
UPD2:
C GUI покончено оставляю "как есть" в принципе меня все устраивает, Новые 2 проблемы посерьезнее: не могу сделать AIM или даже просто летать:
1)Слишком резко даже при 100 мс передвигает курсор (прицел в нашем случае) и дерганно получается
2)Не могу понять как вычислить куда двигать, если нашли обьект и видим куда лететь куда двигать курсор
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Нашел очень крутую либу по поиску пикселей на екране работает минимум в 2 раза больше, а если нужно что-то найти на не очень часто меняющемся изображении то еще в 6-10 раз быстрее оказывается....
Но встала проблема программа почему-то не работает как только я указываю область начала старта отличное от 0, 0.
Или скорее всего проблема в функции, которая берет скриншоты области....
Может кто работал с нею???
Сама либа + пример + бенчмарк для сравнения (стандартного и этого) в архиве
П.С.
Мой бот уже все умеет, но реакции не хватает, не хватает скорости, аа выглядит уже вот так:
wZf8UwG.jpg


UPD = Разобрался, но быстрее только в 2 максимум 3 раза
 

Вложения

  • FastFind 2_2.zip
    186.8 КБ · Просмотры: 17

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Посмотри как ты её используешь. Там скорость возрастает в десятки тысяч раз за счет того, что ты захватываешь экран (или область), производишь все операции с цветами и потом принимаешь решение. Тоесть в отличии пиксельсерча или пиксельгеткалора, там где захват экрана происходит при каждом вызове команды, тут он захватывается только в начале.
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Хмммм..., спасибо что заглянули в мою тему :smile:
Вот инфа компьютера:
------------------
System Information
------------------
Time of this report: 12/15/2014, 12:27:04
Operating System: Windows 8.1 Профессиональная 64-bit (6.3, Build 9600) (9600.winblue_gdr.140330-1035)
Language: Russian (Regional Setting: Russian)
System Manufacturer: Gigabyte Technology Co., Ltd.
System Model: G41MT-ES2L
BIOS: Award Modular BIOS v6.00PG
Processor: Pentium(R) Dual-Core CPU E6600 @ 3.06GHz (2 CPUs), ~3.1GHz
Memory: 4096MB RAM
Available OS Memory: 4094MB RAM
Page File: 4786MB used, 15308MB available
DirectX Version: DirectX 11
DX Setup Parameters: Not found
User DPI Setting: Using System DPI
System DPI Setting: 96 DPI (100 percent)
DWM DPI Scaling: Disabled
D:rofl:iag Version: 6.03.9600.16384 64bit Unicode
----------
DirectX Debug Levels
--------------------
Direct3D: 0/4 (retail)
DirectDraw: 0/4 (retail)
DirectInput: 0/5 (retail)
DirectMusic: 0/5 (retail)
DirectPlay: 0/9 (retail)
DirectSound: 0/5 (retail)
DirectShow: 0/6 (retail)

---------------
Display Devices
---------------
Card name: NVIDIA GeForce GT 240
Manufacturer: NVIDIA
Chip type: GeForce GT 240
DAC type: Integrated RAMDAC
Device Type: Full Device
Device Key: Enum\PCI\VEN_10DE&DEV_0CA3&SUBSYS_83281043&REV_A2
Display Memory: 2506 MB
Dedicated Memory: 459 MB
Shared Memory: 2047 MB
Current Mode: 1920 x 1080 (32 bit) (60Hz)
Monitor Name: LG IPS234(Digital)
Card name: NVIDIA GeForce GT 240
Manufacturer: NVIDIA
Chip type: GeForce GT 240
DAC type: Integrated RAMDAC
Device Type: Full Device
Device Key: Enum\PCI\VEN_10DE&DEV_0CA3&SUBSYS_83281043&REV_A2
Display Memory: 2506 MB
Dedicated Memory: 459 MB
Shared Memory: 2047 MB
Current Mode: 1680 x 1050 (32 bit) (60Hz)
Monitor Name: LG L204W(Digital)
Monitor Model: L204W
Monitor Id: GSM4E7D
Native Mode: 1680 x 1050(p) (59.883Hz)
Output Type: DVI
D3D9 Overlay: Supported
DXVA-HD: Supported
DDraw Status: Enabled
D3D Status: Enabled
AGP Status: Enabled
Далее вот код который использую в основной (Не ругайте,если слишком много инкапсуляции)
Код:
Get_Globals()
_Battle_Fight()
Func Get_Globals()

	Get_Window_Cords()

	Global $BTGoFight[4] = [($aMidleX - 65), ($aEndY - 235), ($aMidleX + 65), ($aEndY - 195)];В Бой
	Global $BTStartFight[4] = [($aMidleX - 75), ($aEndY - 105), ($aMidleX + 75), ($aEndY - 80)];Начать битву
	Global $BTStopFind[4] = [($aMidleX + 275), ($aMidleY - 265), ($aMidleX + 405), ($aMidleY - 245)];Остановить поиск
	Global $BTCloseStatistic[4] = [($aMidleX + 580), ($aMidleY - 362), ($aMidleX + 605), ($aMidleY - 340)];закрыть статистику
	Global $BTLogin[4] = [($aMidleX - 80), ($aMidleY + 235), ($aMidleX + 90), ($aMidleY + 270)]
EndFunc   ;==>Get_Globals
Func Get_Window_Cords()
	$aWinPos = WinGetPos("World of Warplanes");  1.6.1
	$aWinSize = WinGetClientSize("World of Warplanes")
	$hWnd = WinGetHandle("World of Warplanes")

	If @error Then
		MsgBox(48, 'Error!', 'World of Warplanes не запущен!')
		_Delete_Gui_Objects()
	Else

		$Border = ($aWinPos[2] - $aWinSize[0]) / 2
		$Header = ($aWinPos[3] - $aWinSize[1] - $Border)

		$aWinPos[0] += $Border
		$aWinPos[1] += $Header

		$aMidleX = $aWinPos[0] + ($aWinSize[0] / 2);+($Border/2)-$Border
		$aMidleY = $aWinPos[1] + ($aWinSize[1] / 2);+($Header/2)
		$rMidleX = ($aWinSize[0] / 2);+($Border/2)-$Border
		$rMidleY = ($aWinSize[1] / 2);+($Header/2)

		$aEndX = $aWinPos[0] + $aWinSize[0]
		$aEndY = $aWinPos[1] + $aWinSize[1]
		$rEndX = $aWinSize[0]
		$rEndY = $aWinSize[1]

		$aMinY = $aMidleY - 92
		$aMaxY = $aMidleY + 92
		$rMinY = $rMidleY - 92
		$rMaxY = $rMidleY + 92

	EndIf
EndFunc   ;==>Get_Window_Cords
Func Battle_Fight()
	;Fight!
	Local $WaitTimer = TimerInit()
	Local $AimFired = -1, $Forsage = -1, $AimPlane = -1
	Local $BackBufferFree = False, $Current_hDC
	Local $EnemyStructure
	Local $OldMyPlane = -1, $MyPlane = -1
	Local $PriorityTimer = TimerInit()

	Get_Globals()
	FFSnapShot(0, 0, $rEndX, $rEndY, $FFDefaultSnapShot, $hWnd)

	ReDrawStatic()

	$NextBattle = False

	While Not $NextBattle
		$timer = TimerInit()

		Get_Globals()
		FFSnapShot(0, 0, $rEndX, $rEndY, $FFDefaultSnapShot, $hWnd)

		If $BackBufferFree = False Then
			$Current_hDC = $hDC
		Else
			$Current_hDC = $hDC_BackBuffer
		EndIf

		Get_Current_S_H($Current_hDC, $Draw)

		;test rect aim
		If $AutoFire Then
			;Есть по кому стрелять
			$AimPlane = FFNearestSpot(10, 25, 1, 1, 0x000000FF, 2, False, 235, 200, $rEndX - 235, $rEndY - 200, False, $hWnd)
			;_PixelSearch(235, 200, $rEndX - 235, $rEndY - 235, 0x0000FF, 5, 10, $hWnd, 1, 10)
			If Not @error Then
				_DrawLineEx($Current_hDC, $aWinPos[0] + $AimPlane[0] - 1, $aWinPos[1] + $AimPlane[1] - 1, $aWinPos[0] + $AimPlane[0], $aWinPos[1] + $AimPlane[1], 5, 0x00FF00)
				If $AutoAim = True Then _MouseMove_FPS($AimPlane[0], $AimPlane[1]);автонаводчик
				Local $Colors = [0x5D1CA0, 0xF2AB45]
				$AimPlane = _PixelSearch($AimPlane[0] - 25, $AimPlane[1] - 25, $AimPlane[0] + 25, $AimPlane[1] + 25, $Colors, 5, 1, $hWnd, 1, 4, $AimPlane[0], $AimPlane[1])
				If Not @error Then
					$AimFired = TimerInit()
					MouseDown("primary")
				EndIf
			EndIf
			If ($AimFired <> -1) And TimerDiff($AimFired) > Random(300, 550) Then
				MouseUp("primary")
				$AimFired = -1
			EndIf
		EndIf

		;првоерка раз в 1,5 сек
		If Mod(Round(TimerDiff($PriorityTimer) / 250), 6) = 0 Then
			;my Plane on map
			Local $Colors = [0xECECEC, 0xCBCBCB]
			If IsArray($OldMyPlane) Then
				$MyPlane = _PixelSearch($OldMyPlane[0] - 5, $OldMyPlane[1] - 5, $OldMyPlane[0] + 5, $OldMyPlane[1] + 5, $Colors, 4, 1, $hWnd, 1, 3)
			Else
				$MyPlane = _PixelSearch($rEndX - 10, $rEndY - 10, $rEndX - 210, $rEndY - 210, $Colors, 5, 1, $hWnd, 1, 1)
			EndIf
			If Not @error Then
				$OldMyPlane = $MyPlane

			EndIf
			If Not @error Then
				$EnemyStructure = _PixelSearch($MyPlane[0] - 5, $MyPlane[1] - 5, $MyPlane[0] + 5, $MyPlane[1] + 5, 0x66, 10, 1, $hWnd, 1, 2)
				If Not @error Then _DrawLineEx($Current_hDC, $EnemyStructure[0], $EnemyStructure[1], $EnemyStructure[0], $EnemyStructure[1], 5, 0x0000FF)
			EndIf
		EndIf
		;проверка - раз в 4 сек (250*16)
		If Mod(Round(TimerDiff($PriorityTimer) / 250), 16) = 0 Then
			;мы мертвы
			If _PixelSearch($rMidleX + 30, $rMidleY + 100, $rMidleX + 31, $rEndY - 30, 0x00FFFF00, 2, 10, $hWnd, 25, 50) Then
				;MouseMove($Dead[0], $Dead[1])
				_GUIClearEx($Gui, 0x0)
				_GUIClearEx($Back, 0x0)
				_GUIClearEx($BackBuffer, 0x0)
				_DrawTextEx($hDC_Back, "Нас убили :( - ждем", 40, $aMidleX + 250, $aMaxY, $aMidleX - 250, $aMinY, 0x0000FF)
				While Not _Find_Button($BTCloseStatistic, 4276545475, 805122704, 0x00161F21)
					Get_Globals()
				WEnd;Закончился бой - есть крестик
				_MouseClick("primary", $BTCloseStatistic[0] + Random(1, 20), $BTCloseStatistic[1] + Random(1, 20))
				$NextBattle = True
			EndIf

			;закончился бой - черный екран
			If FFGetPixel($rEndY - 50, $rMidleX) = 0 Then
				_GUIClearEx($Gui, 0x0)
				_GUIClearEx($Back, 0x0)
				_GUIClearEx($BackBuffer, 0x0)
				While Not _Find_Button($BTCloseStatistic, 4276545475, 805122704, 0x00161F21)
					Get_Globals()
				WEnd;Закончился бой - есть крестик
				_MouseClick("primary", $BTCloseStatistic[0] + Random(1, 20), $BTCloseStatistic[1] + Random(1, 20))
				$NextBattle = True
			EndIf

		EndIf

		If $Draw >= $Draw_Lines Then
			if IsArray($MyPlane) Then
				_DrawLineEx($Current_hDC, $aWinPos[0] + $MyPlane[0] + 1, $aWinPos[1] + $MyPlane[1] + 1, $aWinPos[0] + $MyPlane[0] + 1, $aWinPos[1] + $MyPlane[1] + 1, 3, 0xFF0000)
				_DrawTextEx($Current_hDC, "X" & ($rEndX - $MyPlane[0]) & " " & TimerDiff($timer) & " Y" & ($rEndY - $MyPlane[1]), 20, $aMidleX + 228, $aMaxY + 20, $aMidleX - 228, $aMinY + 20, 0x00FFFF)
			EndIf
			If IsArray($AimPlane) And $AutoFire Then
				_DrawLineEx($Current_hDC, $AimPlane[0] - 25, $aWinPos[1] + $AimPlane[1] - 25, $AimPlane[0] + 25, $aWinPos[1] + $AimPlane[1] + 25, 1, 0x00FF00)
				_DrawLineEx($Current_hDC, $AimPlane[0] + 25, $aWinPos[1] + $AimPlane[1] - 25, $AimPlane[0] - 25, $aWinPos[1] + $AimPlane[1] + 25, 1, 0x00FF00)
			EndIf
		EndIf
		
			If $BackBufferFree = False Then
				_GUIClearEx($BackBuffer, 0x0)
				$BackBufferFree = True
			Else
				_GUIClearEx($Gui, 0x0)
				$BackBufferFree = False
			EndIf
	WEnd

	_GUIClearEx($Gui, 0x0)
	_GUIClearEx($Back, 0x0)
	_GUIClearEx($BackBuffer, 0x0)
EndFunc   ;==>Battle_Fight
Func _PixelSearch($Left, $Top, $Right, $Bottom, $Colors, $ShadeVariation = 0, $Step = 1, $hWnd = -1, $PixelsCount = 1, $AreaSize = 1, $PosX = -1, $PosY = -1)
	;calculate Real Pos and Size
	Local $Temp
	If $Left > $Right Then
		$Temp = $Right
		$Right = $Left
		$Left = $Temp
		$PosX = $Left
	EndIf
	If $Top > $Bottom Then
		$Temp = $Bottom
		$Bottom = $Top
		$Top = $Temp
		$PosY = $Bottom
	EndIf

	;check for Position
	If $PosX = -1 Then $PosX = $Right ;Int(($Right - $Left) / 2)
	If $PosY = -1 Then $PosY = $Top ;Int(($Bottom - $Top) / 2)
	If $PosX < 0 Then $PosX = 0
	If $PosY < 0 Then $PosY = 0
	;check for Colors
	If IsArray($Colors) Then
		FFResetColors()
		For $i = 0 To UBound($Colors) - 1
			FFAddColor($Colors[$i])
		Next
		$Colors = -1
	EndIf

	If $Left = 0 Then $Left = 1
	If $Top = 0 Then $Top = 1

	;FFNearestSpot($SizeSearch, $NbPixel, $PosX, $PosY, $Color, $ShadeVariation=0, $ForceNewSnap=true, $Left=0, $Top=0, $Right=0, $Bottom=0, $NoSnapShot=$FFLastSnap, $WindowHandle=-1)
	If $hWnd = -1 Then
		;FFAddExcludedArea()
		Local $result = FFNearestSpot($PixelsCount, $AreaSize, $PosX, $PosY, $Colors, $ShadeVariation, False, 0, 0, $Left + $Right, $Top + $Bottom, False, 0)
		;Local $result = DllCall($FFDllHandle, "int", "GenericColorSearch", "int", $PixelsCount, "int*", $AreaSize, "int*", $PosX, "int*",$PosY, "int", $Colors, "int", $ShadeVariation, "int", $FFLastSnap)
	Else
		;FFAddExcludedArea($Left, $Top, $Right, $Bottom)
		Local $result = FFNearestSpot($PixelsCount, $AreaSize, $PosX, $PosY, $Colors, $ShadeVariation, False, $Left, $Top, $Right, $Bottom, False, $hWnd)
		;Local $result = DllCall($FFDllHandle, "int", "GenericColorSearch", "int", $PixelsCount, "int*", $AreaSize, "int*", $PosX, "int*",$PosY, "int", $Colors, "int", $ShadeVariation, "int", $FFLastSnap)
		;FFResetExcludedAreas()
	EndIf
	;	ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $result = ' & $result & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
	;check for errors
	If Not IsArray($result) Then
		SetError(1)
		Return False
	Else
		Return $result
	EndIf

EndFunc   ;==>_PixelSearch
Думаю все 2500 строк выкладывать не нужно интересует именно эта чать работает 250 мс, память продолжаю копать (искать скорость и высоту точнее стат указатель на значение, короче адресс в памяти, но все также безуспешно)
Я сейчас читаю мануал по этой библиотеке, хочу еще искать не на всем скриншоте а только в тех областях что интересует т.к. если в области не находит - ищет дальше...

UPD1:Ох эти французы с их французским это ппц, назвал переменную NoSnapShot и ставит False конечно я подумал что это делать или не делать новый, а не номер его )) хорошо что до справки по библиотеке добрался.... Проблема не решена, но одна ошибка найдена)
UPD2:После перехода на эту библиотеку уменьшил скорость этой основной процедуры с 500-750 до 150-250, главная проблема это то что он ищет на всем скриншоте и не обрезает если я указываю размеры, а размеры это только для нового скриншота, я подумал ну проверю - основная процедура меньше 20мс, в среднем 8-10мс.... Но думаю можно как-то и одним скриншотом обойтись и просто искать только в определенной его части или обрезать его...
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
В код вникать особо времени нету, под конец года работой завален по самые ушли :smile:. Я делал как:
1) захватывается только та область в которой может быть интересующая инфа.
2) Поиск ведется исключительно в пределах этой области
3) На всю область применяется фильтр, который сохраняет только нужные цвета отбрасывая все остальное и заменяя это черным цветом
4) Я пользовался только функциями определения цвета пикселя. NearestSpot и тд я не использовал. При использовании фильтров можно свести успех поиска к критерию "Если не черный - значит нашли".
5) Конечно же нужно максимально уменьшить области поиска, чтобы туда не попадали лишние элементы
6) Увеличить шаг поиска. Если на плоскости ищется элемент, минимальная ширина которого составляет например 2 пикселя, то уже можно не сканировать каждый пиксель подряд, а сканировать каждый второй пиксель, при таком раскладе скорость поиска возрастает в 2 раза.
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Ну сейчас я делаю скриншоты постоянно, НО ооочень маленьких областей шириной к примеру в 2-4 или меньше пикселя - скорость меня уже радует, За идею с фильтрами очень интересно - сейчас попробую но нужно поскринить экран программой с фильтрами и сохранить в BMP, а не осталось ли примеров - я буду вникать в код т.к. для меня это очень важно сейчас пошел поиск и наводка на обьекты, а там области - большие - нужно будет оптимизировать 100%

Сейчас играюсь с фильтрами в дргонку 2 вопроса как найти черны и белый цвета т.е. черный 0, а белый максимум?

пока идея такая - цвета мои уже найдены и попробую так поискать:
Код:
$Temp = _ColorGetRGB($Colors)
			FFApplyFilterOnSnapShot($Temp[0], $Temp[1], $Temp[2])
			FFSaveBMP(@ScriptDir & "\BMP\F"&$Iterator)
;А дальше поиск черного цвета
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Вроде там было что-то типа команды FFKeepColor($array), где $array - список цветов которые нужно оставить - все остальное отсеивается.
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Вы представляете я это сделал!!!
Все я закончил с определением всех цветов, обьектов и т.д. сделал несколько уровней отрисовки для дебага короый можно в процессе менять, если честно вспоминаю сейчас Читы для CS1.6 где тоже отрисовывались все эти мелочи типа AIM BOX и подобное, теперь осталось отладить нормальное поведение его плавные небольшие движения мыши и тактику...
Пока я только понял что скорость буду держать всегда в нормальном уровне т.к. если большая или быстро возрастает - падаем, наоборот уменьшается или маленькая - сильно берем вверх и поэтому скоро упадем ну и т.д. сейчас все это настраиваю...

Вопрос по поводу мышки вот функция которая вычисляет правильно, НО только, если мышка на старте была по центру и далее я ее не трогал....
Проблема скорее всего в том что указатель скрывается и уже его координаты внутри - другие не такие как на экране (по моему, как-то так)
Код:
Func _MouseMove_FPS($X, $Y)
	Get_Globals()
	$aPos = MouseGetPos()
	$toX = $X - $aMidleX
	$toY = $Y - $aMidleY
	$aX = ( 100 / ($aWinSize[0]) ) * $toX
	$aY = ( 100 / ($aWinSize[1]) ) * $toY
	$dX=( 192 / 360 ) * $aX
	$dY=( 108 / 360 ) * $aY
	$X = $aPos[0] + ($dX / 10)
	$Y = $aPos[1] + ($dY / 10)
	MouseMove($X, $Y, 100)
EndFunc   ;==>_MouseMove_FPS

UPD
Суть проблемы что играл ловит перемещение мышкой другим образом и часто мышка просто напросто находится у краев рабочей области и соответсвенно сдвиг за ее пределы дает странный результат.
Сейчас хочу попробовать следующую идею :
1)Делать окно неактивным или зажимать ctrl(делает видимым указатель)
2)Перемещать быстро в центр рабочей области игры
3)перемещать уже в игре
Как-то отлавливать движение мышкой пользователем, а не программой и выполнять эти действия только в этом случае.
В общем пока откладываю этот вопрос, пробы того что описал выше - не дали результата смена, движение, возврат активного окна -лучше всего, НО все-равно медленно.
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
С добавление Меню встало сразу несколько проблем - у меня все завязано на циклах типа:
Код:
While not @Error 
...
Wend

Хочу проверить по отдельности каждую функцию (вход в игру, поиск игры, сам бой)
НО как только я нажимаю гарячую клавишу завершения цикла - программа не возвращается в меню - его показывает, но кнопки - не работают, т.е. не возвращается назад управление в гуи и я не понимаю как это сделать т.е. выход из функции нужно сделать не в самой функции, а в другой на которой гарячая клавиша.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Ибо ты наткнулся на камень преткновения. Используя циклы, ты не можешь работать с гуем, пока программа находится в цикле. Тут тебе нужно пользоваться GUICtrlSetOnEvent(). И циклы строить так, чтобы ими можно было управлять из вне, с помощью этой функции.
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Обьясню поподробнее:
Я постоянно проверяю бота в разных игровых ситуациях, для этого мне нужно его постоянно перезапускать и собственно для этого GUI я и сделал - чтобы нажал кнопку запусть - запустил, остановить - оставновил.. и перезапустил
Вот как я делаю:
Код:
HotKeySet("{PAUSE}", "_Delete_Gui_Objects")
$WOWPForm = GUICreate("Бот World Of WarPlanes", 858, 508, -1, -1)
GUISetFont(12, 400, 0, "MS Sans Serif")
GUISetOnEvent($GUI_EVENT_CLOSE, "WOWPFormClose")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "WOWPFormMinimize")
GUISetOnEvent($GUI_EVENT_RESTORE, "WOWPFormRestore")
$Starters = GUICtrlCreateGroup("Меню разработчика", 392, 8, 457, 201)
$ToBattle = GUICtrlCreateButton("В Бой!", 432, 72, 107, 33)
GUICtrlSetOnEvent(-1, "ToBattleClick")
$FindBattle = GUICtrlCreateButton("Поиск боя", 432, 112, 107, 33)
GUICtrlSetOnEvent(-1, "FindBattleClick")
.......
.......
......
Func ToBattleClick()
	GUISetState(@SW_MINIMIZE, $WOWPForm)
	If Get_Globals() Then
		_Create_Gui_Objects()
		MouseMove($aMidleX, $aMidleY, 1)
		WinActivate($hWnd)
		FFSetWnd($hWnd)
		Start_Battle($Planes[0][0], $Planes[0][1]);Bot_()
		_Delete_Gui_Objects()
	EndIf
EndFunc   ;==>ToBattleClick
Func WOWPFormClose()
	_Delete_Gui_Objects()
	Exit
EndFunc   ;==>WOWPFormClose
Func WOWPFormMinimize()
	GUISetState(@SW_MINIMIZE, $WOWPForm)
EndFunc   ;==>WOWPFormMinimize
Func WOWPFormRestore()
	GUISetState(@SW_RESTORE, $WOWPForm)
EndFunc   ;==>WOWPFormRestore

Func Battle_Fight()
	_Create_Gui_Objects()
	Get_Critical_S_H()
	ReDrawStatic()
        While $GuiCreated = True and $NextBattle = false
много кода, првоерок и всего остального на тысячу строк почти,  выполняется в среднем около 70 мс
        WEnd
EndFunc   ;==>Battle_Fight

Могу выложить весь код, Суть проблемы я нажимаю кнопку - бот запускается и работает, потом я его останавливаю нажатием "Pause", все очищается ($GuiCreated = False) вроде бот останавливается(выйти из цикла), срабатывает @SW_RESTORE, НО в меню ничего не работает :(
Не привык еще по ночам работать и не спать + работать без дебагера - очень сложно, вроде бы нашел ошибку и исправил, может быть это т.н. костыль... пока рабоатет
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
youtube.com/watch?v=AY6AhoZ-HC8
Как вставить видео с ютуба?)
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Ибо ты наткнулся на камень преткновения. Используя циклы, ты не можешь работать с гуем, пока программа находится в цикле. Тут тебе нужно пользоваться GUICtrlSetOnEvent(). И циклы строить так, чтобы ими можно было управлять из вне, с помощью этой функции.
И встраивать сотни проверок в закрытые циклы? Есть решение куда проще:

Код:
While 1 ;Main Loop
	$aMsg = GUIGetMsg(1)
	Switch $aMsg[1]
		....
	EndSwitch
	If $CurrentFunction Then _
		Call( $CurrentFunction )
WEnd

Func CurrentFunction()
	Switch $CurrentFuncState
		Case 0
			MsgBox( 64, '', '0' )
			If Random( 0, 1, 1 ) Then _
				Return
			
		Case 1
			MsgBox( 64, '', '1' )
			
		Case n
			
		Case Else
			$CurrentFuncState = -1
	EndSwitch
	$CurrentFuncState += 1
EndFunc


Банальный пример конструкции цикла с возможностью его удобного прерывания. Она конечно имеет свои недостатки (GUIGetMsg), однако они легко обходится.
 
Автор
I

ivanius

Знающий
Сообщения
74
Репутация
5
Или я не правильно понял пример или вы не правильно поняли вопрос.
Мне нужно принудительно Выйти из функции или ее завершить или передать управление другой или хотя бы выйти из цикла и это нужно сделать из другой функции, которая сидит на кнопке.
Т.е. я не хочу прописывать в каждой функции и в каждом цикле условия типа "_IsKeyDown() - exit loop"
но сейчас почти так и сделано, добавил в While (and _ExitLoop) еще одно условие и меняю его по общей кнопке.
 
Верх