Как я сделал бота для фарма в GTA RP
Всем привет. В этом посте я хотел бы рассказать вам о своем опыте создания ИИ-бота для фарма $$ в гта РП.
Мысль о создании какого-нибудь бота/ИИ для фарма денег у меня появилась больше полугода назад, но тогда я думал что это слишком сложно и даже не пытался взяться за это. Как оказалось, все это не так уж и страшно как я себе это представлял.
Основные трудности, с которыми я столкнулся:
Первый шаг под названием Что делать то или (Постановка цели)
Так как на тот момент у меня не было НИКАКИХ знаний о ботоводстве, Я решил прикинуть, какая работа была бы САМОЙ ПРОСТОЙ в исполнении? Мой выбор пал на рыбалку, и вот почему:
Всю суть рыбалки можно изложить в нескольких шагах
Выглядит довольно просто, поэтому я решился делать первого бота именно для рыбалки (В будущем планирую написать ботов и для более сложных работ).
И так, первым делом я решил начать с создания модели с использованием Computer Vision для того, чтобы определить, где на экране находится рыба.
Просмотрев серию гайдов от sentdex и пару видео на ютубе по поводу Object Detection, я приступил к действию.
После небольшого ресерча, я решил делать бота используя модель YOLO. Наслушавшись, что ФПС увеличивается при конвертации цветов изображения в СЕРЫЙ цвет.
(ну типо RGB это трехмерный массив и занимает ГОРАЗДО больше места и вычислительной мощности, чем просто Gray).
Написал небольшой скрипт для снятия снимков экрана каждую секунду и сохранения их в специальной папке на компьютере. Сделав около 150 скринов Я перешел к созданию training dataset.
Для разметки использовал классический labelImg, хотя позднее выяснилось что roboflow может быть даже удобнее.
Разметил порядка 150 серых картинок, начал тренировать модель YOLOv7, смотрю на графики, а там confidence просто нулевая. Загружаю свое видео для проверки, убираю ограничение по уверенности и вижу, что модель ОПРЕДЕЛЯЕТ рыбу, но уверена в этом всего лишь на несколько процентов.
Начал искать решение проблемы, как оказалось модели YOLO созданы для тренировки на цветных изображениях, я же тренировал модель на серых картинках, посему и получил такой скудный результат.
Окей, пришлось заново собирать кучу картинок, заново тренировать модель и так далее. Спустя несколько часов Я имею на руках модель с довольно высокой точностью определения (60%+). Ну, думаю, пора внедрять ее в бота и писать основной функционал (как бы не так))) )
ОКАЗЫВАЕТСЯ YOLOv7 почти что НЕРЕАЛЬНО внедрить в обычный питоновский код (по крайне мере я так и не понял как), в следствии чего не пришлось делать НОВУЮ модель (опять), но уже на восьмой версии ЙОЛО, там даже тренинг можно делать из кода, что довольно удобно.
Ладно, я сделал еще 100500 картинок рыбы, разобрался во всем опять с нуля и имел на руках уже реально рабочую модель которую я мог использовать в коде (Ура)
Считывание экрана
В качестве image-taker'a я использовал библиотеку mss, которая отличается довольно высокой производительность, в отличии от pyautogui. С использованием MSS я смог добиться производительности в размере 20-25 кадров в секунду, что является довольно большим показателем. (Это считай столько скриншотов делается в секунду и обрабатывается моделью)
А как находить рыбу на экране то? Не знаю, я спросил это у чат-гпт и спустя несколько часов я смог успешно транслировать игру и определять есть ли на экране рыба.
Переходим к третьему шагу, "изнурение" рыбы
Для того, чтобы тянуть рыбу в нужную сторону, нам нужно определить вектор ее направления (т.е в какую сторону плывет рыба). Для этого я использовал встроенную функцию .xyxy
для получения координаты Х (вертикальной оси). Так как наша модель видит игру в формате огромного количества переменных кадров (в принципе как и мы, лол) Я просто решил сравнивать координату Х текущего кадра с предыдущем кадром. Таким образом, если Х меньше => рыба движется влево => тянем вправо. Х стал больше => рыба движется вправо => тянем влево. Спустя еще несколько часов я смог внедрить этот функционал.
Завершающий этап
Осталось понять, "когда же вытягивать рыбу?" Изначально в моих планах было сделать template-matching, но вскоре я понял, что этот вариант мне не подходит, поэтому решил сделать так:
"ЕСЛИ Я ВИДЕЛ РЫБУ И ОНА ПРОПАЛА ИЗ МОЕГО ПОЛЯ ЗРЕНИЯ БОЛЕЕ ЧЕМ НА 1 СЕКУНДУ, ЗНАЧИТ Я ЕЕ ВЫЛОВИЛ"
Данный принцип оказался гораздо проще в исполнении.
На данном этапе мне оставалось только прикрутить возможность закидывать удочку и вытягивать рыбу зажимая ЛКМ, в прочем, это дело нескольких строк кода.
Таким образом Я написал своего первого бота частично используя искуственный интеллект. Кстати, оказалось что кто-то на ютубе уже сделал бота для рыбалки, но там используется другой прицнип, но, в прочем, это не важно.
Следующим делом хочу сделать ботов и для других работ, потому что таких ВРОДЕ нет, но самое главное что это было весело :)