2016-03-12 100 views
1

我正在做一個Snake遊戲,我試圖檢測蛇的頭部和尾部之間的碰撞。Pygame檢查碰撞不起作用

class Snake(): 
def __init__(self, screen, startx, starty, width, height, color): 
    self.screen = screen 
    self.startx = startx 
    self.starty = starty 
    self.width = width 
    self.height = height 
    self.color = color 
    self.amount_tiles = 5 
    self.tile = 0 
    self.position = [] 
    self.rect = pygame.Rect(startx, starty, width, height) #rectangle 1: Head of the Snake 
    pygame.draw.rect(screen, color, self.rect) 

-

def existing_tiles(self): 
    self.count = self.tile 

    while self.count > 0: 
     self.current_pos = self.position 
     x = self.current_pos[self.count - 1] 
     self.rect_new = pygame.Rect(x[0], x[1], self.width, self.height) #rectangle 2:Tail of the Snake 
     pygame.draw.rect(self.screen, GREEN, self.rect_new) 
     self.count = self.count - 1 

我嘗試使用pygame.Rect.colliderect(Rect1的,RECT2),因爲我與蛇頭和糧食矩形以前那樣,但它似乎並沒有工作。

Console output: AttributeError: 'Snake' object has no attribute 'rect_new' 

下面是完整的代碼:

import pygame 
import random 

RED = (255,0,0) 
WHITE = (255,255,255) 
GREEN = (0,255,0) 
BLUE = (0,128,255) 

#------------------------------FUNCTIONS--------------------------------# 
def main(): 

    pygame.init() 
    display_width=460 
    display_height=460 
    gameDisplay = pygame.display.set_mode((display_width, display_height)) 
    pygame.display.set_caption('Snake') 
    clock = pygame.time.Clock() 
    FPS = 10 

    schlange = Snake(gameDisplay, 220, 220, 20, 20, BLUE) 
    essen = Food(gameDisplay) 
    speed = (0,0) 

    while True: 
      #event loop 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       pygame.quit() 
       quit() 
      if event.type == pygame.KEYDOWN: 
       if event.key == pygame.K_UP: 
        speed = (0, -20) 
       if event.key == pygame.K_DOWN: 
        speed = (0, 20) 
       if event.key == pygame.K_LEFT: 
        speed = (-20, 0) 
       if event.key == pygame.K_RIGHT: 
        speed = (20, 0) 

     if pygame.Rect.colliderect(schlange.rect, essen.rect) == True: 
      essen = Food(gameDisplay) 
      schlange.eat() 

     if pygame.Rect.colliderect(schlange.rect, schlange.rect_new) == True: 
      print('rip') 
      pygame.quit() 
      quit() 


     schlange.move(speed[0], speed[1]) 
     essen.spawn() 
     clock.tick(FPS) 
     pygame.display.update() 

#------------------------------CLASSES---------------------------------# 
class Snake(): 
    def __init__(self, screen, startx, starty, width, height, color): 
     self.screen = screen 
     self.startx = startx 
     self.starty = starty 
     self.width = width 
     self.height = height 
     self.color = color 
     self.amount_tiles = 5 
     self.tile = 0 
     self.position = [] 
     self.rect = pygame.Rect(startx, starty, width, height) 
     pygame.draw.rect(screen, color, self.rect) 

    def move(self, x_change, y_change): 
     self.screen.fill(WHITE) 
     self.x_change = x_change 
     self.y_change = y_change 
     self.position.insert(0, (self.startx, self.starty)) 

     self.pos = self.position[self.tile] 

     '''self.add_tile()''' 
     self.existing_tiles() 

     self.startx += x_change 
     self.starty += y_change 
     self.rect = pygame.Rect(self.startx, self.starty, self.width, self.height) 
     pygame.draw.rect(self.screen, self.color, self.rect) 

    def existing_tiles(self): 
     self.count = self.tile 

     while self.count > 0: 
      self.current_pos = self.position 
      x = self.current_pos[self.count - 1] 
      self.rect_new = pygame.Rect(x[0], x[1], self.width, self.height) 
      pygame.draw.rect(self.screen, GREEN, self.rect_new) 
      self.count = self.count - 1 


    '''def add_tile(self): 
     x = self.pos[0] 
     y = self.pos[1] 
     pygame.draw.rect(self.screen, GREEN, (x, y, self.width, self.height))''' 

    def eat(self): 
     self.amount_tiles += 1 
     self.tile += 1 




class Food(): 

    def __init__(self, screen): 
     self.screen = screen 
     self.width = 20 
     self.height = 20 
     self.spawnx = random.randrange(0, 460, 20) 
     self.spawny = random.randrange(0, 460, 20) 
     self.rect = pygame.Rect(self.spawnx, self.spawny, self.width, self.height) 

    def spawn(self): 
     pygame.draw.rect(self.screen, RED, self.rect) 




if __name__ == '__main__': 
    main() 

提前感謝!

+0

您的錯誤是告訴你什麼是錯的。你的蛇對象不是一個矩形。 – Fredrik

回答

0

請嘗試下面您的遊戲的編輯版本。我做了兩個修改,並在代碼中寫了幾個註釋。

import pygame 
import random 

RED = (255,0,0) 
WHITE = (255,255,255) 
GREEN = (0,255,0) 
BLUE = (0,128,255) 

#------------------------------FUNCTIONS--------------------------------# 
def main(): 

    pygame.init() 
    display_width=460 
    display_height=460 
    gameDisplay = pygame.display.set_mode((display_width, display_height)) 
    pygame.display.set_caption('Snake') 
    clock = pygame.time.Clock() 
    FPS = 10 

    schlange = Snake(gameDisplay, 220, 220, 20, 20, BLUE) 
    essen = Food(gameDisplay) 
    speed = (0,0) 

    while True: 
      #event loop 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       pygame.quit() 
       quit() 
      if event.type == pygame.KEYDOWN: 
       if event.key == pygame.K_UP: 
        speed = (0, -20) 
       if event.key == pygame.K_DOWN: 
        speed = (0, 20) 
       if event.key == pygame.K_LEFT: 
        speed = (-20, 0) 
       if event.key == pygame.K_RIGHT: 
        speed = (20, 0) 

     if pygame.Rect.colliderect(schlange.rect, essen.rect) == True: 
      essen = Food(gameDisplay) 
      schlange.eat() 

     """ ADDED """ 

     """ I realized that you're storing the tail pieces in self.position. 
      Iterating through this list and checking for collisions seems to do the trick. 
      Skip check when there's only one element in schlange.position to avoid a collision as soon as the game starts. 
      Now you probably just need to prevent the snake from going straight back 
      into itself (180 degree turn) since that would trigger a collision that you might not want """ 

     if len(schlange.position) > 1: 
      for coords in schlange.position: 
       if pygame.Rect.colliderect(schlange.rect, pygame.Rect(coords[0], coords[1], schlange.width, schlange.height)) == True: 
        print('rip') 
        pygame.quit() 
        quit()    

     """ /ADDED """ 


     schlange.move(speed[0], speed[1]) 
     essen.spawn() 
     clock.tick(FPS) 
     pygame.display.update() 

#------------------------------CLASSES---------------------------------# 
class Snake(): 
    def __init__(self, screen, startx, starty, width, height, color): 
     self.screen = screen 
     self.startx = startx 
     self.starty = starty 
     self.width = width 
     self.height = height 
     self.color = color 
     self.amount_tiles = 5 
     self.tile = 0 
     self.position = [] 
     self.rect = pygame.Rect(startx, starty, width, height) 
     pygame.draw.rect(screen, color, self.rect) 

    def move(self, x_change, y_change): 
     self.screen.fill(WHITE) 
     self.x_change = x_change 
     self.y_change = y_change 
     self.position.insert(0, (self.startx, self.starty)) 

     self.pos = self.position[self.tile] 

     '''self.add_tile()''' 
     self.existing_tiles() 

     self.startx += x_change 
     self.starty += y_change 
     self.rect = pygame.Rect(self.startx, self.starty, self.width, self.height) 
     pygame.draw.rect(self.screen, self.color, self.rect) 


     """ ADDED """ 

     """ You kept adding to self.position but never deleted any elements. 
      That's unnecessary and would eventually cause a MemoryError """ 

     if len(self.position) > self.tile+1: 
      del self.position[-1] 

     """ /ADDED """ 

    def existing_tiles(self): 
     self.count = self.tile 

     while self.count > 0: 
      self.current_pos = self.position 
      x = self.current_pos[self.count - 1] 
      self.rect_new = pygame.Rect(x[0], x[1], self.width, self.height) 
      pygame.draw.rect(self.screen, GREEN, self.rect_new) 
      self.count = self.count - 1 


    '''def add_tile(self): 
     x = self.pos[0] 
     y = self.pos[1] 
     pygame.draw.rect(self.screen, GREEN, (x, y, self.width, self.height))''' 

    def eat(self): 
     self.amount_tiles += 1 
     self.tile += 1 




class Food(): 

    def __init__(self, screen): 
     self.screen = screen 
     self.width = 20 
     self.height = 20 
     self.spawnx = random.randrange(0, 460, 20) 
     self.spawny = random.randrange(0, 460, 20) 
     self.rect = pygame.Rect(self.spawnx, self.spawny, self.width, self.height) 

    def spawn(self): 
     pygame.draw.rect(self.screen, RED, self.rect) 




if __name__ == '__main__': 
    main() 
+0

我想知道爲什麼這是倒票。我在沒有意識到的情況下做了些什麼?爲了清晰和高效,代碼可能會被重寫,但這是OP的業務,因爲我看到它。 – jDo

+0

呵呵謝謝,別擔心:)很高興它的工作。我很新,並且從來沒有在pygame中寫過任何東西,除了在stackoverflow上的另一個答案,所以也許有一個合理的下調投票的原因,我只是太小白來意識到:D一個解釋會很好。好吧。無論如何,[我寫的其他pygame的答案](https://stackoverflow.com/questions/35728199/moving-a-sprite-to-the-other-side-when-a-sprite-moves-off-screen-pygame/35748930#35748930)可能實際上也與你有關。我記得Snake(或者是Snake 2?)擁有相同的「環繞」 - 這是OP要求的效果。 – jDo

+0

噢,是的,我要實施,無論是atlest還是atlest試着:D現在我不必提出一個新的問題,當我被困住了,謝謝:)還有一個問題,除了你所做的所有其他改進在我的代碼上。爲什麼我最初的想法不起作用? schlange.rect是一個矩形,schlange.rect_new是一個矩形。爲什麼沒有像上面的if語句那樣工作(如果pygame.Rect.colliderect(schlange.rect,essen.rect)== True :)? – Bobby