Обнаружить столкновение между текстовым полем и кругом в пигме - PullRequest
2 голосов
/ 09 октября 2019

Я пытаюсь создать игру на python, где можно перетаскивать текстовое поле по экрану, но всякий раз, когда оно касается границ круга вокруг него, я хочу, чтобы цикл начинался заново, но с другим текстом (хранение всех текстовых строк в списке, но я пока не так далеко). Вот как далеко я зашёл:

import pygame

import ptext

pygame.init()

gameDisplay = pygame.display.set_mode((500, 500))

gameDisplay.fill((255,255,255))

x = 190
y = 230
a = 250
b = 250

text = "ExampleText 1."

def textbox(x,y):
    ptext.draw(text, (x,y), color = (0,0,0))


def circle(a,b): 
    pygame.draw.circle(gameDisplay, (0,0,0), (250, 250), 210, 5)


done = False

while not done:
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT:
            done = True
        elif event.type == pygame.MOUSEMOTION:
            if event.buttons[0]:
                x += event.rel[0]
                y += event.rel[1]

    textbox(x,y)
    circle(a,b)
    pygame.display.flip()

pygame.quit()
quit()

Теперь я понимаю, что мне нужно будет обнаружить столкновение границ моих объектов, но здесь я довольно растерялся. Я попытался сохранить переменные моих объектов в прямоугольниках, а затем создать другой оператор if, который распознает, сталкиваются ли мои объекты (я использовал команду печати, потому что я еще не получил нужную команду), но это победилоничего не печатать, и я уверен, что я на неправильном пути, но это мое лучшее усилие ...

Для этого я определил:

text_rect = pygame.Rect(x, y, 10, 30)

circle_rect = pygame.Rect(a,b, 300, 300)

, а затем вМой цикл:

if circle_rect.colliderect(text_rect): 
     print("COLLIDE")

Есть ли у кого-нибудь советы о том, как лучше определить объекты и создать нужную мне функцию?

(Правка: Кстати: я не слишкомобеспокоен тем, что когда я перетаскиваю свое текстовое поле, он оставляет отпечаток текста, поскольку этого не происходит в моем исходном скрипте, но был бы благодарен, если бы кто-нибудь знал, почему это происходит в моем текущем примере.)

1 Ответ

3 голосов
/ 09 октября 2019

Прямоугольник имеет 4 угловых точки. Если прямоугольник «меньше», чем окружность (диаметр окружности больше, чем диагональ прямоугольника), тогда прямоугольник сталкивается с контуром окружности, если хотя бы одна точка находится вне окружности и хотя быодна точка находится в круге.

Определите прямоугольник и настройте список угловых точек. Далее вы должны знать радиус круга:

w, h = 10, 30
rect = pygame.Rect(x, y, 10, 30)

corners = [rect.bottomleft, rect.bottomright, rect.topleft, rect.topright]
radius = 210

Рассчитать Евклидово расстояние каждой угловой точки до центра круга (a, b):

import math
dist = [math.sqrt((p[0]-a)**2 + (p[1]-b)**2) for p in corners]

Создание в списки, один с точками в круге (p_in) и один с точками вне круга (p_out):

p_out = [i for i, d in enumerate(dist) if d > radius]
p_in  = [i for i, d in enumerate(dist) if d < radius]

Если оба спискасодержит элемент any, тогда прямоугольник пересекает контур круга:

if any(p_in) and any(p_out):
    print("COLLIDE")

Если len(p_in) равно 4, то прямоугольник полностью находится в круге. Если len(p_out) равно 4, то прямоугольник полностью выходит из круга.

if any(p_in) and any(p_out):
    print("COLLIDE")
elif len(p_in) == 4:
    print("IN")
elif len(p_out) == 4:
    print("OUT")

См. Простой пример, который основан на вашем фрагменте кода и демонстрирует тест на столкновение. Прямоугольник прикреплен к мышке:

import pygame
import math

pygame.init()
gameDisplay = pygame.display.set_mode((500, 500))
done = False
while not done:
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT:
            done = True

    x, y = pygame.mouse.get_pos()
    w, h = 10, 30
    rect = pygame.Rect(x, y, 10, 30)
    a, b = 250, 250
    radius = 210

    corners = [rect.bottomleft, rect.bottomright, rect.topleft, rect.topright]
    dist    = [math.sqrt((p[0]-a)**2 + (p[1]-b)**2) for p in corners] 
    p_out   = [i for i, d in enumerate(dist) if d > radius]
    p_in    = [i for i, d in enumerate(dist) if d < radius]

    if any(p_in) and any(p_out):
        print("COLLIDE")
    elif len(p_in) == 4:
        print("IN")
    elif len(p_out) == 4:
        print("OUT")

    gameDisplay.fill((255,255,255))
    pygame.draw.rect(gameDisplay, (255, 0, 0), rect)
    pygame.draw.circle(gameDisplay, (0,0,0), (a, b), radius, 5)
    pygame.display.flip()

pygame.quit()
quit()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...