pygame中的碰撞检测

问题描述:

我写了一个小测试来感受pygame中的碰撞检测。我的球员正确地移动并停在发生碰撞的岩石上,但是当我到达岩石时,我不能再离开。你们知道这是为什么吗?这是我的测试代码:pygame中的碰撞检测

import pygame 
import sys 

white = (255, 255, 255) 
black = ( 0, 0, 0) 


# Player class 
class Player(pygame.sprite.Sprite): 
    def __init__(self): 
     super().__init__() 
     self.image = pygame.image.load('../foo.png') 
     self.rect = self.image.get_rect() 


class Rock(pygame.sprite.Sprite): 
    def __init__(self): 
     super().__init__() 
     self.image = pygame.image.load('../rock.png') 
     self.rect = self.image.get_rect() 
     self.rect.x = 50 
     self.rect.y = 50 

# essential pygame init 
pygame.init() 

# screen 
screen_width = 400 
screen_height = 400 
screen_size = (screen_width, screen_height) 
screen = pygame.display.set_mode(screen_size) 

# List for all sprites 
sprites = pygame.sprite.Group() 


# Rock 
rock = Rock() 
sprites.add(rock) 

# Create player 
player = Player() 
sprites.add(player) 

done = False 

clock = pygame.time.Clock() 
while not done: 

    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      sys.exit() 
      sys.exit() 

    sprites.update() 

    pressed = pygame.key.get_pressed() 
    if pressed[pygame.K_LEFT] and not player.rect.colliderect(rock.rect): 
     #if not player.rect.colliderect(rock.rect): 
     move = (-1, 0) 
     player.rect = player.rect.move(move) 
    if pressed[pygame.K_RIGHT] and not player.rect.colliderect(rock.rect): 
     move = (1, 0) 
     player.rect = player.rect.move(move) 
    if pressed[pygame.K_UP] and not player.rect.colliderect(rock.rect): 
     move = (0, -1) 
     player.rect = player.rect.move(move) 
    if pressed[pygame.K_DOWN] and not player.rect.colliderect(rock.rect): 
     move = (0, 1) 
     player.rect = player.rect.move(move) 

    screen.fill(white) 

    sprites.draw(screen) 

    pygame.display.flip() 

    clock.tick(30) 

pygame.quit() 

编辑:当我将移动速度降低到1时,玩家仍然卡在岩石中。我也更新了代码。

你的答案被包含在你的问题..

if .... . and not player.rect.colliderect(rock.rect): 

所有的移动键,如果不是在碰撞只允许。一旦你在碰撞范围内,你的移动动作都不被允许。

您必须允许远离障碍物的移动键! 要做到这一点,你需要知道的冲突时有发生,其中.. (以字符的前面,左边的字符等..)

编辑:从另一个答案

此编辑被列入inpsired,之后的答案被接受;) 的原因是该解决方案是更好的,不是检查碰撞的方向,因为它不要求你什么计算..

的想法很简单.. 总是试图移动,并且只有当结果不会导致碰撞时,才会应用它。

这将始终允许合法移动,并不会让你卡住。

唯一需要注意的是非常小的障碍可能是“跳楼”,如果一个招步骤是较大的障碍一步..

检查碰撞简单的工作方式是先移动,检查为 碰撞并在必要时返回。

David Mašek

与此评论:

举动返回一个新的矩形,所以你可以用它来检查是否有冲突。如果有的话,什么都不要做。如果没有碰撞,请将player.rect设置为新的矩形或(在player.rect上调用move_ip)。

sloth

+1

现在我觉得很愚蠢......你是对的 –

+0

@ Don'clickonmyprofile但是一旦你碰撞你已经在摇滚。这可能不是你想要的行为,即使你稍后可以退出。 –

如果你的岩石不在5单位边界,你可以移动“进入”岩石,然后卡住。

+0

我将移动速度重写为1并再次测试并再次卡住。我错过了你的答案的重点? –

+0

@ Don'tclickonmyprofile:这很有趣。将该信息添加到您的原始问题。 –

+0

好吧我做到了:) –

你检查,你没有碰撞,然后移动。图像你在岩石下面1个单位,你移动1个单位。你可以这样做,因为你没有卡住现在。但现在你在摇滚,你不能移动

检查碰撞的简单和有效的方法是先移动,检查碰撞并在必要时移回。

+0

您实际上不会*移回*,'move'会返回一个新的'Rect',因此您可以使用它来检查碰撞。如果有的话,什么都不要做。如果没有碰撞,请将'player.rect'设置为新的矩形或(在'player.rect'上调用'move_ip')。 – sloth

+0

@sloth我不是指在'Rect.move()'中移动,而是在“改变位置”(即动词的正常含义)。 –

+0

这个答案+评论是一个好方法,我偷了它来编辑我的答案 – Henrik