赞
踩
这篇文章主要介绍了python贪吃蛇游戏代码详解外加中文,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获,下面让小编带着大家一起了解一下。
平台:pycharm
关于pygame的安装这里就不在赘述,大家自行上网找合适自己的版本的安装即可。关于pygame模块知识会穿插在下面代码中介绍,用到什么就介绍什么python用海龟库画笑脸。这里就不统一介绍了。
整个程序由于是调用了大量的pygame里面的库函数,所以也非常简单(卧槽你这不是调包侠嘛)。也就200多行代码。基于整体怎么设计的呢?看下面的图:
想要学习Python?Python学习交流群:1136201545满足你的需求,资料都已经上传群文件,可以自行下载!
由于程序没有多么复杂,就直接用面向过程的思路写了。毕竟这么小的程序没必要整一大堆class来为难自己对吧。
程序整体代码框架:
pycharm里面一堆波浪线也是很无奈。
此函数也非常简单。主要承担一些游戏窗口的初始化工作,以及调用相关函数运行游戏。代码如下:
- 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 *导入:
screen.fill(white)
pygame.surface.fill(color)。对surface对象填充某一种颜色,在这里表现为窗口背景颜色的填充。
以上讲完,然后就是运行我们游戏三个函数了。
show_start_info(screen)
显示欢迎信息,最终效果表现为:
当然,怎么实现,待会说。
接着死循环。因为我们的游戏设置是,当GameOver以后,我们可以按任意键重新开始游戏,或者退出。因此最后不断循环判断用户是否想重新开始游戏,就这样而已。
游戏主体running_game(screen, snake_speed_clock)
贪吃蛇运行的主体函数。整个程序的精髓所在。
show_gameover_info(screen)
贪吃蛇死了,显示GameOver,表现为:
先贴代码,待会讲解。
- 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()
- 9
- 10 while True: #键盘监听事件
- 11 for event in pygame.event.get(): # event handling loop
- 12 if event.type == QUIT:
- 13 terminate() #终止程序
- 14 elif event.type == KEYDOWN:
- 15 if (event.key == K_ESCAPE): #终止程序
- 16 terminate() #终止程序
- 17 else:
- 18 return #结束此函数, 开始游戏
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 # 开始时向右移动
- 10
- 11 food = get_random_location() #实物随机位置
- 12
- 13 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 = LEFT
- 20 elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
- 21 direction = RIGHT
- 22 elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
- 23 direction = UP
- 24 elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
- 25 direction = DOWN
- 26 elif event.key == K_ESCAPE:
- 27 terminate()
- 28
- 29 move_snake(direction, snake_coords) #移动蛇
- 30
- 31 ret = snake_is_alive(snake_coords)
- 32 if not ret:
- 33 break #蛇跪了. 游戏结束
- 34 snake_is_eat_food(snake_coords, food) #判断蛇是否吃到食物
- 35
- 36 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] # 如果没有吃到实物, 就向前移动, 那么尾部一格删掉
画出我们的游戏
最后调用相关函数,讲我们的地图,贪吃蛇,食物等等统统画出来。
直接看代码:
- 1def draw_snake(screen, snake_coords):
- 2 for coord in snake_coords:
- 3 x = coord['x'] * cell_size
- 4 y = coord['y'] * cell_size
- 5 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将身体各个部分画出来即可。不过为了美观,我们选择再在里面画一层不同颜色的,表现为:
- 1#将食物画出来
- 2def draw_food(screen, food):
- 3 x = food['x'] * cell_size
- 4 y = food['y'] * cell_size
- 5 appleRect = pygame.Rect(x, y, cell_size, cell_size)
- 6 pygame.draw.rect(screen, Red, appleRect)
更简单的代码了,获取位置,画矩形。
- 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出来。
整个程序大体如上,其他细枝末节直接看源代码吧。
- 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_size
- 101 y = food['y'] * cell_size
- 102 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_size
- 108 y = coord['y'] * cell_size
- 109 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 水平 lines
- 117 pygame.draw.line(screen, dark_gray, (x, 0), (x, windows_height))
- 118 for y in range(0, windows_height, cell_size): # draw 垂直 lines
- 119 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']}
- 130
- 131 snake_coords.insert(0, newHead)
- 132#判断蛇死了没
- 133def snake_is_alive(snake_coords):
- 134 tag = True
- 135 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 tag
- 142#判断贪吃蛇是否吃到食物
- 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()
- 160
- 161 while True: #键盘监听事件
- 162 for event in pygame.event.get(): # event handling loop
- 163 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()
- 178
- 179 while True: #键盘监听事件
- 180 for event in pygame.event.get(): # event handling loop
- 181 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()
- 199
- 200
- 201main()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。