PyGame窗口无法启动

时间:2020-04-19 23:02:21

标签: python pygame 2d-games pygame-surface

我前一段时间创建了这个简单的蛇游戏,我想尝试运行它,由于某种原因,窗口没有在我的机器上启动。我确定代码之前可以正常工作。我尝试调试了一段时间,但似乎无法弄清为什么我被卡在黑屏上。似乎检测到按键被按下,但屏幕上没有任何显示。

import pygame
from pygame.locals import *
import random

# Global Color Variables
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
CYAN = (0,255, 255)

# Set the speed of the Snake --> lower = faster
timeDelaySpeed = 0

class App:
    def __init__(self):
        self._running = True
        self._display_surf = None
        self.size = self.weight, self.height = 600, 700

        # create the boarder
        self.boarder = self.generateBoard()

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


    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, 45)

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

        # display the board
        for i in range(len(self.boarder)):
            self._display_surf.blit(self.boarder[i].image, self.boarder[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[1]):
                self.spaceToRestartText(20)
                self.gameRestart()
            if pygame.sprite.collide_rect(self.snake[0], self.snake[i]):
                self.spaceToRestartText(20)
                self.gameRestart()

        # Check if Snake hits the boarder - LOSE
        for i in range(len(self.boarder)):
            if pygame.sprite.collide_rect(self.snake[0], self.boarder[i]):
                self.spaceToRestartText(20)
                self.gameRestart()

        # Checks if Snake eats Food 
        if pygame.sprite.collide_rect(self.snake[0], self.initFood):
            self.eatFood()

        # set the direction based of key that is pressed
        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:
                    # check for self collision before eating any food - weird collision method error fix
                    if self.move == 'right':
                        self.spaceToRestartText(20)
                        self.gameRestart()
                        break
                    self.move = 'left'

                if event.key == pygame.K_RIGHT:
                    # check for self collision before eating any food
                    if self.move == 'left':
                        self.spaceToRestartText(20)
                        self.gameRestart()
                        break
                    self.move = 'right'

                if event.key == pygame.K_UP:
                    # check for self collision before eating any food
                    if self.move == 'down':
                        self.spaceToRestartText(20)
                        self.gameRestart()
                        break
                    self.move = 'up'

                if event.key == pygame.K_DOWN:
                    # check for self collision before eating any food
                    if self.move == 'up':
                        self.spaceToRestartText(20)
                        self.gameRestart()
                        break
                    self.move = 'down'

        # if stored current direction is right           
        if self.move == 'right':
            print("RIGHT")

            # Reset the Board
            self.boardReset()

            # Store the current head of the snake
            snakeHead = self.snake[0]

            # remove the last block of the snake
            self.snake.pop()

            # create a new head for the snake that is shifted toward the right
            newHead = snakeHead.moveRight()

            # add the newly created head to the front of the list - make head
            self.snake.insert(0, newHead)

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

            pygame.time.delay(timeDelaySpeed)

        # if stored current direction is left
        if self.move == 'left':
            print("LEFT")

            # Reset the Board
            self.boardReset()

            # Store the current head of the snake
            snakeHead = self.snake[0]

            # remove the last block of the snake
            self.snake.pop()

            # create a new head for the snake that is shifted toward the right
            newHead = snakeHead.moveLeft()

            # add the newly created head to the front of the list - make head
            self.snake.insert(0, newHead)

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

            pygame.time.delay(timeDelaySpeed)

        # if stored current direction is up
        if self.move == 'up':
            print("UP")

            # Reset the Board
            self.boardReset()

            # Store the current head of the snake
            snakeHead = self.snake[0]

            # remove the last block of the snake
            self.snake.pop()

            # create a new head for the snake that is shifted toward the right
            newHead = snakeHead.moveUp()

            # add the newly created head to the front of the list - make head
            self.snake.insert(0, newHead)

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

            pygame.time.delay(timeDelaySpeed)

        # if stored current direction is down
        if self.move == 'down':
            print("DOWN")

            # Reset the Board
            self.boardReset()

            # Store the current head of the snake
            snakeHead = self.snake[0]

            # remove the last block of the snake
            self.snake.pop()

            # create a new head for the snake that is shifted toward the right
            newHead = snakeHead.moveDown()

            # add the newly created head to the front of the list - make head
            self.snake.insert(0, newHead)

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

            pygame.time.delay(timeDelaySpeed)


    """
    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, [90, 100])
        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, 45)

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

        # Add Boarder
        for i in range(len(self.boarder)):
            self._display_surf.blit(self.boarder[i].image, self.boarder[i].rect)


    """
    Eating food helper method
    """
    def eatFood(self):
        # Create a new Food at random location and display it
        self.initFood = Food(RED, 10, 10)
        self._display_surf.blit(self.initFood.image, self.initFood.rect)

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

        # for i in range(len(self.snake)):
        #     self._display_surf.blit(self.snake[i].image, self.snake[i].rect)
        #
        # 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)


    """
    Takes the player back to initial start state
    """
    def gameRestart(self):
        # Erase the Board
        self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
        self._display_surf.fill(BLACK)
        self._running = True

        # Recreate the Snake
        self.snake = [Snake(WHITE, 10, 10, 150, 260), Snake(WHITE, 10, 10, 140, 260), Snake(WHITE, 10, 10, 130, 260)]

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

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

        # set current move to nothing
        self.move = ''

        # draw in the boarder
        for i in range(len(self.boarder)):
            self._display_surf.blit(self.boarder[i].image, self.boarder[i].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()


    """
    Creates a List of Blocks that outline the Boarder of the snake game
    """
    def generateBoard(self):
        boardCorners = []
        boardTop = []
        boardSide1 = []
        boardSide2 = []
        boardBottom = []

        # Makes (0,0) of board = (100, 210)
        # top left corner
        boardCorners.append(Snake(CYAN, 10, 10, 90, 200))

        # top right corner
        boardCorners.append(Snake(CYAN, 10, 10, 500, 200))

        # bottom left corner
        boardCorners.append(Snake(CYAN, 10, 10, 90, 610))

        # bottom right corner
        boardCorners.append(Snake(CYAN, 10, 10, 500, 610))

        # top and bottom sides
        topCoord = 100
        for i in range(40):
            boardTop.append(Snake(CYAN, 10, 10, topCoord, 200))
            boardBottom.append(Snake(CYAN, 10, 10, topCoord, 610))
            topCoord += 10

        # sides of board
        sideCoord = 210
        for i in range(40):
            boardSide1.append(Snake(CYAN, 10, 10, 90, sideCoord))
            boardSide2.append(Snake(CYAN, 10, 10, 500, sideCoord))
            sideCoord += 10

        # combine all parts
        allBoarder = boardCorners + boardTop + boardSide1 + boardSide2 + boardBottom

        # return list of blocks
        return allBoarder


    """
    Allows player to restart a game by pressing space bar - displays losing screen
    """
    def spaceToRestartText(self, size):
        self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
        self._display_surf.fill(BLACK)
        self.youLoseText(50)
        self.yourScoreText(25)
        font = pygame.font.SysFont("Comic Sans MS", size)
        text_surface = font.render("Press space bar to play again", True, WHITE)
        text_rect = text_surface.get_rect(center=(self.weight / 2, self.height / 2))
        self._display_surf.blit(text_surface, text_rect)
        pygame.display.flip()
        done = False
        while not done:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                    done = True
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        done = True


    """
    Helper function that prints 'YOU LOSE!'
    """
    def youLoseText(self, size):
        font = pygame.font.SysFont("Comic Sans MS", size)
        text_surface = font.render("YOU LOSE!", True, WHITE)
        # Shift height up so no collision with space bar text
        text_rect = text_surface.get_rect(center=(self.weight / 2, (self.height / 2) - 75))
        self._display_surf.blit(text_surface, text_rect)
        pygame.display.flip()


    """
    Helper function that prints your score at loss
    """
    def yourScoreText(self, size):
        font = pygame.font.SysFont("Comic Sans MS", size)
        text_surface = font.render("Your Score was: " + str(self.score), True, WHITE)
        # Shift height up so no collision with space bar text
        text_rect = text_surface.get_rect(center=(self.weight / 2, (self.height / 2) - 35))
        self._display_surf.blit(text_surface, text_rect)
        pygame.display.flip()


    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

        self.move = ''
        while (self._running):
            self.on_event()
            self.on_loop()
            self.on_render()
        self.on_cleanup()


"""
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(10,49) * 10
        randY = random.randint(21,60) * 10
        self.rect.x = randX
        self.rect.y = randY

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)


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

enter image description here

2 个答案:

答案 0 :(得分:0)

代码还可以,可以在我的机器上工作。 您可以添加命令提示符的屏幕截图吗?

答案 1 :(得分:0)

我可以同意以上答案。唯一的问题似乎是您没有设置FPS,即clock.tick(fps),并且游戏速度太快,因此无法播放。我认为30岁以下的人会这样做。请提供更多详细信息。