使用Pygame在Snake游戏中让我的蛇体跟随头部

时间:2018-12-13 19:18:21

标签: python pygame

我正在编写我的第一个pygame程序,并试图创建一个Snake游戏。我拥有的当前代码几乎可以完全正常运行,但是弯折的蛇是有缺陷的。我要做的是在按下方向键时存储蛇头的位置,并且一旦它们的坐标等于存储的头坐标,就基本上改变了Snake对象列表中每个块的坐标。照原样,一旦我单击方向键,蛇就会变成一个单独的块。我认为这是因为蛇没有连续运动。我需要连续单击方向键以使蛇移动。我的代码可能不是最干净/最好的实现,但是我现在可以这样做。这是整个代码的链接-https://github.com/Denizhan-Yigitbas/Snake

这是我的Snake课,基本上使身体部位:

import pygame


class Snake(pygame.sprite.Sprite):
    # TODO: Make Snake a chain of Blocks
    def __init__(self, color, width, height, positionX, positionY):
        # Call the parent class (Sprite) constructor
        pygame.sprite.Sprite.__init__(self)

        # Create an image of the block, and fill it with a color.
        # This could also be an image loaded from the disk.
        self.image = pygame.Surface([width, height])
        self.image.fill(color)

        # Fetch the rectangle object that has the dimensions of the image
        # Update the position of this object by setting the values of rect.x and rect.y
        self.rect = self.image.get_rect()

        # set the position of the snake
        self.rect.x = positionX
        self.rect.y = positionY

        # set the inputs the usable variables for later code
        self.color = color
        self.width = width
        self.height = height


    """
    Method the will change the direction of the Snake towards the left
    """
    def moveLeft(self):
        newX = self.rect.x - 10
        return Snake(self.color, self.width, self.height, newX, self.rect.y)

    """
    Method that will change the direction of the Snake toward the right
    """
    def moveRight(self):
        newX = self.rect.x + 10
        return Snake(self.color, self.width, self.height, newX, self.rect.y)

    """
    Method that will change the direction of the Snake to go upward
    """
    def moveUp(self):
        newY = self.rect.y - 10
        return Snake(self.color, self.width, self.height, self.rect.x, newY)

    """
    Method that will change the direction of the Snake to go downward
    """
    def moveDown(self):
        newY = self.rect.y + 10
        return Snake(self.color, self.width, self.height, self.rect.x, newY)

这是我的食品课:

import pygame
import random

"""
Class to create a Food at a random coordinate
"""


class Food(pygame.sprite.Sprite):
    def __init__(self, color, width, height):
        # Call the parent class (Sprite) constructor
        pygame.sprite.Sprite.__init__(self)

        # Create an image of the block, and fill it with a color.
        # This could also be an image loaded from the disk.
        self.image = pygame.Surface([width, height])
        self.image.fill(color)

        # Fetch the rectangle object that has the dimensions of the image
        # Update the position of this object by setting the values of rect.x and rect.y
        self.rect = self.image.get_rect()

        # set the position of the Food
        # TODO: change values in randint to use the input width and height
        randX = random.randint(0, 39) * 10
        randY = random.randint(0, 39) * 10
        self.rect.x = randX
        self.rect.y = randY

这是我运行游戏的App类:

import pygame


from pygame.locals import *
from Classes.Snake import *
from Classes.Food import *
from Classes.Block import *

RED = (255, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)


class App:

    def __init__(self):
        self._running = True
        self._display_surf = None
        self.size = self.weight, self.height = 400, 400

        # Initial Snake array with 3 Snake Blocks starting at (50, 50) and going left
        self.snake = [Snake(WHITE, 10, 10, 50, 50), Snake(WHITE, 10, 10, 40, 50), Snake(WHITE, 10, 10, 30, 50)]

    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
        self._display_surf.fill(BLACK)
        self._running = True

        # Create Score Board
        self.score = 0
        self.displayScore(self.score, 30)

        # Create Initial Food
        self.initFood = Food(RED, 10, 10)
        self._display_surf.blit(self.initFood.image, self.initFood.rect)

        # display the initial Snake array
        for i in range(len(self.snake)):
            self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
        pygame.display.update()

    """
    Helper Method that will run the events that are clicked on by the user
    """

    def on_event(self):

        # Checks if Snake crashes with itself - LOSE
        for i in range(1, len(self.snake)):
            if pygame.sprite.collide_rect(self.snake[0], self.snake[i]):
                pygame.quit()

        # Checks if Snake goes off the board
        if self.snake[0].rect.x == -10 or self.snake[0].rect.x == 400:
            self.message_display("LOSE")
            # pygame.quit()
        if self.snake[0].rect.y == -10 or self.snake[0].rect.y == 400:
            pygame.quit()

        # Checks if Snake eats Food - LOSE
        if pygame.sprite.collide_rect(self.snake[0], self.initFood):
            # Erases the current screen
            self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
            self._display_surf.fill(BLACK)

            # Create a new Food at random location and display it
            self.initFood = Food(RED, 10, 10)

            # Create Score Board
            self.score += 1
            self.displayScore(self.score, 30)

            # Store the last and second to last blocks of the snake
            lastSnakeBlock = self.snake[-1]
            secondToLastBlock = self.snake[-2]

            # if the last two blocks are on the same horizontal line and the last block is to the left of the
            # second to last block, add a block to the left side of the last block
            if lastSnakeBlock.rect.y == secondToLastBlock.rect.y and lastSnakeBlock.rect.x < secondToLastBlock.rect.x:
                newX = lastSnakeBlock.rect.x - 10
                newSnakeBlock = Snake(lastSnakeBlock.color, lastSnakeBlock.width, lastSnakeBlock.height, newX,
                                      lastSnakeBlock.rect.y)
                self.snake.append(newSnakeBlock)

            # if the last two blocks are on the same horizontal line and the last block is to the right of the
            # second to last block, add a block to the right side of the last block
            if lastSnakeBlock.rect.y == secondToLastBlock.rect.y and lastSnakeBlock.rect.x > secondToLastBlock.rect.x:
                newX = lastSnakeBlock.rect.x + 10
                newSnakeBlock = Snake(lastSnakeBlock.color, lastSnakeBlock.width, lastSnakeBlock.height, newX,
                                      lastSnakeBlock.rect.y)
                self.snake.append(newSnakeBlock)

            # if the last two blocks are on the same vertical line and the last block is above the
            # second to last block, add a block above the last block
            if lastSnakeBlock.rect.x == secondToLastBlock.rect.x and lastSnakeBlock.rect.y < secondToLastBlock.rect.y:
                newY = lastSnakeBlock.rect.y - 10
                newSnakeBlock = Snake(lastSnakeBlock.color, lastSnakeBlock.width, lastSnakeBlock.height,
                                      lastSnakeBlock.rect.x, newY)
                self.snake.append(newSnakeBlock)

            # if the last two blocks are on the same vertical line and the last block is below the
            # second to last block, add a block below the last block
            if lastSnakeBlock.rect.x == secondToLastBlock.rect.x and lastSnakeBlock.rect.y > secondToLastBlock.rect.y:
                newY = lastSnakeBlock.rect.y + 10
                newSnakeBlock = Snake(lastSnakeBlock.color, lastSnakeBlock.width, lastSnakeBlock.height,
                                      lastSnakeBlock.rect.x, newY)
                self.snake.append(newSnakeBlock)

            for i in range(len(self.snake)):
                self._display_surf.blit(self.snake[i].image, self.snake[i].rect)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self._running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    print("LEFT")

                    xCoord = self.snake[0].rect.x
                    yCoord = self.snake[0].rect.y

                    # Reset the Board
                    self.boardReset()

                    # Store the length of the snake
                    currentLength = len(self.snake)

                    # Loop to make points follow the head
                    for i in range(len(self.snake)):
                        if self.snake[i].rect.x == xCoord and self.snake[i].rect.y == yCoord:
                            newSnake = self.snake[i].moveLeft()

                            # append new Snake into list instead of old
                            self.snake.append(newSnake)

                    # removes old snake blocks
                    for i in range(currentLength):
                        self.snake.pop(0)

                    # displays the shifted snake Blocks
                    for i in range(len(self.snake)):
                        self._display_surf.blit(self.snake[i].image, self.snake[i].rect)

                if event.key == pygame.K_RIGHT:
                    print("RIGHT")

                    # # get the coordinates of the head of the Snake
                    xCoord = self.snake[0].rect.x
                    yCoord = self.snake[0].rect.y

                    # Reset the Board
                    self.boardReset()

                    # Store the length of the snake
                    currentLength = len(self.snake)

                    # Loop to make points follow the head
                    for i in range(len(self.snake)):
                        if self.snake[i].rect.x == xCoord and self.snake[i].rect.y == yCoord:
                            newSnake = self.snake[i].moveRight()

                            # append new Snake into list instead of old
                            self.snake.append(newSnake)

                    # removes old snake blocks
                    for i in range(currentLength):
                        self.snake.pop(0)

                    # displays the shifted snake Blocks
                    for i in range(len(self.snake)):
                        self._display_surf.blit(self.snake[i].image, self.snake[i].rect)

                if event.key == pygame.K_UP:
                    # # get the coordinates of the head of the Snake
                    xCoord = self.snake[0].rect.x
                    yCoord = self.snake[0].rect.y

                    # Reset the board
                    self.boardReset()

                    # Store the length of the snake
                    currentLength = len(self.snake)

                    # Loop to make points follow the head
                    for i in range(len(self.snake)):
                        if self.snake[i].rect.x == xCoord and self.snake[i].rect.y == yCoord:
                            newSnake = self.snake[i].moveUp()

                            # append new Snake into list instead of old
                            self.snake.append(newSnake)

                    # removes old snake blocks
                    for i in range(currentLength):
                        self.snake.pop(0)

                    # displays the shifted snake Blocks
                    for i in range(len(self.snake)):
                        self._display_surf.blit(self.snake[i].image, self.snake[i].rect)

                if event.key == pygame.K_DOWN:
                    # get the coordinates of the head of the Snake
                    xCoord = self.snake[0].rect.x
                    yCoord = self.snake[0].rect.y

                    # Reset the Board
                    self.boardReset()

                    # Store the length of the snake
                    currentLength = len(self.snake)

                    for i in range(len(self.snake)):
                        if self.snake[i].rect.x == xCoord and self.snake[i].rect.y == yCoord:
                            newSnake = self.snake[i].moveDown()

                            # append new Snake into list instead of old
                            self.snake.append(newSnake)

                    # removes old snake blocks
                    for i in range(currentLength):
                        self.snake.pop(0)

                    # displays the shifted snake Blocks
                    for i in range(len(self.snake)):
                        self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
        pygame.display.update()

    """
    Helper method that displays the current score on the screen.
    """

    def displayScore(self, score, size):
        font = pygame.font.SysFont("Comic Sans MS", size)
        ScoreBoard = font.render("SCORE: {}".format(score), False, (WHITE))
        self._display_surf.blit(ScoreBoard, [0, 0])
        pygame.display.update()

    """
    Helper method that will reset the screen:

    Make screen Black
    Add the current Food block
    Add the current Score
    """

    def boardReset(self):
        # Erases the current screen
        self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
        self._display_surf.fill(BLACK)

        # Create Score Board
        self.displayScore(self.score, 30)

        # Add Food
        self._display_surf.blit(self.initFood.image, self.initFood.rect)

    def text_objects(self, text, font):
        textSurface = font.render(text, True, BLACK)
        return textSurface, textSurface.get_rect()

    def message_display(self, text):
        largeText = pygame.font.Font('freesansbold.ttf', 115)
        TextSurf = largeText.render(text, True, BLACK)
        TextRect = TextSurf.get_rect()
        # TextSurf, TextRect = text_objects(text, largeText)
        TextRect.center = ((self.weight / 2), (self.height / 2))
        self._display_surf.blit(TextSurf, TextRect)
        pygame.display.update()

    def on_loop(self):
        pass

    def on_render(self):
        pass

    def on_cleanup(self):
        pygame.quit()

    """
    Game Loop
    """

    def on_execute(self):
        if self.on_init() == False:
            self._running = False

        while (self._running):
            self.on_event()
            self.on_loop()
            self.on_render()
        self.on_cleanup()


if __name__ == "__main__":
    theApp = App()
    theApp.on_execute()

0 个答案:

没有答案