Извините за мой английский и начинающие знания Python
Я пытаюсь найти способ, во время столкновения между двумя прямоугольниками (движущаяся пуля и коробка), какая сторона коробки попала в пулю. В настоящее время я использую rect.midtop, midright, midleft, midbottom пули, чтобы найти его. Моя проблема в том, что пуля перемещается на несколько пикселей одновременно, и когда пуля попадает в коробку, но недостаточно близко к центру, она регистрирует неправильное коллизия.
Пример:
Пуля идет из нижней части экрана, и я вижу, что это должно быть коллизия с нижней стороной поля, но оно не касается rect.midtop, а вместо этого затрагивает rect.midright и регистрирует неправильное событие столкновения.,
Вот мой код столкновения:
if self.bullet.rect.collidelist(self.listbox):
self.bullet.pretx1 = 1
self.bullet.pretx2 = 1
self.bullet.prety = 1
self.bullet.pret = 1
for box in self.listbox:
if box.rect.collidepoint(self.bullet.rect.midtop) or box.rect.collidepoint(self.bullet.rect.midbottom) and self.a == 1:
self.a = 0
print("vertical")
print(self.bullet.angle)
self.bullet.angle = abs(360 - self.bullet.angle)
print(self.bullet.angle)
self.listbox.remove(box)
elif box.rect.collidepoint(self.bullet.rect.midleft) or box.rect.collidepoint(self.bullet.rect.midright) and self.a == 1:
self.a = 0
print("horizontal")
print(self.bullet.angle)
self.bullet.angle = 180 - self.bullet.angle
print(self.bullet.angle)
if self.bullet.angle < 0:
self.bullet.angle += 360
print(self.bullet.angle)
self.listbox.remove(box)
Как бы вы это сделали? Я пытался получить прямую линию, сравнивая углы, используя маски, но я не мог найти решение для работы.
Спасибо за ваше время!
Используйте вектор направления (dx
, dy
) от центра box
к центру bullet
, чтобы определить, подходит ли рамка слева, справа, сверху или снизу:
dx = self.bullet.rect.centerx - box.rect.centerx
dy = self.bullet.rect.centery - box.rect.centery
4 направления, которые должны быть проверены:
dir = [(-1, 0), (1, 0), (0, -1), (0, 1)]
dirName = ["left", "right", "top", "bottom"]
Вы должны определить то направление, которое близко к (dx
, dy
). Это можно сделать путем сравнения точечного произведения вектора (dx
, dy
) и векторов с четырьмя направлениями, что аналогично проверке, существует ли точка в круговом секторе или нет в Python
В общем случае произведение двух векторов равно косинусу угла между двумя векторами, умноженному на величину (длину) обоих векторов:
dot( A, B ) == | A | * | B | * cos( angle_A_B )
Точечное произведение двумерных векторов A и B можно рассчитать с помощью 2 умножений и 1 сложения:
dotAB = Ax * Bx + Ay * By
Направление шкафа - это направление, при котором получается максимальное произведение точек. Максимальный кулачок можно найти по max
:
max_dir = max([i for i in range(len(dir))], key = lambda i: dx*dir[i][0] + dy*dir[i][1])
например
dir = [(-1, 0), (1, 0), (0, -1), (0, 1)]
dirName = ["left", "right", "top", "bottom"]
for box in self.listbox:
if box.rect.colliderect(self.bullet.rect):
dx = self.bullet.rect.centerx - box.rect.centerx
dy = self.bullet.rect.centery - box.rect.centery
max_dir = max([i for i in range(len(dir))], key = lambda i: dx*dir[i][0] + dy*dir[i][1])
print("hit", dirName[max_dir])
# [...]