Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Игровые боты. Предисловие

Anna | 24.06.2014 | нет комментариев

Что может быть увлекательнее процесса игры в игры? Верно! Процесс слежения за тем, как играет в игры написанный тобой бот.

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

Вступление

Боты для онлайн игр я бы дерзко поделил на 3 разновидности по методам реализации:
1. Боты не использующие приложение игры. Имитирующие протокол обмена с сервером.
2. Боты работающие с процессом приложения игры. В случае с Web, работающие с окном браузера.
3. Боты работающие со скриншотом и имитирующие устройства ввода мышь и клавиатуру.

Первая разновидность скорее гипотетическая, т.к. протоколы, как правило, закрыты и не банальны.

Вторая разновидность больше реальна и может быть реализована. Бот второго вида получает пригодную информацию из памяти процесса игры. Недочет — версии заказчиков могут регулярно обновляться и тогда может понадобиться снова искать волнующие адреса памяти.

Мы разглядим третюю разновидность ботов, т.к. ИМХО они больше симпатичны, хоть и не лишены недостатков.

В этой статье я разгляжу комплект инструментов для самого простого бота для Windows.

Для самого простого бота довольно эмитировать события мыши и клавиатуры. В большинстве случаев этого оказывается довольно для решения (не самого результативного, но не требующего участия человека) рутинных дел в разных играх. Для больше результативной работы бота требуется обратная связь с игрой, т.е. приобретение и обработка скриншотов игры.

Код

Для разработки приложений я буду применять Qt Creator Qt 5 либы (так мне привычнее) и раз бот для Виндовс то windows.h (WinAPI).

Инклуды:

#include <windows.h>   // WinAPI
#include <iostream>    // std::cout
#include <unistd.h>    // sleep(), usleep()
#include <math.h>

Хидер бота:

// Индексы точек
enum {
    menu=0,
    elm_1,
    points_cnt
};

class MyBot
{
public:
    MyBot();
    void run();
    void move_to(int inx);
    void lclick_to(int inx);
    void rclick_to(int inx);
    void drag(int from_inx,int to_inx);
    POINT point[points_cnt];
};

Конструктор:

MyBot::MyBot() :
    // Массив координат органов управления (по которым мы будем кликать мышкой)
    point({
      {100,100}, // 0 - menu
      {130,130}, // 1 - elm_1
    })
{
}

Регистрация жгучих кнопок для управления ботом:

    RegisterHotKey((HWND)Widget::winId(), 101, MOD_ALT, VK_F1);    // Запуск бота
    RegisterHotKey((HWND)Widget::winId(), 102, MOD_ALT, VK_F2);    // inx  
    RegisterHotKey((HWND)Widget::winId(), 103, MOD_ALT, VK_F3);    // Проверить точку inx
    RegisterHotKey((HWND)Widget::winId(), 104, MOD_ALT, VK_F4);    // Запомнить точку inx
    RegisterHotKey((HWND)Widget::winId(), 105, MOD_ALT, VK_F5);    // Вывести в консоль массив координат

Обработка событий нажатия кнопок управления ботом:

int inx=0;
MyBot bot;

bool Widget::nativeEvent(const QByteArray & eventType, void * message, long * result){
    Q_UNUSED(result);
    Q_UNUSED(eventType);
    MSG* msg = reinterpret_cast<MSG*>(message);
    if(msg->message!=WM_HOTKEY)return false;

    switch(msg->wParam){
    case 101: // Alt-F1 - запуск бота
        bot.run();
        return true;
    case 102: // Alt-F2 - inx  
        if(inx<points_cnt-1)inx  ;
        return true;
    case 103: // Alt-F3 - Проверить точку inx
        bot.move_to(inx);
        return true;
    case 104: // Alt-F4 - Запомнить точку inx
        GetCursorPos(&point[inx]);
        return true;
    case 105: // Alt-F5 - Вывести в консоль массив координат
        for(i=0;i<points_cnt;i  ){
            std::cout << "{" << bot.point[i].x << "," << bot.point[i].y << "}, //" << i << std::endl;
        }
        return true;
    }
    return false;
}

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

#define width 1920
#define height 1080

void MyBot::move_to(int inx){
    int x=point[id].x;
    int y=point[id].y;
    POINT pt;
    GetCursorPos(&pt);

    int from_x=pt.x;
    int from_y=pt.y;

    int to_x=x;
    int to_y=y;

    int dx=to_x-from_x;
    int dy=to_y-from_y;

    float fdx;
    float fdy;
    int loop_cnt;

    if(abs(dx)>abs(dy) && dx!=0){
        fdx=dx<0? -1.0 :1.0;
        fdy=(float)dy/abs(dx);
        loop_cnt=abs(dx);
    }
    else if(dy!=0){
        fdy=dy<0? -1.0 :1.0;
        fdx=(float)dx/abs(dy);
        loop_cnt=abs(dy);
    }
    else return;

    // двинуть за 1 секунду
    int time=1000000/loop_cnt;
    float fx=from_x;
    float fy=from_y;
    for(int i=0;i<loop_cnt;i  ){
        fy =fdy;
        fx =fdx;
        int nx=(fx)*(65536 / width);
        int ny=(fy)*(65536 / height);
        mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,nx,ny,0,0);
        usleep(time);
    }
    usleep(50000);
}

Клики:

void MyBot::lclick_to(int inx){
    move_to(inx);
    mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
    usleep(50000);
    mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
    usleep(100000);
}

void MyBot::rclick_to(int inx){
    move_to(inx);
    mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
    usleep(50000);
    mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);
    usleep(100000);
}

Перетаскивание:

void MyBot::drag(int from_inx, to_inx){
    move_to(from_inx);
    usleep(50000);
    mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
    usleep(70000);
    move_to(to_inx);
    mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
    usleep(30000);
}

Работа бота:

void MyBot::run(){
    rclick_to(menu);  // кликнем правой кнопкой для вызова контекстного меню
    lclick_to(elm_1); // кликнем левой кнопкой по строке меню
}
Мануал юзера

Перед запуском бота жгучей кнопкой Alt-F1, бот следует вначале настроить, определив правильные координаты органов управления по которым бот будет кликать.
Для запоминания координат точки наводим указатель месту и жмём Alt-F4.
Для проверки корректности точки отводим указатель в сторону и жмём Alt-F3.
Для настройки дальнейшей точки жмём Alt-F2.
Для сохранения правильных координат жмём Alt-F5.

Подводные камни

Навык показывает, что не стоит спешить кликать по органам управления и двигать указатель. Зачастую игры притормаживают, при наведении мыши на кнопку срабатывает отрисовка подсветки и прочие неведанные процессы и торопливость приводит к несрабатыванию клика либо захвата при перетягивании и т.п. и как следствие неработоспособность бота. При ручном управлении, люди традиционно таких неприятных мелочей даже не примечают, так как работает обратная связь через органы зрения. Решение — делать паузы позже всех элементарных действий.

Окно игры может произвольно свернуться в следствии возникновения сообщения от виндозы либо ещё по каким причинам. В программе последовательности кликов и пауз стоит предусмотреть клик по иконке свёрнутой игры.

Qt Creator: qt-project.org/downloads
Начальный код плана на гитхабе: github.com/rumaster/my_bot_v1

P.S. Не подумайте что я ярый противник онлайн игр, раз публикую исходники ботов. Я противник дискриминации ИИ (ботов) и за становление онного. А ещё, игры — мотор прогресса.

P.P.S. Говоря ИИ, я подразумеваю программу способную получать и обрабатывать (исследовать) информацию, планировать и исполнять действия в соответствии с целями и итогами обзора обстановки.

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB