Pygame检查碰撞不起作用

时间:2016-03-12 19:46:03

标签: python oop python-3.x pygame

我正在进行Snake游戏,我正试图探测蛇头和尾巴之间的碰撞。

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),就像我之前使用Snake Head和Food矩形一样,但它似乎不起作用。

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()

提前致谢!

1 个答案:

答案 0 :(得分: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()