PyGame中的collide_rect检测到不存在的碰撞

3

我对pygame和编程还是比较新的。我正在制作一个需要进行碰撞检测的游戏,但似乎出现了问题。每次运行程序时,它都会检测到不存在的碰撞。以下是我的代码片段:

class Player(pygame.sprite.Sprite):
    def __init__(self,x,y,width,height):
    pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.right = False
        self.left = False
        self.up = False
        self.down = False
        self.surf = pygame.Surface((50,50))
        self.rect = self.surf.get_rect()

    def draw(self):
        pygame.draw.rect(screen, (0,0,0), (self.x, self.y, self.width, self.height))

    def collision_test(self):
        if pygame.sprite.collide_rect(self, block1):
            print("a collision is detected")

以上是我的播放器类。
class Block1(pygame.sprite.Sprite):
    def __init__(self,x,y,width,height):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.surf = pygame.Surface((self.width,self.height))
        self.rect = self.surf.get_rect()

    def draw(self):
        pygame.draw.rect(screen, (150,150,150), (self.x, self.y, self.width, self.height))

这是我的障碍物类,它需要与我的玩家发生碰撞。我在碰撞检测中运行打印命令以进行调试。就像我说的那样,它只是不断地打印我给它的消息,即使它们没有发生碰撞。但是没有错误消息。谢谢提前任何帮助!
编辑:
我改变了collision_test方法并添加了block1参数。现在它是这个:
    def collision_test(self, block1):
        if pygame.sprite.collide_rect(self, block1):
            print("a collision is detected")

我的玩家和block1精灵是在主循环之前初始化的,它们看起来像这样:

player = Player(50,50,50,50)
block1 = Block1(200, 200, 100, 100)

我在mainloop的结尾处调用函数collision_test。如果需要,这是完整代码: https://pastebin.com/LTQdLMuV

你好!你的 collision_test(self) 方法没有接受任何 block1 参数。那个 block1 是从哪里来的?在代码中你是在哪里调用这个函数的?请添加你实例化类对象并使用它们的代码部分。 - Valentino
谢谢您的快速回复!我刚刚编辑了我的帖子。就像我说的,我是编码新手,因此也是stackoverflow的新手,所以我不确定您在编辑时是否会收到通知。 - Nolan Dailey
谢谢您的更新,我想我找到了问题所在。我会写在答案里。 - Valentino
1个回答

4
您忘记更新对象矩形的位置,导致问题出现。
pygame文档 中可以得知:

get_rect()
获取表面的矩形区域
get_rect(**kwargs)-> Rect
返回一个涵盖整个表面的新矩形。 此矩形始终以0, 0为起点,宽度和高度与图像大小相同。

在两个类中的PlayerBlock1都有一行代码:
self.rect = self.surf.get_rect()

要使用colliderect()方法,必须将rect属性更新为图像在屏幕上的位置(以像素为单位),否则您的draw()方法使用的坐标与用于检查碰撞的矩形不匹配。请改为:
self.rect = self.surf.get_rect().move(x, y)

因此,当对象被创建时,rect属性对应于对象在屏幕上的实际位置。

记得在移动玩家方块时更新player.rect的位置。也要编辑你的move_player()函数,例如添加:

player.rect.x = player.x
player.rect.y = player.y

因此,rect 对应于屏幕上的内容。

评论后编辑

如果您的目标是如何防止表面重叠,那就更加复杂。检测碰撞只是这个过程的一部分。完整的步骤如下:

  • 移动玩家对象。
  • 不仅检测是否发生碰撞,而且还要检测已碰撞的边缘。
  • 一旦检测到边缘,沿该轴将玩家对象向后移动。
  • 重新绘制。

那就是问题所在,谢谢!但我想我的问题描述可能不够具体...现在它已经能够检测到碰撞了,但是我该如何使用它来防止我的玩家重叠到block1中呢?我不知道如何将其制作成一个障碍物,使我的玩家无法通过。我认为我可能需要一种测试玩家重叠的哪一侧的方法,以便我可以立即将玩家移出block1。 - Nolan Dailey
那是一个完全不同的问题,可能对stackoverflow来说太过宽泛。我会在答案中添加一些提示。 - Valentino
尝试实施这些步骤,如果遇到困难,可以就该特定点提出问题。 - Valentino
好的,我认为我可以通过逻辑来解决它。谢谢。 - Nolan Dailey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接