2015-08-28 125 views
1

我寫了一個小測試來感受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時,玩家仍然卡在岩石中。我也更新了代碼。

回答

1

你的答案被包含在你的問題..

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

所有的移動鍵,如果不是在碰撞只允許。一旦你在碰撞範圍內,你的移動動作都不被允許。

您必須允許遠離障礙物的移動鍵! 要做到這一點,你需要知道的衝突時有發生,其中.. (以字符的前面,左邊的字符等..)

編輯:從另一個答案

此編輯被列入inpsired,之後的答案被接受;) 的原因是該解決方案是更好的,不是檢查碰撞的方向,因爲它不要求你什麼計算..

的想法很簡單.. 總是試圖移動,並且只有當結果不會導致碰撞時,纔會應用它。

這將始終允許合法移動,並不會讓你卡住。

唯一需要注意的是非常小的障礙可能是「跳樓」,如果一個招步驟是較大的障礙一步..

檢查碰撞簡單的工作方式是先移動,檢查爲 碰撞並在必要時返回。

David Mašek

與此評論:

舉動返回一個新的矩形,所以你可以用它來檢查是否有衝突。如果有的話,什麼都不要做。如果沒有碰撞,請將player.rect設置爲新的矩形或(在player.rect上調用move_ip)。

sloth

+1

現在我覺得很愚蠢......你是對的 –

+0

@ Don'clickonmyprofile但是一旦你碰撞你已經在搖滾。這可能不是你想要的行爲,即使你稍後可以退出。 –

1

如果你的岩石不在5單位邊界,你可以移動「進入」岩石,然後卡住。

+0

我將移動速度重寫爲1並再次測試並再次卡住。我錯過了你的答案的重點? –

+0

@ Don'tclickonmyprofile:這很有趣。將該信息添加到您的原始問題。 –

+0

好吧我做到了:) –

3

你檢查,你沒有碰撞,然後移動。圖像你在岩石下面1個單位,你移動1個單位。你可以這樣做,因爲你沒有卡住現在。但現在你在搖滾,你不能移動

檢查碰撞的簡單和有效的方法是先移動,檢查碰撞並在必要時移回。

+0

您實際上不會*移回*,'move'會返回一個新的'Rect',因此您可以使用它來檢查碰撞。如果有的話,什麼都不要做。如果沒有碰撞,請將'player.rect'設置爲新的矩形或(在'player.rect'上調用'move_ip')。 – sloth

+0

@sloth我不是指在'Rect.move()'中移動,而是在「改變位置」(即動詞的正常含義)。 –

+0

這個答案+評論是一個好方法,我偷了它來編輯我的答案 – Henrik