旋转时检测碰撞

时间:2013-10-15 19:45:18

标签: python algorithm pygame collision-detection

我有一个以pygame表示的正方形链。我有一些代码可以让我旋转链的一部分,如下所示。

#!/usr/bin/python
import pygame

def draw(square):
    (x,y) = square
    pygame.draw.rect(screen, black, (100+x*20,100+y*20,20,20), 1) 

def rotate(chain, index, direction):
    (pivotx, pivoty) = chain[index]
    if (direction == 1):
        newchain = chain[:index]+[(y-pivoty+pivotx, (x-pivotx)+pivoty) for (x,y) in chain[index:]]
    else:
        newchain = chain[:index]+[(y-pivoty+pivotx, -(x-pivotx)+pivoty) for (x,y) in chain[index:]]
    return newchain

pygame.init()

size = [600, 600]
screen = pygame.display.set_mode(size)
white = (255,255,255)
black = (0,0,0)

n = 20
chain = [(i,0) for i in xrange(n)]

screen.fill(white)
for square in chain:
    draw(square)

pygame.display.flip()
raw_input("Press Enter to continue...")
newchain = rotate(chain, 5, 1)
print chain
print newchain
screen.fill(white)
for square in newchain:
    draw(square)

pygame.display.flip()
raw_input("Press Enter to continue...")

screen.fill(white)
newchain = rotate(newchain, 10,0)
for square in newchain:
    draw(square)

pygame.display.flip()
raw_input("Press Enter to continue...")
pygame.quit()

函数rotate在链中取一个正方形的索引,并在该正方形之后旋转整个链90度,围绕初始正方形旋转。问题在于,这是为了模仿实体玩具,因此不允许它与自身发生碰撞。旋转后我可以检查两个方块是否在彼此的顶部,但是如何确保它们在旋转时不会暂时发生碰撞?

6 个答案:

答案 0 :(得分:1)

听起来你已经知道如果你做轮换后他们是否重叠,除非我误解。如果是这种情况,那么通过在理解结束时添加一个检查来定义一个函数来回答该问题是相对容易的,因为链中可能有一个旋转:

if (direction == 1):
    newchain = chain[:index]+[(y-pivoty+pivotx, (x-pivotx)+pivoty) for (x,y) in chain[index:] if not overlapping(x, y, pivotx, pivoty)]
else:
    newchain = chain[:index]+[(y-pivoty+pivotx, -(x-pivotx)+pivoty) for (x,y) in chain[index:] if not overlapping(x, y, pivotx, pivoty)]

当然还有某种依赖:

def overlapping(x, y, px, py):
    if (some logic that determins if this is bad):
        raise Exception('Overlapping')
    return True

你需要对异常做一些有用的事情,但至少这会在你处理时检查每个方格,并立即突破,而不是等到整个轮换之后才能确认它是好的。

答案 1 :(得分:1)

我会使用pygame函数来做到这一点。

1.使表面变为sprites 2.用pygame.transform.rotate旋转它们 3.检查与pygame函数的冲突 4.这个功能对我来说很完美;)。

def collision(sprite, group):
    rectCol = pygame.sprite.spritecollide(sprite, group, False)
    return [s for s in rectCol if pygame.sprite.collide_mask(sprite, s)]
精灵是你的方格之一 group是所有其他方块。
该函数返回一个列表,其中所有正方形与你的正方形碰撞。

答案 2 :(得分:0)

您需要做的是检查旋转矩形两侧的两个四分之一圆之间的碰撞。要检查四分之一圆和矩形之间的碰撞,您可以尝试调整this code

答案 3 :(得分:0)

如果出现以下情况,2个方格将在传输中重叠:

  • 一个是静止的,另一个是移动
  • 一个中心从另一个的左边开始,到右边(交叉产品将在这里使用)
  • 它们到枢轴方块的距离在一个范围内(由最远和最靠近枢轴方块的角确定)。

上面我提出了如何快速检查2个给定方块的想法。

如果按照距离枢轴方块的距离对方块进行排序,则不必检查所有对,只检查距离内的对(因此避免使用O(N ^ 2))。

答案 4 :(得分:0)

你可以做的一种方法是在圆圈之后对方块进行建模并使用关系

d = SQRT((X2-X1)^ 2 +(Y2-Y1)^ 2) (x1,y1),(x2,y2)是正方形的中心。

其中d是其中心之间的最小距离。然后将它与r1 + r2进行比较,其中r1和r2是居住在正方形中的圆的半径。如果d小于r1 + r2,则反转它们的单位速度矢量,或使它们反向旋转。

您可以通过测试一个正方形的顶点与另一个正方形的对角线来提高模型的精确度。例如(请用方格纸看这个),比如我们有一个方形A,顶点是[(2,0),(0,2),(2,4),(4,2)],另一个(方形B)是[(2,2),(5,2),(5,5),(2,5)],现在取任何一个方格(我们将取B)并取任何一个顶点比方说,(2,2)。测试x坐标(2)是否位于A的对角线对齐顶点的x坐标之间,比如(2,4)和(2,0)。显然它确实如此!然后我们检查另一个对角线,(0,2)和(4,2)。它也是!因此,方形B与方形A碰撞,旋转矢量或速度矢量必须反转。您也可以查看y-coords。

你必须遍历每个方块以检查它们是否与其他方碰撞。但是,您不必检查所有方块,因为您只需要关注最小距离d小于r1 + r2相对于彼此的方块,因此您只需要一个循环来检查它们的距离是否为小于半径的总和,另一个循环来检查它们的顶点是否已进入正方形的主体。我通常在我的游戏中那样刺激粒子的随机运动(例如布朗运动)

答案 5 :(得分:-1)

这个问题已经被多次解决了。最简单的解释是您使用越来越多的细节。

对于形状本身,您必须创建边界框或边界圆,这些圆足够大以包含形状中最外面的点。边界圆很好,因为它是最小的形状,总是完全覆盖对象。它也不需要在旋转后重新生成,因为它总是描述您的形状可能的最大空间。

对于边界圆,下一个操作是测量每个边界圆之间的距离,并丢弃那些不可能重叠的边界圆。这相当便宜。另请注意,您可以放弃反射。即如果您测试的形状不能与形状b重叠,请不要测试形状b是否与形状a重叠。

一旦你有“可能”重叠的形状,你必须使用精确的算法来查看一个形状中的任何点是否与另一个形状中的任何点重叠。有很多种方法可以做到这一点。其中一些是几何的(GJK Algorithm),而另一些则使用像z缓冲区或像素掩码之类的东西。对于后一类,您可以将一个形状绘制到测试缓冲区,然后开始绘制第二个形状。如果在绘制像素之前检查缓冲区并看到已存在像素,则表示存在交叉点(碰撞)。