栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python的pygame实现贪吃蛇

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python的pygame实现贪吃蛇

        刚结束期末考试,闲来无事,便尝试着做个贪吃蛇玩玩。

        起初尚是不明所以,但在看了另一个老哥的文章用python写一个简单的贪吃蛇游戏(附代码)之后,豁然开朗。

        我的代码大体采用了这位老哥的框架,但采取了与之不同的面向对象的实现方式。并且我的代码实现了贪吃蛇穿墙移动(从一头进,在另一头出)的操作。

        但是写完之后实际看看还是有比较大的上升空间的,例如可以把蛇和苹果的绘制放到”蛇“类和”苹果“类当中去。只是练习作,如果有更好的意见欢迎畅所欲言。

代码实现

“蛇”类:用于实现蛇对象(本质为队列)

class Snake:
    def __init__(self) -> None:
        self._sn = deque()
        self._sn.append([2, 2])
        self._sn.append([1, 2])
        self._sn.append([0, 2])
        self.directionX = 1
        self.directionY = 0
    def pushBack(self, nextStep : list) -> None:
        self._sn.appendleft(nextStep)
    def pop(self) -> None:
        self._sn.pop()
    def __len__(self) -> int:
        return len(self._sn)
    def getSn(self) -> deque:
        return self._sn

”苹果“类: 用于实现苹果对象

class Apple:
    def __init__(self, snake : Snake):
        self._x = random.randint(0, screenWidth // 20 - 1)
        self._y = random.randint(2, screenHeight // 20 - 1)
        while [self._x, self._y] in snake.getSn():
            self._x = random.randint(0, screenWidth // 20 - 1)
            self._y = random.randint(2, screenHeight // 20 - 1)
    def getX(self) -> int:
        return self._x
    def getY(self) -> int:
        return self._y

”计数“类:用于计量游戏数值(得分,速度)

class ScoreAndSpeed:
    def __init__(self):
        self._score = 0
        self._oriSpeed = 0.5
        self._speed = self._oriSpeed
    def getScore(self) -> int:
        return self._score
    def setScore(self, score : int):
        self._score = score
    def getOriSpeed(self) -> float:
        return self._oriSpeed
    def getSpeed(self) -> float:
        return self._speed
    def setSpeed(self, speed : float):
        self._speed = speed

”游戏“类:用于实现游戏画面和相关功能

class Game:
    def __init__(self):
        pygame.init()
        self.myWindow = pygame.display.set_mode((screenWidth, screenHeight), 0, 32)
        pygame.display.set_caption("Snake")
        self.myWindow.fill((0, 0, 0))
        pygame.display.update()
        self.font_score = pygame.font.SysFont('SimHei', 24)
        self.font_Length = pygame.font.SysFont('SimHei', 24)
        self.font_GameOver = pygame.font.SysFont(None, 72)
        self.font_Beginning = pygame.font.SysFont(None, 48)
        self.color_GameOver = (255, 255, 255)
        # self.directionX = 1
        # self.directionY = 0
        self.directionLimit = True
        self.isGameOver = True
        self.isStart = False
        # self.score = 0
        # self.oriSpeed = 0.5
        self.lastMove = time.time()
        self.isPause = False
        self.snake = Snake()
        self.apple = Apple(self.snake)
        self.scoreAndSpeed = ScoreAndSpeed()
        self.speed = self.scoreAndSpeed.getOriSpeed()
    def fontPrinter(self, font, x, y, text, fcolor = (255, 255, 255)):
        Textimg = font.render(text, True, fcolor)
        self.myWindow.blit(Textimg, (x, y))
    def runing(self):
        while True:
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == KEYDOWN:
                    if event.key == K_RETURN:
                        # restart game
                        if self.isGameOver:
                            self.isGameOver = False
                            self.isStart = True
                            self.directionLimit = True
                            self.snake = Snake()
                            self.apple = Apple(self.snake)
                            self.scoreAndSpeed = ScoreAndSpeed()
                            self.lastMove = time.time()
                    elif event.key == K_SPACE:
                        if not self.isGameOver:
                            self.isPause = not self.isPause
                    elif event.key in (K_UP, K_w):
                        if self.directionLimit and self.snake.directionY == 0:
                            self.snake.directionY = -1
                            self.snake.directionX = 0
                            self.directionLimit = False
                    elif event.key in (K_DOWN, K_s):
                        if self.directionLimit and self.snake.directionY == 0:
                            self.snake.directionY = 1
                            self.snake.directionX = 0
                            self.directionLimit = False
                    elif event.key in (K_RIGHT, K_d):
                        if self.directionLimit and self.snake.directionX == 0:
                            self.snake.directionY = 0
                            self.snake.directionX = 1
                            self.directionLimit = False
                    elif event.key in (K_LEFT, K_a):
                        if self.directionLimit and self.snake.directionX == 0:
                            self.snake.directionY = 0
                            self.snake.directionX = -1
                            self.directionLimit = False
            self.myWindow.fill((0, 0, 0))
            for x in range(stepWidth, screenWidth, stepWidth):
                pygame.draw.line(self.myWindow, (255, 255, 255), (x, 2 * stepWidth), (x, screenHeight), lineWidth)
            for y in range(2 * stepWidth, screenHeight, stepWidth):
                pygame.draw.line(self.myWindow, (255, 255, 255), (0, y), (screenWidth, y), lineWidth)
            if self.isGameOver:
                if not self.isStart:
                    self.fontPrinter(self.font_Beginning, screenWidth // 2, screenHeight // 2, 'Enter to start',
                                    self.color_GameOver)
            if self.isGameOver:
                if self.isStart:
                    self.fontPrinter(self.font_GameOver, screenWidth // 2, screenHeight // 2, 'Game Over',
                                    self.color_GameOver)
            else:
                now = time.time()
                if now - self.lastMove > self.scoreAndSpeed.getSpeed():
                    if not self.isPause:
                        self.directionLimit = True
                        self.lastMove = now
                        nextStepX, nextStepY = (self.snake.getSn()[0][0] + self.snake.directionX) % (screenWidth // stepWidth), 
                                               (self.snake.getSn()[0][1] + self.snake.directionY)
                        if nextStepY >= (screenHeight // stepWidth) or nextStepY < 2:
                            if nextStepY >= (screenHeight // stepWidth):
                                nextStepY = 2
                            elif nextStepY < 2:
                                nextStepY = screenHeight // stepWidth - 1
                        else:
                            nextStepY = nextStepY % (screenHeight // stepWidth)
                        if nextStepX == self.apple.getX() and nextStepY == self.apple.getY():
                            self.apple = Apple(self.snake)
                            self.snake.pushBack([nextStepX, nextStepY])
                            self.scoreAndSpeed.setScore(self.scoreAndSpeed.getScore() + 10)
                            self.scoreAndSpeed.setSpeed(self.scoreAndSpeed.getOriSpeed() - 0.03 * (self.scoreAndSpeed.getScore() // 100))
                        else:
                            if [nextStepX, nextStepY] not in self.snake.getSn():
                                self.snake.pushBack([nextStepX, nextStepY])
                                self.snake.pop()
                            else:
                                self.isGameOver = True
                    else:
                        self.fontPrinter(self.font_Beginning, screenWidth // 2, screenHeight // 2, 'space to continue',
                                         self.color_GameOver)
            if not self.isGameOver:
                pygame.draw.rect(self.myWindow, (255, 0, 0), (self.apple.getX() * stepWidth + 1, self.apple.getY() * stepWidth + 1, 
                                                                stepWidth - 2, stepWidth - 2), 0)
            for snake in self.snake.getSn():
                pygame.draw.rect(self.myWindow, (200, 200, 200), (snake[0] * stepWidth + 1, snake[1] * stepWidth + 1, stepWidth - 2, stepWidth - 2), 0)
            self.fontPrinter(self.font_Length, 30, 7, f'length:{len(self.snake)}', (255, 255, 255))
            self.fontPrinter(self.font_score, 450, 7, f'score:{self.scoreAndSpeed.getScore()}', (255, 255, 255))
            pygame.display.update()
全部代码
# Snake by myself
'''
    About Variables:
        // directionX: the direction on x-axis, '1' is to right, '-1' is to left, else '0'
        // directionY: the direction on y-axis, '-1' is to up, '1' is to down, else '0'
        // isGameOver: if 'isGameOver' and 'isStart' are all true, the game will over
'''
import queue
import random
import sys
import pygame
import time
from pygame.locals import *
from collections import deque

# the bound of game screen
screenWidth = 600
screenHeight = 480
stepWidth = 20
lineWidth = 1

class Snake:
    def __init__(self) -> None:
        self._sn = deque()
        self._sn.append([2, 2])
        self._sn.append([1, 2])
        self._sn.append([0, 2])
        self.directionX = 1
        self.directionY = 0
    def pushBack(self, nextStep : list) -> None:
        self._sn.appendleft(nextStep)
    def pop(self) -> None:
        self._sn.pop()
    def __len__(self) -> int:
        return len(self._sn)
    def getSn(self) -> deque:
        return self._sn

class Apple:
    def __init__(self, snake : Snake):
        self._x = random.randint(0, screenWidth // 20 - 1)
        self._y = random.randint(2, screenHeight // 20 - 1)
        while [self._x, self._y] in snake.getSn():
            self._x = random.randint(0, screenWidth // 20 - 1)
            self._y = random.randint(2, screenHeight // 20 - 1)
    def getX(self) -> int:
        return self._x
    def getY(self) -> int:
        return self._y

class ScoreAndSpeed:
    def __init__(self):
        self._score = 0
        self._oriSpeed = 0.5
        self._speed = self._oriSpeed
    def getScore(self) -> int:
        return self._score
    def setScore(self, score : int):
        self._score = score
    def getOriSpeed(self) -> float:
        return self._oriSpeed
    def getSpeed(self) -> float:
        return self._speed
    def setSpeed(self, speed : float):
        self._speed = speed
class Game:
    def __init__(self):
        pygame.init()
        self.myWindow = pygame.display.set_mode((screenWidth, screenHeight), 0, 32)
        pygame.display.set_caption("Snake")
        self.myWindow.fill((0, 0, 0))
        pygame.display.update()
        self.font_score = pygame.font.SysFont('SimHei', 24)
        self.font_Length = pygame.font.SysFont('SimHei', 24)
        self.font_GameOver = pygame.font.SysFont(None, 72)
        self.font_Beginning = pygame.font.SysFont(None, 48)
        self.color_GameOver = (255, 255, 255)
        # self.directionX = 1
        # self.directionY = 0
        self.directionLimit = True
        self.isGameOver = True
        self.isStart = False
        # self.score = 0
        # self.oriSpeed = 0.5
        self.lastMove = time.time()
        self.isPause = False
        self.snake = Snake()
        self.apple = Apple(self.snake)
        self.scoreAndSpeed = ScoreAndSpeed()
        self.speed = self.scoreAndSpeed.getOriSpeed()
    def fontPrinter(self, font, x, y, text, fcolor = (255, 255, 255)):
        Textimg = font.render(text, True, fcolor)
        self.myWindow.blit(Textimg, (x, y))
    def runing(self):
        while True:
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == KEYDOWN:
                    if event.key == K_RETURN:
                        # restart game
                        if self.isGameOver:
                            self.isGameOver = False
                            self.isStart = True
                            self.directionLimit = True
                            self.snake = Snake()
                            self.apple = Apple(self.snake)
                            self.scoreAndSpeed = ScoreAndSpeed()
                            self.lastMove = time.time()
                    elif event.key == K_SPACE:
                        if not self.isGameOver:
                            self.isPause = not self.isPause
                    elif event.key in (K_UP, K_w):
                        if self.directionLimit and self.snake.directionY == 0:
                            self.snake.directionY = -1
                            self.snake.directionX = 0
                            self.directionLimit = False
                    elif event.key in (K_DOWN, K_s):
                        if self.directionLimit and self.snake.directionY == 0:
                            self.snake.directionY = 1
                            self.snake.directionX = 0
                            self.directionLimit = False
                    elif event.key in (K_RIGHT, K_d):
                        if self.directionLimit and self.snake.directionX == 0:
                            self.snake.directionY = 0
                            self.snake.directionX = 1
                            self.directionLimit = False
                    elif event.key in (K_LEFT, K_a):
                        if self.directionLimit and self.snake.directionX == 0:
                            self.snake.directionY = 0
                            self.snake.directionX = -1
                            self.directionLimit = False
            self.myWindow.fill((0, 0, 0))
            for x in range(stepWidth, screenWidth, stepWidth):
                pygame.draw.line(self.myWindow, (255, 255, 255), (x, 2 * stepWidth), (x, screenHeight), lineWidth)
            for y in range(2 * stepWidth, screenHeight, stepWidth):
                pygame.draw.line(self.myWindow, (255, 255, 255), (0, y), (screenWidth, y), lineWidth)
            if self.isGameOver:
                if not self.isStart:
                    self.fontPrinter(self.font_Beginning, screenWidth // 2, screenHeight // 2, 'Enter to start',
                                    self.color_GameOver)
            if self.isGameOver:
                if self.isStart:
                    self.fontPrinter(self.font_GameOver, screenWidth // 2, screenHeight // 2, 'Game Over',
                                    self.color_GameOver)
            else:
                now = time.time()
                if now - self.lastMove > self.scoreAndSpeed.getSpeed():
                    if not self.isPause:
                        self.directionLimit = True
                        self.lastMove = now
                        nextStepX, nextStepY = (self.snake.getSn()[0][0] + self.snake.directionX) % (screenWidth // stepWidth), 
                                               (self.snake.getSn()[0][1] + self.snake.directionY)
                        if nextStepY >= (screenHeight // stepWidth) or nextStepY < 2:
                            if nextStepY >= (screenHeight // stepWidth):
                                nextStepY = 2
                            elif nextStepY < 2:
                                nextStepY = screenHeight // stepWidth - 1
                        else:
                            nextStepY = nextStepY % (screenHeight // stepWidth)
                        if nextStepX == self.apple.getX() and nextStepY == self.apple.getY():
                            self.apple = Apple(self.snake)
                            self.snake.pushBack([nextStepX, nextStepY])
                            self.scoreAndSpeed.setScore(self.scoreAndSpeed.getScore() + 10)
                            self.scoreAndSpeed.setSpeed(self.scoreAndSpeed.getOriSpeed() - 0.03 * (self.scoreAndSpeed.getScore() // 100))
                        else:
                            if [nextStepX, nextStepY] not in self.snake.getSn():
                                self.snake.pushBack([nextStepX, nextStepY])
                                self.snake.pop()
                            else:
                                self.isGameOver = True
                    else:
                        self.fontPrinter(self.font_Beginning, screenWidth // 2, screenHeight // 2, 'space to continue',
                                         self.color_GameOver)
            if not self.isGameOver:
                pygame.draw.rect(self.myWindow, (255, 0, 0), (self.apple.getX() * stepWidth + 1, self.apple.getY() * stepWidth + 1, 
                                                                stepWidth - 2, stepWidth - 2), 0)
            for snake in self.snake.getSn():
                pygame.draw.rect(self.myWindow, (200, 200, 200), (snake[0] * stepWidth + 1, snake[1] * stepWidth + 1, stepWidth - 2, stepWidth - 2), 0)
            self.fontPrinter(self.font_Length, 30, 7, f'length:{len(self.snake)}', (255, 255, 255))
            self.fontPrinter(self.font_score, 450, 7, f'score:{self.scoreAndSpeed.getScore()}', (255, 255, 255))
            pygame.display.update()
if __name__ == '__main__':
    game = Game()
    game.runing()

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1001439.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号