python - 检测pygame中文本框和圆圈之间的碰撞

标签 python pygame collision-detection

我正在尝试用 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")

有人对定义对象和创建我想要的函数有更好的方法吗?

(编辑:顺便说一句:我不太关心当我拖动文本框时,它会留下文本的打印,因为这在我的原始脚本中不会发生,但如果有人知道为什么在我当前的示例中会这样做。)

最佳答案

矩形有 4 个角点。如果矩形比圆“小”(圆的直径大于矩形的对角线),则矩形与圆的轮廓碰撞,如果至少有一个点在圆之外并且至少一点在圆内。

定义矩形并设置角点列表。此外,您还必须知道圆的半径:

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

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

计算Euclidean distance每个角点指向圆心 (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()

关于python - 检测pygame中文本框和圆圈之间的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58305721/

相关文章:

python - pygame 在退出()时仍然使用 .ttf 文件

c++ - 使用 QML 绘制图形项目的最佳方式是什么?

javascript - HTML5/Javascript 游戏开发 - 如果我有多个边界,则只有最新的边界有效

Python/Pandas - 基于多个条件的新列

python - 用空格填充列表元素给定最小长度

python - 是否可以在 python 中向导入的类添加属性?

c# - XNA C# 2D 平台游戏

在函数内部调用时字典理解中的 Python 名称错误

python - 不根据前 x 值插值绘制数据

python - Pygame,如何在屏幕上绘制形状并删除之前的表面?