在 pygame 中检测文本框和圆圈之间的碰撞
Detect collision between textbox and circle in pygame
我正在尝试在 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个角点。如果矩形是"smaller"则圆(圆的直径大于矩形的对角线),则矩形与圆的轮廓碰撞,如果至少有一个点在圆外并且至少有一点在圆圈内。
定义矩形并设置角点列表。此外,您还必须知道圆的半径:
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 中创建一个游戏,其中可以在屏幕上拖动一个文本框,但每当它触及周围圆圈的边界时,我希望循环重新开始,但是使用不同的文本(通过将所有文本字符串存储在列表中,但我还没有那么远)。这是我走了多远:
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个角点。如果矩形是"smaller"则圆(圆的直径大于矩形的对角线),则矩形与圆的轮廓碰撞,如果至少有一个点在圆外并且至少有一点在圆圈内。
定义矩形并设置角点列表。此外,您还必须知道圆的半径:
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()