2016-03-12 32 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