Автокликер Clickermann :: Форум
Основной раздел => Общие вопросы => Topic started by: ya12 on October 12, 2018, 10:32:50 AM
-
Нужен совет, как подсчитать количество определенного цвета в многоугольной области. Область задана последовательностью координат Х,Y. Код на кликере или дельфи.
-
А можешь это както показать визуально, хотябы примерн - что за многоугольник, и что за цвета (обьекты с какимто цветом скорее всего). многоугольник статичен или меняет форму со временем?
-
А че, интересно.
STRSEPARATE ("133,83,206,193,79,220,266,276,345,169,339,55,133,83", ",", $arr) //координаты вершин. координаты первой и последней точки - равны
//опрелделяем границы
$y_max = $arr[1]
$y_min = $arr[1]
$x_max = $arr[0]
$x_min = $arr[0]
FOR($i=3,$i<arrsize($arr),2)
IF($y_max < $arr[$i])
$y_max = $arr[$i]
END_IF
IF($y_min > $arr[$i])
$y_min = $arr[$i]
END_IF
IF($x_max < $arr[$i-1])
$x_max = $arr[$i-1]
END_IF
IF($x_min > $arr[$i-1])
$x_min = $arr[$i-1]
END_IF
END_CYC
//закрашиваем буфер нулем
PXLREPLACE(0,0,500,500, -1, 0)
//рисуем единицами
FOR($i=0,$i<arrsize($arr)-2,2)
$x1 = $arr[$i]
$y1 = $arr[$i+1]
$x2 = $arr[$i+2]
$y2 = $arr[$i+3]
$n = ($y2-$y1)/abs($y2-$y1)
FOR($y=$y1,$y!$y2+$n,$n)
$x = ROUND((($x1*$y2-$x2*$y1)+($x2-$x1)*$y)/($y2-$y1),0)
PXLREPLACE ($x,$y,$x,$y, -1, 1)
end_cyc
END_CYC
//SCREENSHOTEX(0,0,500,500, "Image_", 0)
//закрашиваем все что в нутри многоугнольникам с помощью оператора XOR pxl($x,$y) xor pxl($x+1,$y)
FOR($y=$y_min+1,$y<$y_max)
FOR($x=$x_min,$x<$x_max)
pxlreplace($x+1,$y,$x+1,$y, -1, pxl($x,$y) xor pxl($x+1,$y) )
END_CYC
END_CYC
//то что получили, перекрашиваем в нужные цвета.
PXLREPLACE(0,0,500,500, 0, 16777215)
SCREENSHOTEX(0,0,500,500, "Image_", 0)
halt
//это наглядный пример с последующим получением массива всех точек в многоугольнике с помощью сканпиксела. нУ И ПООЧЕРЕДИ ПРОВЕРЯТЬ КАЖДУЮ КООРДИНАТУ НА ИСКОМЫЙ ЦВЕТ
//НО МОЖНО ПЕРЕДЕЛАТЬ БЕЗ ГРАФИЧЕСКОГО БУФЕРА, НАПРЯМУЮ СОЗДАВАТЬ МАССИВ КООРДИНАТ. И ДАЛЬЕ УЖЕ ЦИКЛ ПРОВЕРКИ ЭТИХ ПИКЧЕЛЕЙ НА ИСКОМЫЙ
Возможны ошибки, вечером подробнее проверю. Инфа отсюда https://habr.com/post/116398/ .
Результат из кода выше:
(https://i.imgur.com/itmz8Xr.png)
-
Паскаль у меня был 20 лет назад и мозг не такой гибкий, как раньше. Играть уже не очень интересно, в свободное время пишу бота, что бы вместо меня играл в линейку.
Большинство данных берется из памяти клиента. В ручную задаются координаты зоны охоты и маршрут внутри нее, если нет мобов. У внутриигровой команды /targetnext радиус действия маленький. Как это обойти я нашел, теперь можно брать ближайшего по заданному списку в пределах видимости клиентом. Но между ботом и мобом могут быть препятствия. Соответственно если между ними нет белого цвета можно брать в таргет и бежать напрямую, если есть продолжаем бег по заданному маршруту.
На рисунке точка 1 = бот, 2 и 3 - мобы. Внутри желтой области бот охотится на мобов.
В кликере есть функция для прямоугольной области PXLCOUNT (x, y, x2, y2, color). Мне же нужен многоугольник.
-
Если между 1 и 2 точками нет белого цвета атакуем. Между 1 и 3 есть белый цвет не атакуем. На зеленые полосы не обращаем внимания, они нарисованы позже, для наглядности.
-
Бот бегает по заданному маршруту внутри желтой области. Мобы нужны не все и только внутри заданной области. Физические размеры бота и моба больше точки, плюс есть еще камера от 3 лица которая вблизи стен начинает тупить, что вносит искажения в расчеты угла поворота.
Поэтому считаем количество белого цвета в 4х угольнике между ботом и мобом. Если 0 то можно брать в таргет и атаковать. Персонаж автоматически бежит по прямой к мобу. Если больше 0, то или этот моб вне желтой зоны или есть препятствия, продолжаем бежать по маршруту пока между ботом и мобом не будет белого цвета.
-
Действительно, задача одна, а просишь другое.
По словесному описанию понятно, я даже делал такое в боте для TimeZero, правда там гексы.
И ходил не очень оптимально, но там так и нужно было, т.к. дальность действия оружия не маленькая.
1. Вычисляем азимут на ближайшего моба, это же предпочитаемый азимут движения.
2. Пока не важно есть прямой путь к мобу или нет. Есть определённый выбранный оптимальный радиус при достижении которого начинаем искать обход.
3. Проверяем на линии между персом и мобом нет ли препятствий (стен) ближе, чем заданное расстояние.
4. Если препятствие есть идём на моба...
5. Пока расстояние до препятствия больше размера радиуса из п.2 идём на моба
6. Если равно или меньше ищем обходной путь...
6.1 От выбранного направления на расстоянии радиуса из п.2 проверяем точки на окружности со сдвигом в N градусов поочерёдно в обе стороны.
Т.е. на 5 градусов левее направления преведущего движения, на 5 правее, на 10 левее, на 10 правее и т.д. пока не всретим открытое место.
6.2 Вычисляем новый азимут движения, на новую точку. Берём чуть запас в ту же сторону чтоб не идти впритирку.
6.3 Пока идём в этом направлении проверяем не открылся ли из текущей точки прямой путь.
-
Мне только подсчет цветов, остальное я уже сделал.
-
Хм. Ты так и не объяснил, зачем здесь считать цвета?
-
Не важно сколько желтых, важно что-бы белых не было.
Пример во вложении
-
И действительно, можно было както попроще все это замутить. Да хотябы тем же уровненией прямой, если одной линии пикселей мало, то можно с несколькими сдвигами.
Но, раз уж я там выше накалякал эти ненужные сложные расчеты, то вот на твоем рисунке прямо с браузера с колормодом №6.
19:26:46 start
19:27:04 в нашей области 3268 белых пикселей
19:27:05 в нашей области 1312 зеленых пикселей
19:27:06 в нашей области 808 желтых пикселей
19:27:06 а всего в нашей области 16354 пикселей
всегото 20 секунд ;D, но и размеры твоей картинки не маленькие...
print("start")
$allx1 = 508 //координаты твоего рисунка
$ally1 = 814
$allx2 = 2039
$ally2 = 1675
STRSEPARATE ("819,1592,1020,1117,1035,1119,834,1600,819,1592", ",", $arr) //координаты вершин. координаты первой и последней точки - равны
//опрелделяем границы
$y_max = $arr[1]
$y_min = $arr[1]
$x_max = $arr[0]
$x_min = $arr[0]
FOR($i=3,$i<arrsize($arr),2)
IF($y_max < $arr[$i])
$y_max = $arr[$i]
END_IF
IF($y_min > $arr[$i])
$y_min = $arr[$i]
END_IF
IF($x_max < $arr[$i-1])
$x_max = $arr[$i-1]
END_IF
IF($x_min > $arr[$i-1])
$x_min = $arr[$i-1]
END_IF
END_CYC
//закрашиваем буфер нулем
PXLREPLACE($allx1,$ally1,$allx2,$ally2, -1, 0)
//рисуем единицами
FOR($i=0,$i<arrsize($arr)-2,2)
$x1 = $arr[$i]
$y1 = $arr[$i+1]
$x2 = $arr[$i+2]
$y2 = $arr[$i+3]
$n = ($y2-$y1)/abs($y2-$y1)
FOR($y=$y1,$y!$y2+$n,$n)
$x = ROUND((($x1*$y2-$x2*$y1)+($x2-$x1)*$y)/($y2-$y1),0)
PXLREPLACE ($x,$y,$x,$y, -1, 1)
end_cyc
END_CYC
//закрашиваем все что в нутри многоугнольникам с помощью оператора XOR pxl($x,$y) xor pxl($x+1,$y)
FOR($y=$y_min+1,$y<$y_max)
FOR($x=$x_min,$x<$x_max)
pxlreplace($x+1,$y,$x+1,$y, -1, pxl($x,$y) xor pxl($x+1,$y) )
END_CYC
END_CYC
//то что получили, перекрашиваем в нужные цвета.
PXLREPLACE($allx1,$ally1,$allx2,$ally2, 0, 16777215)
SCREENSHOTEX($allx1,$ally1,$allx2,$ally2, "Image_", 0)
SCANPXL($var, $allx1,$ally1,$allx2,$ally2, 1) // создаем массив координат каждой точки нашего многоугольника
GETSCREEN //обновляем наш испорченный буфер
COLORMODE(6) //так как в оригинале jpg, делаем цвета почетче
FOR($i=0,$i<arrsize($var), 2)
IF(pxl($var[$i],$var[$i+1]) = 16777215)
inc($n_pix)
END_IF
END_CYC
print("в нашей области ",$n_pix," белых пикселей")
$n_pix = 0
FOR($i=0,$i<arrsize($var), 2)
IF(pxl($var[$i],$var[$i+1]) = 4194239)
inc($n_pix)
END_IF
END_CYC
print("в нашей области ",$n_pix," зеленых пикселей")
$n_pix = 0
FOR($i=0,$i<arrsize($var), 2)
IF(pxl($var[$i],$var[$i+1]) = 4194303)
inc($n_pix)
END_IF
END_CYC
print("в нашей области ",$n_pix," желтых пикселей")
print("а всего в нашей области ", arrsize($var)," пикселей")
halt
Во вложении черным отмечена та область которая сканировалась (относительно всего рисунка).
-
Не взлетит. Там опрашивать надо хотя бы 1 раз в секунду. Буду думать.
зы Картинка сжата раз в 5.
-
зы Картинка сжата раз в 5.
:o раз в пять?
Разрешение твоей картинки 1533х864, если это умножить на пять, то это уже даже в рамки 4К не влазит.
Но это не важно, на скорость выполнения влияет только границы искомой области, это x_min - y_min - x_max - y_max . В твоем примере это примерно 220х480 точек, размер не маленький.
Но и это не важно, нужно искать более подходящий и простой принцип работы для такой задачи. Как вариант, я писал выше, уровнение прямой - тупо проверяешь линию пикселей от бота к мобу. Если этого мало, то можно проверить по тойже прямой но со смещением (право лево либо верх низ). Либо попробуй вариант что предложил Vint, я сильно не вникал в его суть...
-
Человек отказался, уже всё сделано. Осталось подсчитать цвета. Вот только считать их и не надо, что я и пытался донести.
Здесь нужно придумать способ чтобы было просто и быстро. Способ я давно уже придумал, тогда ещё. А начинал тоже с подсчёта, потом с поиска, там такие ужасные количества получались...
На самом деле можно проверять несколько раз в секунду в зависимости от размеров. И даже уравнение прямой не нужно, там нужно другое уравнение.
Могу дать направление. Видите, у нас обширные области, места полно. И нам к мобу не по канату идти над пропастью, такая точность не нужна.
-
Можно и по уравнению прямой проверить, тоже нормально. Только взять две прямые чуть левее и чуть правее если линия ближе к вертикальной. Можно проверять не каждый пиксел, а с шагом. Шаг можно взять чуть меньше, чем расстояние которое мы сдвинули линию. Ведь там нет уж очень острых углов. Может и больше можно.
-
Точность таки нужна, потому что нижняя желтая ножка - это мост без перил над пропастью на котором сидят мои баферы и куда нужно возвращаться каждые 20 минут. Буду пробовать с 2мя линиями.
-
1. Вычисляем азимут на ближайшего моба, это же предпочитаемый азимут движения.
2. Пока не важно есть прямой путь к мобу или нет. Есть определённый выбранный оптимальный радиус при достижении которого начинаем искать обход.
3. Проверяем на линии между персом и мобом нет ли препятствий (стен) ближе, чем заданное расстояние.
4. Если препятствие есть идём на моба...
5. Пока расстояние до препятствия больше размера радиуса из п.2 идём на моба
6. Если равно или меньше ищем обходной путь...
6.1 От выбранного направления на расстоянии радиуса из п.2 проверяем точки на окружности со сдвигом в N градусов поочерёдно в обе стороны.
Т.е. на 5 градусов левее направления преведущего движения, на 5 правее, на 10 левее, на 10 правее и т.д. пока не всретим открытое место.
6.2 Вычисляем новый азимут движения, на новую точку. Берём чуть запас в ту же сторону чтоб не идти впритирку.
6.3 Пока идём в этом направлении проверяем не открылся ли из текущей точки прямой путь.
Интересно.
Дословно не смог понять этот алгоритм, но пока пытался понять, возможно пришел к чемуто своему (хотя, возможно это именно то что ты и пытался обьяснить). Но так как пока практической нужды нету, не на чем испытывать.
А вообще, если карта статична, то какой смысл писать искустсвенный интеллект? :D . Если мы видим моба в какойто определенной области карты, то почему бы не пойти в эту область по заранее записанному маршруту?
-
Ну там карт много. Мы появляемся в нескольких местах и мобы рандомно ходят. Проще отслеживать на лету чем чем собирать все данные и прописывать. Если такое вообще возможно.
Да, с описанием беда :) сам понимаю. Картинки бы помогли, но я с телефона.
-
А еще...
Может вполне себе справиться "алгоритм поиска пути А*" http://crapware.aidf.org/forum/index.php?topic=1958.0. Карта то не сложная. Или в реале это не так? Разрешение "рабочей" карты большое не потребуется.
Я вот вчера и сегодня немного пытался понять принцип работы этого алгоритма... :( понял, что пока не мой уровень. А еще и надеялся всунуть его в длл плагин... мечты... ;D
Пока читал различные статьи, заметил что есть "мод" для этого алгоритма - "Jump Point Search" https://habr.com/post/162915/
@Vint
Не уж то этот JPS сложнее в написании чем поиск пути А*? А по скорости выполнения прирост должен быть ощутимым ::) .
Вроде написано "Этот алгоритм является улучшенным алгоритмом поиска пути A*. ". Значит они в чемто схожи.