Основы изготовления игровых ботов
В этой небольшой статейке я приведу пример изготовления бота “навесного” типа для DirectX игры на примере Pro Evolution Soccer 2011/2012. Естественно, наш бот будет не в футбол играть, а только запускать матчи МЛО в режиме тренера, пока мы спим. Цель - финансы.
Итак, мы имеем стандартную DirectX-игру, запущенную в окне. Что нам нужно? Распознать то, что отображено на экране и послать туда нажатие соответствующих клавиш. Для распознавания/опознания мы будем использовать библиотеку OpenCV (Open Source Computer Vision Library) - ru.wikipedia.org/wiki/OpenCV
Для начала нам нужно найти окно нашего DirectX-приложения и сдампить экран. Мы привяжем это к таймеру и будем делать каждые ХХ секунд. Самый простой вариант:
HWND hWnd = FindWindow(0,”Pro Evolution Soccer 2011″), SetForegroundWindow(hWnd), Form1->ImageEnViewPES->IO->CaptureFromScreen(iecsForegroundWindow, 0); - используем библиотеку OpenCV для более простого захвата содержимого активного окна.
Но если вы не хотите, чтобы фокус на это окно переводился каждые несколько секунд, и за компьютером можно было спокойно работать (особенно, если у вас два монитора), то лучше делать все сложнее - делать полный дамп всего видимого пространства, а в нем искать вхождение главной иконки приложения (той, сто слева от заголовка окна) с помощью функций cvMatchTemplate() и cvMinMaxLoc(), чтобы вычислять нужные координаты и вырезать область изображения без смены фокуса окна.
Теперь нужно определить в каком режиме/диалоге игры мы находимся. Как это сделать? Для начала нам нужно определить какие области экрана имеют объекты, к наличию/отсутствию которых мы можем привязаться. Например, если мы видим на экране такую кнопку (обведена красным на скриншоте), то это значит, что мы в кубковом режиме МЛО, где необходимо нажать клавишу “Enter” для запуска очередного матча.
Далее следует уже большая и нудная работа по “подготовке базы” - необходимо сделать скриншоты в разных игровых ситуациях, подобрать координаты границ объектов для сравнения с областью экрана, “процент схожести”, какой можно считать пороговым (многие менюшки не статичны, так что 100-процентного совпадения не будет) и описать эмуляцию каких клавиш нам нужно туда передавать.
Для сравнения двух изображений и получения процента схожести на выходе в OpenCV у компонента ImageEnView существует функция CompareWith(). Для удобства, я обернул это все в отдельную функцию, которая у меня выглядит примерно так (немного упростил и выкинул лишний код для более наглядного просмотра):
bool ImgEq (double percent, char* filename, int x1, int y1, int x2, int y2)
{
Form1->ImageEnView2->Assign (Form1->ImageEnViewPES);
Form1->ImageEnView2->Proc->Crop (x1-5,y1-5,x2-5,y2-5);
Form1->ImageEnView1->IO->LoadFromFile(filename);
Form1->ImageEnView1->Proc->Crop (x1,y1,x2,y2);
double dPer = Form1->ImageEnView1->Proc->CompareWith(Form1->ImageEnView2->IEBitmap, NULL);
return (dPer >= percent);
}
Вызов этой функции выглядит так:
if (ImgEq(0.98, “points-2012.bmp”,410,390,700,500)) { … }
if (ImgEq(0.97, “mlo-message-2012.bmp”,750,230,950,520)) { … }
if (ImgEq(0.98, “cup-menu.bmp”,350,700,520,870)) { … }
Ну все! Теперь наша программка умеет определять текущий режим, в котором находится игра. Осталось только научиться передавать туда нужные комбинации клавиш. Так как нам нужно делать эмуляцию в DirectX приложении, то PostMessage/kbdevent тут работать не будут, необходимо передавать сканкоды с помощью SendInput(). Для того, чтобы можно было красиво описывать последовательности нажатий вызовами типа Key(DIKEYBOARD_X), я сделал такую функцию:
void Key ( int key)
{
INPUT input;
memset(&input,0,sizeof(INPUT));
input.type=INPUT_KEYBOARD;
input.ki.wScan = key; // direct-input scancode
input.ki.dwFlags=0;
SendInput(1,&input,sizeof(INPUT));
Sleep(50);
input.ki.dwFlags=KEYEVENTF_KEYUP;
SendInput(1,&input,sizeof(INPUT));
}
А что дальше? А дальше уже чистое творчество. Мой бот для PES2011, например, умеет определять все ситуации и на них реагировать - обрывы связи, служебные сообщения и т.п., умеет определять счет в игре и в зависимости от него посылать комбинации клавиш для смены тактики игры. А так же протоколирует читеров (игроков, которые при неудачном исходе матча к концу игры “портят соединение” так, чтобы матч был аннулирован).
Если вы уже давно подумывали о том, чтобы написать бота для своей любимой игры, но не все не доходили руки - попробуйте, это довольно творческий процесс, который затягивает.
Февраль 1st 2012 in Обо всем
Комментариев: 6 к записи “Основы изготовления игровых ботов”
Как написать бота для игры DirectX. Библиотека opencv для распознавания образов
Экскурсии по Москве: вднх - фонтаны, красная площадь, ночная москва .
Случайные записи: поисковая оптимизация WordPress
Soul сказал 03 Фев 2012 at 03:23 #
А реально написать бота для WoT, чтобы танк сам прятался в углу карты и стоял там неподвижно?
Чисто бот на опыт и деньги)
сказал 03 Фев 2012 at 12:47 #
Без понятия - не играл в WoT. Но если надо будет для этого распознавать именно игровое пространство (динамическое) с кучей объектов - это может быть не самый адекватный вариант решения данной задачи.
Алекс сказал 16 Июл 2012 at 19:04 #
А как заставить SendInput отправлять клавиши в неактивное окно?
сказал 18 Июл 2012 at 00:47 #
Алекс, вроде бы, никак. Надо делать окно активным.
Сергей сказал 09 Ноя 2012 at 03:45 #
доброго времени суток, хотелось поинтересоваться, а Вы случайно не желаете сделать бота на заказ, к флеш игре на майле, если это вас заинтересовало то напишите мне на скайп serjserj79
сказал 11 Ноя 2012 at 05:54 #
Сергей, к сожалению, не могу помочь - не работаю на заказ, могу посоветовать найти исполнителя через сайты типа freelance.ru и weblancer.net.