Pygame 碰撞精度问题
Pygame colliderect precision issue
我正在为大学考试设计 Pacman 克隆版。
我使用 pygame,但在处理鬼影与墙壁的碰撞时遇到了一些问题。
例如鬼魂撞到左边的墙时,鬼魂矩形的左边取墙矩形右边的值:
rectGhost.left = blockRect.right
但是在多次碰撞之后(在墙的左边)鬼魂越过了墙,好像随着运动鬼魂矩形越过墙壁并且检测到碰撞到墙的左侧,然后移动到墙右边幻影矩形的左侧。
这是幽灵的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
我正在为大学考试设计 Pacman 克隆版。 我使用 pygame,但在处理鬼影与墙壁的碰撞时遇到了一些问题。
例如鬼魂撞到左边的墙时,鬼魂矩形的左边取墙矩形右边的值:
rectGhost.left = blockRect.right
但是在多次碰撞之后(在墙的左边)鬼魂越过了墙,好像随着运动鬼魂矩形越过墙壁并且检测到碰撞到墙的左侧,然后移动到墙右边幻影矩形的左侧。
这是幽灵的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