Author Topic: Скрипт по изображению  (Read 6121 times)

0 Members and 1 Guest are viewing this topic.

SergPT

  • Зашел в гости
  • *
  • Posts: 3
    • View Profile
Скрипт по изображению
« on: April 27, 2014, 04:01:51 PM »
Для завсегдатаев думаю моя задача окажется простой, но я запутался, буду очень признателен за помощь в написании скрипта через опознавание скриншотов (их я понял надо сделать  .BMP ;)
В игре нужно нажимать кнопку -Изучить постоянно пока не кончится энергия.
Но:
- рандомно выпадает карта - надо нажать на нее, она исчезнет и появится картинка №1 и затем снова кнопку - Изучить
 - точно также рандомно попадаешь на боса (лунный Коготь -всегда именно он) - надо нажать кнопку -Бегство и возвращаемся к картинке №1 (после этого он 2ч не будет выпадать)
-когда закончится энергия -нажать в окне - ОК - возвращаемся к картинке №1 и сделать задержку 5мин до следующего нажатия пока не пополнится энергия - затем Изучить и так по кругу зациклить

Начал пробовать и все не то:
GETSCREEN
SCANPICTURE($ARR_SCAN, 0,0, $_xmax,$_ymax, "Foto_Zlobius.bmp", -1, 100)
$ARR_NUM = 0
WHILE ($ARR_NUM < ARRSIZE($ARR_SCAN))
   $X = $ARR_SCAN [$ARR_NUM]
   INC($ARR_NUM,1)
   $Y = $ARR_SCAN [$ARR_NUM]
   INC($ARR_NUM,1)
   MOVE($X, $Y)   // перемещаем курсор
   LOGWRITE ("X: ", 1072, " Y: ", 386)
   WAITMS(100)
END_CYC
UNDEFINE($ARR_SCAN)
HALT
Картинка №1 -нажимать -Изучить
[/img]http://clip2net.com/s/7iws1a]
Выпадающий лут -просто нажать на картинку
[/img]http://clip2net.com/s/7iwvyB]
БОсс - нужно нажать бегство
[/img]http://clip2net.com/s/7iwxGx]
Закончилась энергия - нажать ОК
[/img]http://clip2net.com/s/7iwyxR]

Atas

  • Активный участник
  • ***
  • Posts: 147
    • View Profile
Re: Скрипт по изображению
« Reply #1 on: April 27, 2014, 06:40:59 PM »
Тут сценарий сводится к тому, чтобы определить на каком экране игры мы в данный момент находимся и выполнить заранее известное действие. Нужно найти уникальные пиксели, которые позволят с вероятностью 100% идентифицировать текущий экран.
В своем примере за такие уникальные пиксели я взял кнопки управления в игре. Предполагается, что на экране "Бой с боссом" нет кнопки "Изучить", а в окне сбора лута нет кнопки "Бегство" и т.д.

Пример скрипта (вставьте свои координаты и задержки в нужных местах):
Code: (clickermann) [Select]

WHILE($var < 1) // Цикл
   
   GETSCREEN
   
   IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Изучить.bmp", -1, 100) // Кнопка "Изучить" есть?
      LCLICK(x, y) // Если есть, то кликаем по этой кнопке
      WAIT(3) // Ожидание смены изображения
   END_IF
   
   IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Лут.bmp", -1, 100) // Окно сбора лута
      LCLICK(x, y)
      WAIT(3)
   END_IF
   
   IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Бегство.bmp", -1, 100) // Бой с боссом
      LCLICK(x, y)
      WAIT(3)
   END_IF   
   
   IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Закончилась энергия.bmp", -1, 100)
      LCLICK(x, y) // Нажимаем "OK"
      WAIT(300) // Задержка 5 минут, пока не пополнится энергия
   END_IF
   
   WAITMS(500) // Частота проверки экрана
   
END_CYC

Необходимо будет сделать несколько картинок (*.bmp) для сравнения и поместить их в папку проекта.
Если получится идентифицировать текущий экран по одному уникальному пикселю, будет здорово, если же придется использовать картинки, то уменьшаем их размер до предела (и зону поиска картинок тоже). Например, из кнопки "Изучить" достаточно взять только полоску пикселей похожую на штрих код (см. вложение). Картинка 1x10 цветных пикселей, в точно указанных координатах на экране, вряд ли встретится не только в игре но и вообще где либо на компьютере.

Ах да, сорри, чуть не забыл...
Подсказка дня по оптимизации кода от СОЗДАТЕЛЯ (!): http://crapware.aidf.org/forum/index.php?topic=1169.msg5358#msg5358
Это позволит обойтись вообще без картинок. :)
« Last Edit: April 27, 2014, 06:59:57 PM by Atas »

SergPT

  • Зашел в гости
  • *
  • Posts: 3
    • View Profile
Re: Скрипт по изображению
« Reply #2 on: April 27, 2014, 09:06:40 PM »
Atas, Большое тебе спасибо :)
Все получилось, правда не с первой попытки, но работает как надо.
Если тебя не затруднит помоги пож-та  дальше, жадность приходит во время еды ;)

После того как энергия закончилась, пришла мысль, а зачем ждать 5мин, когда у нас есть 90мин на ее полное восстановление, значит можно сделать еще что-то значимое, а именно израсходовать ману.
Как сделать так, чтобы как только нашлась картинка "Закончилась энергия" мы нажали кнопку "ок" (это мы уже сделали) и дальше все шло не по новой, а:
 - нажать кнопку "Назад" - координаты Х, У (она на первом скрине есть в первом моем посту)
-еще раз нажимаем кнопку назад (попадаем на карту)
- далее по скрину найти город Авалон и куда нажать, это мы делали, должно быть так:
IF_PICTURE_IN (0,0, $_xmax,$_ymax, ".bmp", -1, 100) // Окно города Авалон
         LCLICK(х, у)
         WAIT(2)
      END_IF
-Вошли в город, тут тоже самое - по скрину определить и нажать на него, такой же код
IF_PICTURE_IN (0,0, $_xmax,$_ymax, ".bmp", -1, 100) //Босс Авалон
         LCLICK(х, у)
         WAIT(2)
      END_IF
-нажать кнопку "бой" - функции те же, это понятно
-Если выпал Лут - жмем на него - функция известна
- Жмем кнопку "Ок" -тоже все ясно
- снова ищем скрин босса Авалона -тоже понятно

И так по кругу пока не кончится мана, т.е. мы не попадем на кнопку наподобие Энергия, только тут она будет называться "Мана"
- после этого нам надо вернуться к "Энергии", т.е. нажать 2 раза назад

Но вот тут получается неприятность,тк. после 2 нажатий Назад попадаем на эту Карту

Нам для вовзрата на "Энергию" нужен город, а его не видно сейчас на карте и нужно зажав левую кнопку мышки протащить экран влево.
-дальше все понятно, по скрину жмем на него, потом еще на локацию -тоже ясно
-и мы вернулись на нашу готовую локацию
Вот как она сейчас работает
 [spoiler]WHILE($var < 1) // Цикл
     
      GETSCREEN
     
      IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Изучить.bmp", -1, 100) // Кнопка "Изучить" есть?
         LCLICK(1800, 500) // Если есть, то кликаем по этой кнопке
         WAIT(2) // Ожидание смены изображения
      END_IF
     
      IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Пес.bmp", -1, 100) // Окно сбора лута
         LCLICK(1141, 550)
         WAIT(2)
      END_IF
     
        IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Дикобразина.bmp", -1, 100) // Окно сбора лута
         LCLICK(1141, 550)
         WAIT(2)
      END_IF
     
            IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Русалка.bmp", -1, 100) // Окно сбора лута
         LCLICK(1141, 550)
         WAIT(2)
      END_IF
     
      IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Бегство.bmp", -1, 100) // Бой с боссом
         LCLICK(1800, 862)
         WAIT(2)
      END_IF 
     
      IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Энергия.bmp", -1, 100)
         LCLICK(1374, 363) // Нажимаем "OK"
         WAIT(300) // Задержка 5 минут, пока не пополнится энергия
      END_IF
     
      WAITMS(500) // Частота проверки экрана
     
    END_CYC[/spoiler]

Atas

  • Активный участник
  • ***
  • Posts: 147
    • View Profile
Re: Скрипт по изображению
« Reply #3 on: April 28, 2014, 06:36:25 PM »
Я уж понял, что скриптом "в пару строк" мне тут не отделаться. ;D
Писанины будет много, поэтому нужно всё в скрипте упорядочить и разложить по полкам. Потребуется разбить скрипт на несколько разделов. Каждый раздел должен выполнять свою конкретную задачу. Например, раздел "Идентификация экрана" отвечает за то, что где бы в игре мы не находились, он распознает текущий экран и передаст управление другому отделу, например модулю "Бой с боссом", который, в свою очередь, тоже знает что делать, и куда нас потом послать.  :)
Приведу для примера скрипт, где я попытался изобразить нечто подобное. Это не готовое решение, а обрывки кода (для наглядности), и всё это требует осмысления. Так или иначе, если скрипт будет большой и сложный, то у него должна быть структура. А модульность позволит не запутаться в коде, а так же позволит изменять отдельные модули не переписывая каждый раз заново весь скрипт.

[spoiler]
Code: (clickermann) [Select]
//================================ Подпрограмма - Переход к стартовому экрану

SUB(RETURN)
   WHILE($var < 1)
      GETSCREEN
      IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Назад.bmp", -1, 100) // Кнопка "Назад"
         LCLICK(x, y)
         WAIT(2)
      ELSE
         $var = 1
      END_IF
   END_CYC
   UNDEFINE($var)
   // ... или другие действия, позволяющие вернуться в Главное окно игры
   // из любой точки игрового мира. Например, что бы выбрать другую миссию.
END_SUB

//================================ Идентификация экрана

identification:

GETSCREEN

IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Окно ввода пароля.bmp", -1, 100) // На случай дисконнекта
   #include "password.cms" // Скрипт, который вводит пароль, в отдельном файле (тут не светится)
   WAIT(2)
END_IF

// Главное (или стартовое) окно служит отправной точкой для выбора приключений в игре.
// Здесь, например, можно выбрать город или поле боя, куда хотим сходить.
// Сюда мы будем возвращаться выполнив очередную миссию в игре, чтобы выбрать следующую.
IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Главное окно.bmp", -1, 100)
   GOTO(main_window) // Так как тут возможны варианты развития событий, переходим в специальный раздел
END_IF

IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Окно сбора лута.bmp", -1, 100) // Окно сбора лута
   LCLICK(1141, 550) // OK - обшариваем жалкий трупик поверженного врага
   WAIT(2)
   GOTO(identification) // Лут собран, снова проверяем где мы находимся
END_IF

IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Окно боя с боссом.bmp", -1, 100) // Бой с боссом
   GOTO(mortal_kombat) // Переходим в специальный раздел
END_IF

IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Город.bmp", -1, 100) // Окно города
   GOTO(city)
END_IF

IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Карта.bmp", -1, 100) // Карта игрового мира
   GOTO(map) // Переходим в специальный раздел
END_IF

IF_PICTURE_IN (0,0, $_xmax,$_ymax, "Энергия.bmp", -1, 100) // Если кончилась Энергия
   LCLICK(1374, 363) // Нажимаем "OK"
   $energy = 0
   WAIT(2)
   RETURN() // Вызываем подпрограмму, для возврата в Главное окно (откуда и напрвимся тратить ману)
END_IF

// Далее другие окна, которые возможно встретить в игре ...
// Окна, которые появляются в игре чаще других, располагаются в этом списке выше остальных.

//--------------------------------

IF($re_identification < 10) // 10 попыток распознать текущий экран
   INC($re_identification,1)
   WAIT(1)
   GOTO(identification)
ELSE
   SCREENSHOT ("Неизвестный экран - ") // Экран распознать не удалось, делаем скриншот
   HALT // Останавливаем сценарий
END_IF

//================================ Главное окно

main_window:
// Здесь происходит выбор направлений и расстановка приоритетов для приключений.
//
// Например ...
// 1. Идем тратить энергию
// a) энергия есть, идем тратить энергию
//    b) если энергия потрачена ($energy = 0), тогда идем тратить ману
//     
// 2. Идем тратить ману
// a) мана есть, идем тратить ману
//    b) если мана тоже потрачена, тогда идем в магазин
//
// 3. Идем в магазин тратить золото
//    a) Золото есть, покупаем энергию или ману и идем тратить
//    b) Золота тоже нет, делаем паузу
//
// 4. Задержка 5 минут, пока не пополнится энергия или мана
//
GOTO(identification) // Выбрав приключение, проверяем куда нас закинуло

//================================ Бой с боссом

mortal_kombat:

LCLICK(1800, 862) // Тыдыщ!!!
WAIT(2)
GOTO(identification) // Проверка - "Уж не на кладбище ли я?"

//================================ Карта (или Маршруты)

map:

// Действия, например ...
#include "Авалон - Солсбери.cms" // Инклуд содержит скрипт, который проведет нас от Авалона до Солсбери

// Или вот ещё ...
IF($avalon_visited = 1) // Если в Авалоне мы уже были, перемещаемся в следующий по списку город
   #include "Еду в Магадан.cms"
END_IF

GOTO(identification) // Где я?

//================================ Город

city:
// Действия в городе ...
GOTO(куда_надо)

//--------------------------------
// Каждый специальный раздел - самостоятельная программа, которую можно
// редактировать отдельно, не нарушая работу других разделов скрипта.

HALT
[/spoiler]

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

SergPT

  • Зашел в гости
  • *
  • Posts: 3
    • View Profile
Re: Скрипт по изображению
« Reply #4 on: April 30, 2014, 11:33:24 AM »
Спасибо буду разбираться на днях, так сходу не все понял, буду походу дела спрашивать))

Andrey_13

  • Освоившийся
  • **
  • Posts: 28
    • View Profile
Re: Скрипт по изображению
« Reply #5 on: August 12, 2014, 12:58:22 PM »
Можно вопрос?
Я так понимаю если в Кликере задавать координаты точек то скрипт будет правильно работать только под мое разрешение экрана, а если делать скрины кнопок, кусочек карты и всего прочего что есть в игре тогда скрипт будет более универсальный?

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Скрипт по изображению
« Reply #6 on: August 12, 2014, 02:14:09 PM »
Можно вопрос?
Я так понимаю если в Кликере задавать координаты точек то скрипт будет правильно работать только под мое разрешение экрана, а если делать скрины кнопок, кусочек карты и всего прочего что есть в игре тогда скрипт будет более универсальный?
Да. При задании точных координат будет работать не только на твоём разрешении, а ещё и при том же положении окон. И, например, в случае браузера ещё и на том же браузере той же версии с тем же расположением и количеством панелей.
Короче, можно попасть.

Для универсальности не обязательно заменять все клики на поиск. Поиск стоит применять для элементов, которые и так появляются в разных местах или нужно отследить их появление. Большинство координат можно привязать к неизменным элементам игры (опять же).
Вот пример http://crapware.aidf.org/forum/index.php?topic=69.0
Изначально ищется изображение монеты слева вверху, её (или угол рядом) можно принять за координаты 0,0. Все клики и области задаём не глобально, а относительно этого нашего базиса.
Например нашли монеты, записали координаты начала отсчёта
Code: (clickermann) [Select]
      $vX = $_return1-19
      $vY = $_return2-13
и после, где нужно всё отсчитываем от них
Code: (clickermann) [Select]
LCLICK($vX+813,$vY+77)
//или .....
IF_PICTURE_IN($vX+148,$vY+446,$vX+666,$vY+638, "5.bmp")


Andrey_13

  • Освоившийся
  • **
  • Posts: 28
    • View Profile
Re: Скрипт по изображению
« Reply #7 on: August 12, 2014, 03:19:27 PM »
А если я играю на "BlueStacks App Player" то можно определить что-то в левом углу, принять за начала координат, и вести отсчет от него?
а потом MOVE($vX+29,$vY+188) - перемещает курсор мышки ?

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Скрипт по изображению
« Reply #8 on: August 12, 2014, 04:35:08 PM »
Примерно так.


Andrey_13

  • Освоившийся
  • **
  • Posts: 28
    • View Profile
Re: Скрипт по изображению
« Reply #9 on: August 12, 2014, 08:51:40 PM »
У меня с программированием не очень, задам еще вопрос.
А какого размера должен быть базис и как проверить что он единственный на этом экране?
Если в игре несколько игровых меню/полей то в каждом надо делать базис?
$_return1-19 - не совсем понял, что за "-19"?

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Скрипт по изображению
« Reply #10 on: August 13, 2014, 01:19:12 AM »
-19 - это значение которое отнимается от переменной чтобы получить в результате сдвиг относительно найденной картинки или пиксела. Кликерман поддерживает вычисления прямо в функциях.