【python】10分钟教你用python打造贪吃蛇超详细教程 您所在的位置:网站首页 我想看制作蟒蛇的教程 【python】10分钟教你用python打造贪吃蛇超详细教程

【python】10分钟教你用python打造贪吃蛇超详细教程

#【python】10分钟教你用python打造贪吃蛇超详细教程| 来源: 网络整理| 查看: 265

10分钟教你用python打造贪吃蛇超详细教程

在家闲着没妹子约, 刚好最近又学了一下python,听说pygame挺好玩的。今天就在家研究一下, 弄了个贪吃蛇出来。希望大家喜欢。

先看程序效果:

01 整体框架

平台:pycharm

关于pygame的安装这里就不在赘述,大家自行上网找合适自己的版本的安装即可。关于pygame模块知识会穿插在下面代码中介绍,用到什么就介绍什么。这里就不统一介绍了。

整个程序由于是调用了大量的pygame里面的库函数,所以也非常简单(卧槽你这不是调包侠嘛)。也就200多行代码。基于整体怎么设计的呢?看下面的图:

由于程序没有多么复杂,就直接用面向过程的思路写了。毕竟这么小的程序没必要整一大堆class来为难自己对吧。

程序整体代码框架:

pycharm里面一堆波浪线也是很无奈。

02 main主函数-开始工作

此函数也非常简单。主要承担一些游戏窗口的初始化工作,以及调用相关函数运行游戏。代码如下:

1#主函数 2def main(): 3    pygame.init() # 模块初始化 4    snake_speed_clock = pygame.time.Clock() # 创建Pygame时钟对象 5    screen = pygame.display.set_mode((windows_width, windows_height)) # 6    screen.fill(white) 7 8    pygame.display.set_caption("Python 贪吃蛇小游戏") #设置标题 9    show_start_info(screen)               #欢迎信息10    while True:11        running_game(screen, snake_speed_clock)12        show_gameover_info(screen)

基于以上代码,咱们来做几点讲解:

pygame.time.Clock()控制帧速率。pygame.time.Clock()会控制每个循环多长时间运行一次。这就好比,有个定时器在控制着时间进程,一到时间就告诉CPU:现在该开始循环了!现在该开始循环了!

使用pygame时钟之前,必须先创建Clock对象的一个实例,这与创建其他类的实例完全相同。Clock= Pygame.time.Clock()。然后在主循环体中,只需要告诉时钟多久“提醒”一次-------也就是说,循环应该多长时间运行一次:clock.tick(60)。

传入clock.tick()的数不是一个毫秒数。这是每秒内循环要运行的次数,所以这个循环应当每秒运行60次,在这里我只是说应当运行,因为循环只能按计算机能够保证的速度运行,每秒60个循环(或帧)时,每个循环需要1000/60=16.66ms(大约17ms)如果循环中的代码运行时间超过17ms,在clock指出下一次循环时当前循环将无法完成。

再说通俗一点,就是我们游戏的fps嘛。每秒多少帧这样。至于后面在哪clock.tick(),下面会讲。详细可参考这篇文章:http://eyehere.net/2011/python-pygame-novice-professional-8/

pygame.display.set_mode((windows_width, windows_height))

生成windows窗口,pygame.display.set_mode(resolution=(0,0),flags=0,depth=0)。返回的是一个surface对象(surface对象是用于表示图像的图像,只要指定尺寸,就可以利用),resolution可以控制生成windows窗口的大小,flags代表的是扩展选项,depath不推荐设置。

flags标志位控制你想要什么样的显示屏,主要有下面几个,这几个量相当于是全局的常量,使用的时候可以from pygame.locals import *导入:

pygame.FULLSCREEN,控制全屏,0或者1来控制 pygame.HWSURFACE 控制是否进行硬件加速 pygame.RESIZABLE 控制窗口是否可以调节大小

screen.fill(white)pygame.surface.fill(color)。对surface对象填充某一种颜色,在这里表现为窗口背景颜色的填充。

以上讲完,然后就是运行我们游戏三个函数了。

 

show_start_info(screen)显示欢迎信息,最终效果表现为:

当然,怎么实现,待会说。

 

接着死循环。因为我们的游戏设置是,当GameOver以后,我们可以按任意键重新开始游戏,或者退出。因此最后不断循环判断用户是否想重新开始游戏,就这样而已。

游戏主体running_game(screen, snake_speed_clock)贪吃蛇运行的主体函数。整个程序的精髓所在。

show_gameover_info(screen)贪吃蛇死了,显示GameOver,表现为:

怎么实现,下面说。 03 show_start_info()欢迎进入游戏

先贴代码,待会讲解。

1#开始信息显示 2def show_start_info(screen): 3    font = pygame.font.Font('myfont.ttf', 40) 4    tip = font.render('按任意键开始游戏~~~', True, (65, 105, 225)) 5    gamestart = pygame.image.load('gamestart.png') 6    screen.blit(gamestart, (140, 30)) 7    screen.blit(tip, (240, 550)) 8    pygame.display.update() 910    while True:  #键盘监听事件11        for event in pygame.event.get():  # event handling loop12            if event.type == QUIT:13                terminate()     #终止程序14            elif event.type == KEYDOWN:15                if (event.key == K_ESCAPE):  #终止程序16                    terminate() #终止程序17                else:18                    return #结束此函数, 开始游戏 字体显示先创建一个Font对象,用自己的字体。有了Font对象以后, 就可以用render方法来写字了,然后通过blit方法blit到屏幕上。 图像加载用 pygame.image.load()加载图像获得对象,在用blit方法刷到屏幕上。做完以上事件以后,记得要update一下刷新一下屏幕。 监听键盘按任意键继续或者ESC退出…… 04 running_game-让我们开始游戏吧

running_game(screen, snake_speed_clock)是游戏主要功能,在这里给大家慢慢讲解。先贴代码:

1#游戏运行主体 2def running_game(screen,snake_speed_clock): 3    startx = random.randint(3, map_width - 8) #开始位置 4    starty = random.randint(3, map_height - 8) 5    snake_coords = [{'x': startx, 'y': starty},  #初始贪吃蛇 6                  {'x': startx - 1, 'y': starty}, 7                  {'x': startx - 2, 'y': starty}] 8 9    direction = RIGHT       #  开始时向右移动1011    food = get_random_location()     #实物随机位置1213    while True:14        for event in pygame.event.get():15            if event.type == QUIT:16                terminate()17            elif event.type == KEYDOWN:18                if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:19                    direction = LEFT20                elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:21                    direction = RIGHT22                elif (event.key == K_UP or event.key == K_w) and direction != DOWN:23                    direction = UP24                elif (event.key == K_DOWN or event.key == K_s) and direction != UP:25                    direction = DOWN26                elif event.key == K_ESCAPE:27                    terminate()2829        move_snake(direction, snake_coords) #移动蛇3031        ret = snake_is_alive(snake_coords)32        if not ret:33            break #蛇跪了. 游戏结束34        snake_is_eat_food(snake_coords, food) #判断蛇是否吃到食物3536        screen.fill(BG_COLOR)37        #draw_grid(screen)38        draw_snake(screen, snake_coords)39        draw_food(screen, food)40        draw_score(screen, len(snake_coords) - 3)41        pygame.display.update()42        snake_speed_clock.tick(snake_speed) #控制fps

关于贪吃蛇这里我们采用一个元组存储贪吃蛇身体各个部分的坐标(一条贪吃蛇不是由很多节组成的嘛)。最后再写个方法根据元组坐标把贪吃蛇画出来就行。

关于食物同样做法。存坐标,最后画出来。

关于移动监听键盘,根据用户按键,用direction变量记录移动方向。然后更新贪吃蛇元组里面的坐标(其实每次移动只用更新头尾就行)。最后统一画出来。移动做法具体是,我们把每次头部移动的新坐标插入贪吃蛇元组,然后删掉尾部一节(注意,删除尾部我们放在了另外一个函数里做)。

1#移动贪吃蛇 2def move_snake(direction, snake_coords): 3    if direction == UP: 4        newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] - 1} 5    elif direction == DOWN: 6        newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] + 1} 7    elif direction == LEFT: 8        newHead = {'x': snake_coords[HEAD]['x'] - 1, 'y': snake_coords[HEAD]['y']} 9    elif direction == RIGHT:10        newHead = {'x': snake_coords[HEAD]['x'] + 1, 'y': snake_coords[HEAD]['y']}11    snake_coords.insert(0, newHead)

开始阶段先把贪吃蛇和食物的坐标随机生成,贪吃蛇一开始3节长,先设置向右移动。

移动我们的贪吃蛇监听键盘,用户按下键盘只是改变direction的值,再用move_snake(direction, snake_coords)函数更新贪吃蛇坐标。如果不按,那direction值一直不变,贪吃蛇就一直向前走。

相关判断要判断贪吃蛇是否挂了,表现为:

头坐标超出地图范围 头坐标等于身体某节坐标 1    #判断蛇死了没 2def snake_is_alive(snake_coords): 3    tag = True 4    if snake_coords[HEAD]['x'] == -1 or snake_coords[HEAD]['x'] == map_width or snake_coords[HEAD]['y'] == -1 or \ 5            snake_coords[HEAD]['y'] == map_height: 6        tag = False # 蛇碰壁啦 7    for snake_body in snake_coords[1:]: 8        if snake_body['x'] == snake_coords[HEAD]['x'] and snake_body['y'] == snake_coords[HEAD]['y']: 9            tag = False # 蛇碰到自己身体啦10    return tag

判断贪吃蛇是否吃到食物,表现为:

头坐标等于食物坐标,那么吃到食物。这时候注意,我们就不用删尾部一节了,因为吃到食物变长了嘛。 如果没有吃到食物,那么是正常移动,删掉尾部一节坐标。 1    #判断贪吃蛇是否吃到食物2def snake_is_eat_food(snake_coords, food):  #如果是列表或字典,那么函数内修改参数内容,就会影响到函数体外的对象。3    if snake_coords[HEAD]['x'] == food['x'] and snake_coords[HEAD]['y'] == food['y']:4        food['x'] = random.randint(0, map_width - 1)5        food['y'] = random.randint(0, map_height - 1) # 实物位置重新设置6    else:7        del snake_coords[-1]  # 如果没有吃到实物, 就向前移动, 那么尾部一格删掉

画出我们的游戏最后调用相关函数,讲我们的地图,贪吃蛇,食物等等统统画出来。

05 draw_snake-画出我们的贪吃蛇

直接看代码:

1def draw_snake(screen, snake_coords):2    for coord in snake_coords:3        x = coord['x'] * cell_size4        y = coord['y'] * cell_size5        wormSegmentRect = pygame.Rect(x, y, cell_size, cell_size)6        pygame.draw.rect(screen, dark_blue, wormSegmentRect)7        wormInnerSegmentRect = pygame.Rect(                #蛇身子里面的第二层亮蓝色色8            x + 4, y + 4, cell_size - 8, cell_size - 8)9        pygame.draw.rect(screen, blue, wormInnerSegmentRect)

代码很easy,主要是获取相关坐标,最后调用pygame.draw.rect将身体各个部分画出来即可。不过为了美观,我们选择再在里面画一层不同颜色的,表现为:

06 draw_food-画出我们的食物 1#将食物画出来2def draw_food(screen, food):3    x = food['x'] * cell_size4    y = food['y'] * cell_size5    appleRect = pygame.Rect(x, y, cell_size, cell_size)6    pygame.draw.rect(screen, Red, appleRect)

更简单的代码了,获取位置,画矩形。

07 draw_score-画出我们的成绩 1#画成绩2def draw_score(screen,score):3    font = pygame.font.Font('myfont.ttf', 30)4    scoreSurf = font.render('得分: %s' % score, True, Green)5    scoreRect = scoreSurf.get_rect()6    scoreRect.topleft = (windows_width - 120, 10)7    screen.blit(scoreSurf, scoreRect)

画成绩也比较简单。获得Font对象以后,render写字,最后设置位置,在屏幕上blit出来。

08 完整代码

整个程序大体如上,其他细枝末节直接看源代码吧。

1## 导入相关模块 2import random 3import pygame 4import sys 5 6from pygame.locals import * 7 8 9snake_speed = 15 #贪吃蛇的速度 10windows_width = 800 11windows_height = 600 #游戏窗口的大小 12cell_size = 20       #贪吃蛇身体方块大小,注意身体大小必须能被窗口长宽整除 13 14''' #初始化区 15由于我们的贪吃蛇是有大小尺寸的, 因此地图的实际尺寸是相对于贪吃蛇的大小尺寸而言的 16''' 17map_width = int(windows_width / cell_size) 18map_height = int(windows_height / cell_size) 19 20# 颜色定义 21white = (255, 255, 255) 22black = (0, 0, 0) 23gray = (230, 230, 230) 24dark_gray = (40, 40, 40) 25DARKGreen = (0, 155, 0) 26Green = (0, 255, 0) 27Red = (255, 0, 0) 28blue = (0, 0, 255) 29dark_blue =(0,0, 139) 30 31 32BG_COLOR = black #游戏背景颜色 33 34# 定义方向 35UP = 1 36DOWN = 2 37LEFT = 3 38RIGHT = 4 39 40HEAD = 0 #贪吃蛇头部下标 41 42#主函数 43def main(): 44    pygame.init() # 模块初始化 45    snake_speed_clock = pygame.time.Clock() # 创建Pygame时钟对象 46    screen = pygame.display.set_mode((windows_width, windows_height)) # 47    screen.fill(white) 48 49    pygame.display.set_caption("Python 贪吃蛇小游戏") #设置标题 50    show_start_info(screen)               #欢迎信息 51    while True: 52        running_game(screen, snake_speed_clock) 53        show_gameover_info(screen) 54 55 56#游戏运行主体 57def running_game(screen,snake_speed_clock): 58    startx = random.randint(3, map_width - 8) #开始位置 59    starty = random.randint(3, map_height - 8) 60    snake_coords = [{'x': startx, 'y': starty},  #初始贪吃蛇 61                  {'x': startx - 1, 'y': starty}, 62                  {'x': startx - 2, 'y': starty}] 63 64    direction = RIGHT       #  开始时向右移动 65 66    food = get_random_location()     #实物随机位置 67 68    while True: 69        for event in pygame.event.get(): 70            if event.type == QUIT: 71                terminate() 72            elif event.type == KEYDOWN: 73                if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT: 74                    direction = LEFT 75                elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT: 76                    direction = RIGHT 77                elif (event.key == K_UP or event.key == K_w) and direction != DOWN: 78                    direction = UP 79                elif (event.key == K_DOWN or event.key == K_s) and direction != UP: 80                    direction = DOWN 81                elif event.key == K_ESCAPE: 82                    terminate() 83 84        move_snake(direction, snake_coords) #移动蛇 85 86        ret = snake_is_alive(snake_coords) 87        if not ret: 88            break #蛇跪了. 游戏结束 89        snake_is_eat_food(snake_coords, food) #判断蛇是否吃到食物 90 91        screen.fill(BG_COLOR) 92        #draw_grid(screen) 93        draw_snake(screen, snake_coords) 94        draw_food(screen, food) 95        draw_score(screen, len(snake_coords) - 3) 96        pygame.display.update() 97        snake_speed_clock.tick(snake_speed) #控制fps 98#将食物画出来 99def draw_food(screen, food):100    x = food['x'] * cell_size101    y = food['y'] * cell_size102    appleRect = pygame.Rect(x, y, cell_size, cell_size)103    pygame.draw.rect(screen, Red, appleRect)104#将贪吃蛇画出来105def draw_snake(screen, snake_coords):106    for coord in snake_coords:107        x = coord['x'] * cell_size108        y = coord['y'] * cell_size109        wormSegmentRect = pygame.Rect(x, y, cell_size, cell_size)110        pygame.draw.rect(screen, dark_blue, wormSegmentRect)111        wormInnerSegmentRect = pygame.Rect(                #蛇身子里面的第二层亮绿色112            x + 4, y + 4, cell_size - 8, cell_size - 8)113        pygame.draw.rect(screen, blue, wormInnerSegmentRect)114#画网格(可选)115def draw_grid(screen):116    for x in range(0, windows_width, cell_size):  # draw 水平 lines117        pygame.draw.line(screen, dark_gray, (x, 0), (x, windows_height))118    for y in range(0, windows_height, cell_size):  # draw 垂直 lines119        pygame.draw.line(screen, dark_gray, (0, y), (windows_width, y))120#移动贪吃蛇121def move_snake(direction, snake_coords):122    if direction == UP:123        newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] - 1}124    elif direction == DOWN:125        newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] + 1}126    elif direction == LEFT:127        newHead = {'x': snake_coords[HEAD]['x'] - 1, 'y': snake_coords[HEAD]['y']}128    elif direction == RIGHT:129        newHead = {'x': snake_coords[HEAD]['x'] + 1, 'y': snake_coords[HEAD]['y']}130131    snake_coords.insert(0, newHead)132#判断蛇死了没133def snake_is_alive(snake_coords):134    tag = True135    if snake_coords[HEAD]['x'] == -1 or snake_coords[HEAD]['x'] == map_width or snake_coords[HEAD]['y'] == -1 or \136            snake_coords[HEAD]['y'] == map_height:137        tag = False # 蛇碰壁啦138    for snake_body in snake_coords[1:]:139        if snake_body['x'] == snake_coords[HEAD]['x'] and snake_body['y'] == snake_coords[HEAD]['y']:140            tag = False # 蛇碰到自己身体啦141    return tag142#判断贪吃蛇是否吃到食物143def snake_is_eat_food(snake_coords, food):  #如果是列表或字典,那么函数内修改参数内容,就会影响到函数体外的对象。144    if snake_coords[HEAD]['x'] == food['x'] and snake_coords[HEAD]['y'] == food['y']:145        food['x'] = random.randint(0, map_width - 1)146        food['y'] = random.randint(0, map_height - 1) # 实物位置重新设置147    else:148        del snake_coords[-1]  # 如果没有吃到实物, 就向前移动, 那么尾部一格删掉149#食物随机生成150def get_random_location():151    return {'x': random.randint(0, map_width - 1), 'y': random.randint(0, map_height - 1)}152#开始信息显示153def show_start_info(screen):154    font = pygame.font.Font('myfont.ttf', 40)155    tip = font.render('按任意键开始游戏~~~', True, (65, 105, 225))156    gamestart = pygame.image.load('gamestart.png')157    screen.blit(gamestart, (140, 30))158    screen.blit(tip, (240, 550))159    pygame.display.update()160161    while True:  #键盘监听事件162        for event in pygame.event.get():  # event handling loop163            if event.type == QUIT:164                terminate()     #终止程序165            elif event.type == KEYDOWN:166                if (event.key == K_ESCAPE):  #终止程序167                    terminate() #终止程序168                else:169                    return #结束此函数, 开始游戏170#游戏结束信息显示171def show_gameover_info(screen):172    font = pygame.font.Font('myfont.ttf', 40)173    tip = font.render('按Q或者ESC退出游戏, 按任意键重新开始游戏~', True, (65, 105, 225))174    gamestart = pygame.image.load('gameover.png')175    screen.blit(gamestart, (60, 0))176    screen.blit(tip, (80, 300))177    pygame.display.update()178179    while True:  #键盘监听事件180        for event in pygame.event.get():  # event handling loop181            if event.type == QUIT:182                terminate()     #终止程序183            elif event.type == KEYDOWN:184                if event.key == K_ESCAPE or event.key == K_q:  #终止程序185                    terminate() #终止程序186                else:187                    return #结束此函数, 重新开始游戏188#画成绩189def draw_score(screen,score):190    font = pygame.font.Font('myfont.ttf', 30)191    scoreSurf = font.render('得分: %s' % score, True, Green)192    scoreRect = scoreSurf.get_rect()193    scoreRect.topleft = (windows_width - 120, 10)194    screen.blit(scoreSurf, scoreRect)195#程序终止196def terminate():197    pygame.quit()198    sys.exit()199200201main()

 

欲获取代码,请关注我们的微信公众号【程序猿声】,在后台回复:python贪吃蛇。python和贪吃蛇之间不要有空格,不要有空格,不要有空格!!!即可获取。

 


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有