使用python pygame库写基础“贪吃蛇游戏”

笔者参考《Python编程从入门到实践》、开源代码等资源,写了一个简单的贪吃蛇游戏。

最初学习pygame库的时候遇到的难点笔者也深有体会,所以为了方便新手学习理解,特地将注释写的非常详细。因此不再进行多余讲解。阅读需要一定pygame库基础知识。阅读代码不理解时请及时查阅pygame官方英文文档,会有详细介绍。

游戏由下图几部分组成:



因为工程量较小,笔者使用IDLE开发,整个游戏由这6个文件组成。双击run_game文件运行游戏。


    food文件包含食物类,包含图片初始化、置于随机位置、获得食物坐标、获得外接矩形、绘制食物功能。
    snake文件包含蛇类、初始化蛇头、获得各点位置列表、移动蛇、吃掉食物、绘制蛇功能。
    settings文件包含设置类、修改速度、窗口大小、背景颜色功能,便于修改设置。
    response文件包含响应鼠标键盘事件、修改移动方向、控制蛇移动功能。

    run_game文件为运行文件,协调各文件。功能详见代码。

    apple2为图片,用于加载食物。

以下是具体代码:

food文件:

import pygame
import random


class Food:
    """食物类"""
    
    def __init__(self,screen):
        """随机初始化第一个食物的位置"""


        self.screen = screen
 
        #加载食物图片并获取外接矩形 (pygame通过外接矩阵操作图片)
        self.image = pygame.image.load('apple2.png')


        #获得图片外接矩阵
        self.rect = self.image.get_rect()
               
        #随机获得图片中心横纵坐标
        #(randint获得10~490的int类型随机数,包括10和490)
        #(rect.centerx为中心横坐标)
        self.rect.centerx = random.randint(20,480)   
        self.rect.centery = random.randint(20,480)
        
    def reinit(self):
        """ 随机获得一个食物,并返回食物坐标"""


        self.rect.centerx = random.randint(20,480)
        self.rect.centery = random.randint(20,480)
        return [self.rect.centerx,self.rect.centery]
    def position(self):
        """ 返回食物坐标"""
        
        return [self.rect.centerx,self.rect.centery]


    def foodrect(self):
        """返回外接矩矩形"""
        
        return self.rect
        
    def blitme(self):
        """在指定位置绘制食物"""
        
        self.screen.blit(self.image,self.rect)
response文件:
import pygame


#初始化移动状态,使一开始向上移动
move_up = True
move_down = False
move_left = False
move_right = False


def check_events(snake):
    """响应按键和鼠标事件"""


    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit(0)
        check_keydown_events(event)
    redirection(snake)


def check_keydown_events(event):
    """响应键盘按下"""


    #可修改全局变量
    global move_up
    global move_down 
    global move_left 
    global move_right


    if event.type == pygame.KEYDOWN:
        # and move_down == False 及类似代码使蛇不可回头
        if event.key == pygame.K_UP and move_down == False:
            #修改移动状态
            move_up = True
            move_down = False
            move_left = False
            move_right = False
        if event.key == pygame.K_DOWN and move_up == False:
            move_up = False
            move_down = True
            move_left = False
            move_right = False
        if event.key == pygame.K_LEFT and move_right == False:
            move_up = False
            move_down = False
            move_left = True
            move_right = False
        if event.key == pygame.K_RIGHT and move_left == False:
            move_up = False
            move_down = False
            move_left = False 
            move_right = True


def redirection(snake):
    global move_up
    global move_down 
    global move_left 
    global move_right


    #传递给蛇类的方向方法,使蛇头方向变更
    if move_up:
        snake.direction('U')
    if move_down:
        snake.direction('D')
    if move_left:
        snake.direction('L')
    if move_right:
        snake.direction('R')
    

settings文件:

class Settings():
    """存储游戏所有设置的类"""


    def __init__(self):
        """初始化游戏的设置"""
        # 设置屏幕大小
        self.screen_width = 500
        self.screen_height = 500


        #设置屏幕背景色
        self.bg_color = [255,255,240]


        #设置蛇移动速度(帧数)
        self.speed = 20


        #设置蛇的颜色
        self.snake_color = [50,0,0]

snake文件:

import copy


class Snake:
    def __init__(self):
        """初始化第一个点(蛇头)的位置"""


        #创建存储每个点位置的列表,目前只有蛇头
        self.poslist = [[250,250]]
        
    def position(self):
        """返回存储连续点位置的列表"""
        
        return self.poslist
    
    def direction(self,new_direction):
        """控制蛇移动方向"""
        
        count = len(self.poslist)
        position = count-1


        #所有点移动向下一位置
        while position > 0:
            self.poslist[position] = copy.deepcopy(self.poslist[position-1])
            position -= 1


        #更新蛇头位置,和移动方向有关
        if new_direction is 'U':
            self.poslist[0][1] -= 10


            #设置可以穿墙
            if self.poslist[0][1] < 0:
                self.poslist[0][1] = 500
                
        if new_direction is 'D':
            self.poslist[0][1] += 10
            if self.poslist[0][1] > 500:
                self.poslist[0][1] = 0
        if new_direction is 'L':
            self.poslist[0][0] -= 10
            if self.poslist[0][0] < 0:
                self.poslist[0][0] = 500
        if new_direction is 'R':
            self.poslist[0][0] += 10
            if self.poslist[0][0] > 500:
                self.poslist[0][0] = 0
                
    def eatfood(self,foodpoint):
        """吃掉食物并加入列表"""
        
        self.poslist.append(foodpoint)


    def draw_snake(self,poslist):
        """画蛇"""


        self.poslist = poslist
        

run_game文件:
import pygame


#导入其他文件的类、函数
import response as res
from food import Food
from settings import Settings
from snake import Snake


def run_game():


    #初始化pygame
    pygame.init()


    #设置时钟对象,控制帧数
    clock = pygame.time.Clock()


    #一个Settings类实例,便于控制游戏参数
    run_settings = Settings()


    #游戏窗口大小,参数为宽和高
    screen = pygame.display.set_mode((run_settings.screen_width,
                                      run_settings.screen_height))


    #设置窗口名字
    pygame.display.set_caption("贪吃蛇")
    restart = True


    #创建字体对象,绘制文本,返回surface。参数一:字体  参数二:字号
    socre_font = pygame.font.Font(None,28)


    #记录分数
    score = 0


    #是否重开
    while restart:


        #类的实例
        snake = Snake()
        food = Food(screen)
        running = True


        #是否游戏结束
        while running:


           #窗口背景颜色,用参数RGB设置
           screen.fill(run_settings.bg_color)


           #开始接收、响应键盘指令
           res.check_events(snake)


           #控制循环帧数,参数为每秒帧数
           time_pass = clock.tick(run_settings.speed)                


           #接受食物图片的外接矩形
           food_rect = food.foodrect()


           #矩形中心的位置
           food_point = food.position()


           #绘制这个食物
           food.blitme()


           #绘制蛇
           poslist = snake.position()
           snakes_rect = []
           for pos in poslist:
                #pygame.draw.circle()返回外接矩形
                snakes_rect.append(pygame.draw.circle(screen,run_settings.snake_color,pos,5,0))


                #检测是否吃到食物
                #pygame.Rect.collidepoint() 检测一个点是否包含在该Rect对象内 
                if food_rect.collidepoint(pos):
                    snake.eatfood(food_point)
                    food.reinit()
                    food.blitme()
                    food_rect = food.foodrect()
                    score += 1
                    break


           #打印内容 参数:字符串、是否平滑、颜色     
           score_text = socre_font.render("score : "+str(score),True,(255,0,0))
           score_rect = score_text.get_rect()


           #设置字体位置
           score_rect.centerx = 450
           score_rect.centery = 10 
           screen.blit(score_text,score_rect)
           
           #检测是否撞到自己 (蛇头和身体位置是否重合)
           head_rect = snakes_rect[0]
           count = len(snakes_rect)
           while count > 1:
                if head_rect.colliderect(snakes_rect[count-1]):
                    running = False
                count -= 1


           #更新屏幕
           pygame.display.update()   


        #游戏结束界面
        screen.fill([255,255,240])


        #一个字体对象,参数一:字体(None为默认)  参数二:字体大小
        font = pygame.font.Font(None,38)
        
        #绘制文本,返回surface
        text = font.render("Game Over! press space to restart. ",True,(255,0,0))
        textRect = text.get_rect()
        textRect.centerx = screen.get_rect().centerx
        textRect.centery = screen.get_rect().centery 
        screen.blit(text,textRect)


        #是否重开
        while True:
            event = pygame.event.poll()
            if event.type == pygame.QUIT:
                pygame.quit()
                exit(0)
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    restart = True
                    #初始化对象、变量
                    #python自动清理,只用删除引用
                    score = 0
                    del snake
                    del food
                    break


            #更新屏幕
            pygame.display.update()        

run_game()        

游戏过程:


此版本为基础版本,可在版本上添加:

显示历史最高分
屏幕中设置墙
背景加载图片
增加游戏声效
美化蛇头、蛇身
根据等级加快行走速度
设置各关卡

等等……各种功能

限于篇幅不做更多讨论。


转载请告知作者。

猜你喜欢

转载自blog.csdn.net/htgt_tuntuntun/article/details/80531817