Pygame 碰撞精度问题

Pygame colliderect precision issue

我正在为大学考试设计 Pacman 克隆版。 我使用 pygame,但在处理鬼影与墙壁的碰撞时遇到了一些问题。

例如鬼魂撞到左边的墙时,鬼魂矩形的左边取墙矩形右边的值:

rectGhost.left = blockRect.right

但是在多次碰撞之后(在墙的左边)鬼魂越过了墙,好像随着运动鬼魂矩形越过墙壁并且检测到碰撞到墙的左侧,然后移动到墙右边幻影矩形的左侧。

Collision issue example

这是幽灵的class:

import character, random
from globalVar import *

class ghost(character.character):

    def __init__(self, imgSprite):
        super(ghost, self).__init__(imgSprite)
        self._direction = random.choice([LEFT, RIGHT, UP, DOWN])

    def catch(self, wall):

        # Keep the direction 
        if self._direction ==  LEFT:
            self.moveToLeft()
        if self._direction ==  RIGHT:
            self.moveToRight()
        if self._direction ==  UP:
            self.moveToUp()
        if self._direction ==  DOWN:
            self.moveToDown()


        # Get ghost position
        rectGhost = self.getRectSprite()

        # Collision with wall
        for blockRect in wall:
            if rectGhost.colliderect(blockRect): # Check collision with the wall (wall contain a list of Rect object)

                if self._direction ==  LEFT:
                    rectGhost.left = blockRect.right 
                    self._direction = random.choice([RIGHT, UP, DOWN]) 

                if self._direction ==  RIGHT:
                    rectGhost.right = blockRect.left 
                    self._direction = random.choice([LEFT, UP, DOWN]) 

                if self._direction ==  UP:
                    rectGhost.top = blockRect.bottom 
                    self._direction = random.choice([LEFT, RIGHT, DOWN]) 

                if self._direction ==  DOWN:
                    rectGhost.bottom = blockRect.top 
                    self._direction = random.choice([LEFT, RIGHT, UP]) 

这就是超级class人物:

from globalVar import *

class character:

    def __init__(self, imgSprite):
        self._imageSprite = imgSprite
        self._spriteRect = self._imageSprite.get_rect() 
        self._dimStep = 10 
        self._direction = 0

    def setCharPos(self, charPos): 
        self._spriteRect.centerx = charPos[0]
        self._spriteRect.centery = charPos[1]


    def moveToLeft(self):
        self._spriteRect.x -= self._dimStep 


    def moveToRight(self):
        self._spriteRect.x += self._dimStep


    def moveToUp(self):
        self._spriteRect.y -= self._dimStep


    def moveToDown(self):
        self._spriteRect.y += self._dimStep


    def drawSprite(self):
        WINDOWSURF.blit(self._imageSprite, self._spriteRect)


    def getRectSprite(self):
        return self._spriteRect

    def setDirection(self, direction):
        self._direction = direction

这是主要的:

def main():

    thisPacman = pacman.pacman(pacmanCImg) # Ghot obj

    thisGhost_a = ghost.ghost(ghostAImg) # Ghot obj

    thisGhost_o = ghost.ghost(ghostOImg) # Ghot obj

    thisGhost_p = ghost.ghost(ghostPImg) # Ghot obj

    thisGhost_r = ghost.ghost(ghostRImg) # Ghot obj

    # Coords of wall
    wall = thisLevel.getBlocksListPos()

    # Coords of Ghosts
    ghostsStartPos = thisLevel.getGhostsPos()

    # Start pos azure
    thisGhost_a.setCharPos(ghostsStartPos[0])

    # Start pos ghost orange
    thisGhost_o.setCharPos(ghostsStartPos[1])

    # Start pos ghost purple
    thisGhost_p.setCharPos(ghostsStartPos[2])

    # Start pos ghost red
    thisGhost_r.setCharPos(ghostsStartPos[3])

    while running:

        thisGhost_a.catch(wall)
        thisGhost_o.catch(wall)
        thisGhost_p.catch(wall)
        thisGhost_r.catch(wall)

        thisGhost_a.drawSprite()
        thisGhost_o.drawSprite()
        thisGhost_p.drawSprite()
        thisGhost_r.drawSprite()

        pygame.display.update()
        FPSCLOCK.tick(8)

有什么想法吗? 非常感谢您的关注!

在不熟悉您的代码的情况下,我发现很难给您答案。但是,您可以尝试从 catch() 方法调试代码:

# Collision with wall
import pdb; pdb.set_trace()

这可能会为您提供有关正在发生的事情的更多信息。

我还注意到您的 catch() 方法中的 if 语句出现在 幽灵运动之后。在允许移动之前,这些肯定需要检查碰撞吗?

正如 David Jay Bredy 所解释的那样,解决方案就在这里。

撞墙

        #pdb.set_trace() # Debugging

        for blockRect in wall:
            if rectGhost.colliderect(blockRect): 

                while 1:# Cycle that solve the problem
                    if self._direction ==  LEFT:
                        rectGhost.left = blockRect.right
                        self._direction = random.choice([RIGHT, UP, DOWN])
                        break

                    if self._direction ==  RIGHT:
                        rectGhost.right = blockRect.left
                        self._direction = random.choice([LEFT, UP, DOWN]
                        break

                    if self._direction ==  UP:
                        rectGhost.top = blockRect.bottom
                        self._direction = random.choice([LEFT, RIGHT, DOWN]
                        break 

                    if self._direction ==  DOWN:
                        rectGhost.bottom = blockRect.top
                        self._direction = random.choice([LEFT, RIGHT, UP])
                        break