3

我有一个以 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 度,围绕初始正方形旋转。问题在于,这是为了模仿物理玩具,因此不允许它与自身发生碰撞。我可以检查旋转后两个正方形是否相互重叠,但我如何确保它们在旋转过程中不会暂时碰撞?

4

6 回答 6

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

您需要对例外做一些有用的事情,但至少这会在您处理它时检查每个方块,并立即突破,而不是等到整个旋转之后才能验证它是否良好。

于 2013-10-22T16:46:27.657 回答
1

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

1. 使你的表面成为精灵
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)]

sprite 是您的方块之一。
组是所有其他方格。
该函数返回一个列表,其中所有方块都与您的方块发生碰撞。

于 2013-10-24T09:04:35.013 回答
0

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

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

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

如果您按正方形到枢轴正方形的距离对正方形进行排序,则不必检查所有对,只需检查距离内的对(从而避免 O(N^2))。

于 2013-10-18T23:23:44.307 回答
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 坐标。

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

于 2013-10-22T09:12:55.577 回答
0

您要做的是检查旋转矩形两侧所刻的两个四分之一圆之间的碰撞。要检查四分之一圆和矩形之间的碰撞,您可以尝试调整此代码

于 2013-10-15T19:52:19.237 回答
-1

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

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

对于包围圈,接下来的操作是测量每个包围圈之间的距离,并丢弃不可能重叠的那些。这是相当便宜的。还要注意,您可以丢弃反射。即,如果您测试了形状a 不能与形状b 重叠,那么现在不要测试形状b 是否与形状a 重叠。

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

于 2013-10-21T18:22:31.160 回答