Проверьте, существует ли точка в круговом секторе или нет с помощью Python - PullRequest
2 голосов
/ 03 апреля 2019

Мне известно, что в сети, а также здесь вопрос уже задавался, но, к сожалению, не в среде Python.Глядя в сети, я нашел это ( Link ) и оттуда я начал работать над этим.Так как я использую Pyglet, я написал функцию в виде потока.Но сначала я покажу вам, что я думал и чего хотел добиться:

enter image description here

P = позиция игрока в спрайте

M = позиция мыши

C = Воображаемый круг, радиус которого равен расстоянию между P и M.

0, 1, 2, 3, 4, 5, 6, 7 = Направления, которые может спрайтиметь

a = Угол между одним направлением и другим = 45 °

S = Участок окружности, соответствующий направлению спрайта.Проще говоря, если M присутствует в S, направление равно 1

start, end = Start Angle и End Angle

Итак, в функцию я вставил цикл while.Позже мне пришлось вычислить, когда радиус был:

while mpc_thread:
    radius = math.hypot(mpx - cpx, mpy - cpy) + 20

mpx, mpy = положение мыши (X, Y)

cpx, cpy = позиция игрока в спрайте (X, Y)

Я использовал math.hypot благодаря этому ( Ссылка ).Я добавил 20, чтобы радиус немного превышал положение мыши.

Затем я добавил цикл for, чтобы проверить сечение круга для каждого направления:

while mpc_thread:
    radius = math.hypot(mpx - cpx, mpy - cpy) + 20
    for ang_obj in range(0, fchar):
        reference_angle = 360 // fchar * ang_obj
        s_angle = reference_angle - (360 / (fchar / 2))
        e_angle = reference_angle + (360 / (fchar / 2))

fchar = КоличествоНаправления спрайтов, в данном случае 8

Чтобы выяснить начальный и конечный угол для каждого направления, я разделил угол наклона в два раза на количество направлений.Затем я вычел / добавил результат к исходному углу.

С этого момента начались проблемы.Написав так, как я разместил первую ссылку, функция if ничего не обнаружила, и если я пошел в отрицательном направлении (я получил ошибку. Затем я искал решение и нашел это ( Link ) изОтвет пользователя 7048690. Изменив функцию, я получил новую проблему (ошибка математической области). Поэтому я изменил math.sqrt на cmath.sqrt, и это сработало. Но возникла новая проблема. То есть, всегда следуя этому ответу,Функция if резко снизила FPS до 0/1. Теперь я не знаю, куда идти. Можете ли вы помочь мне с этой проблемой? Как мне правильно построить и работать правильно? Надеюсь, я поняла, что я имела в виду под своим вопросом.

1 Ответ

2 голосов
/ 03 апреля 2019

Самый простой способ найти наилучшее направление - это вычислить косинус угла между линией от позиции игрока до позиции мыши и линией от позиции игрока до 8 точек.
Должен быть найден тот вектор направления, который имеет наименьший угол к направлению «мыши». Косинус 0 градусов равен 1, а косинус 180 ° равен -1. Таким образом, направление с наибольшим косинусом - это направление, которое нужно найти.

Самым простым способом вычисления косинуса является точка произведение .

В общем случае произведение двух векторов точка равно косинус угла между двумя векторами, умноженного на величину (длину) обоих векторов.

dot( A, B ) == | A | * | B | * cos( angle_A_B ) 

Отсюда следует, что произведение точка на 2 единичных вектора равно косинусу угла между двумя векторами, поскольку длина единичного вектора равна 1.

uA = normalize( A )
uB = normalize( B )
cos( angle_A_B ) == dot( uA, uB )

точка произведение двумерных векторов A и B можно рассчитать с помощью 2 умножений и 1 сложения:

dotAB = Ax * Bx + Ay * By  

Настройка списка с 8 нормализованными направлениями:

dir = [(0, 1), (0.707, 0.707), (1, 0), (0.707, -0.707),
       (0, -1), (-0.707, -0.707), (-1, 0), (-0.707, 0.707)]

Найдите «лучшее» направление, это направление с ближайшим углом или наибольшим косинусом угла:

dx, dy = mpx - cpx, mpy - cpy
max_i = max([i for i in range(len(dir))], key = lambda i: dx*dir[i][0] + dy*dir[i][1])

Наконец, max_i содержит искомое направление.

Обратите внимание, что алгоритм не вычисляет и не сравнивает косинус углов, он сравнивает произведение косинуса и радиуса. dx*dir[i][0] + dy*dir[i][1] равно radius * cos(alpha).

Наконец, искомая точка:

radius = math.hypot(mdir_x, mdir_y) + 20
X = (dir[max_i][0] * radius, dir[max_i][1] * radius)

...