python 使用pygame工具包实现贪吃蛇游戏(多彩版)


Posted in Python onOctober 30, 2019

今天我们用python和python的工具包pygame来编写一个贪吃蛇的小游戏

贪吃蛇游戏功能介绍

贪吃蛇的游戏规则如下:

通过上下左右键或者WASD键来移动蛇来,让它吃到食物,每吃到食物,蛇的长度变长,并获得分数。若蛇碰到游戏边际

或者自身,则蛇死亡,游戏结束。

游戏设计思路

根据游戏规则,我们需要:

1.初始化游戏环境。

2.初始化蛇、食物

3.监听键盘动作

4.蛇的运动,吃食物,是否死亡

5.该局游戏结束,是否还有再玩。

其中的难点在于如何在屏幕上展示蛇的运动,其实我们肉眼所见的蛇的运动并不是真实的,而是在后台通过刷新蛇的坐标而实现的。即可以创建一个蛇的坐标列表,每移动一次,则新的坐标加入,同时删除末尾坐标,看起来像是蛇的在移动。

一个简单地设计框图如下:

python 使用pygame工具包实现贪吃蛇游戏(多彩版)

代码实现

'''
my_snake.py
@author HelloWorld!
@time:2019.10.27

'''

import random
import pygame
import sys
from pygame.locals import *

windows_width=800 #游戏窗口的大小,原点在左上角
windows_height=600

cell_size=20  #snake 的大小,需被窗口长宽整除

#一些颜色定义
white = (255, 255, 255)
black = (0, 0, 0)
gray = (230, 230, 230)
dark_gray = (40, 40, 40)
DARKGreen = (0, 155, 0)
Green = (0, 255, 0)
Red = (255, 0, 0)
blue = (0, 0, 255)
dark_blue =(0,0, 139)

BG_COLOR = (184,224,217)

#贪吃蛇的地图尺寸
map_width = int(windows_width / cell_size)
map_height = int(windows_height / cell_size)

#蛇的移动速度
snake_speed=5

#方向定义
UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4

#主函数
def main_game():
  pygame.init() #初始化gygame
  screen=pygame.display.set_mode((windows_width,windows_height))
  pygame.display.set_caption("贪吃蛇游戏")
  snake_speed_clock = pygame.time.Clock() # 创建Pygame时钟对象
  screen.fill(white)

  while True:
    run_game(screen,snake_speed_clock) #游戏主体
    gameover(screen)        #游戏结束


def run_game(screen,snake_speed_clock):
  #初始化蛇的位置,方向,食物的位置
  start_x=random.randint(3,map_width-8)
  start_y=random.randint(3,map_width-8)
  snake_coords=[{'x':start_x,'y':start_y},{'x':start_x-1,'y':start_y},{'x':start_x-2,'y':start_y}]#初始化snake,也可以用列表的的列表
  direction = RIGHT
  food=get_random_location()

  #循环
  while True:
    for event in pygame.event.get(): #键盘事件监听
      if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()
      elif event.type == pygame.KEYDOWN: #按键事件
        if (event.key==K_LEFT or event.key==K_a) and direction!=RIGHT:
          direction=LEFT
        elif (event.key==K_RIGHT or event.key==K_d) and direction!=LEFT:
          direction=RIGHT
        elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
          direction = UP
        elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
          direction = DOWN
        elif event.key == K_ESCAPE:
          pygame.quit()
          sys.exit()

    snake_move(direction,snake_coords) #根据方向,移动蛇

    alive=snake_is_alive(snake_coords)  #判断蛇的死活
    if not alive:            #如果挂了,则终止循环,跳出run_game函数,执行gameover
      break
    snake_eat_foods(snake_coords,food)  #没挂,则看看迟到食物了吗
    screen.fill(BG_COLOR)        #游戏背景刷新

    #下面draw,是把蛇食物等画出来
    draw_snake(screen, snake_coords)
    draw_food(screen,food)
    draw_score(screen, len(snake_coords) - 3)
    # draw_grid(screen)
    pygame.display.flip()

    #控制执行次数
    snake_speed_clock.tick(snake_speed) # 控制fps


#根据移动方向,更新蛇头坐标
def snake_move(directtion,snake_coords):
  if directtion==UP:
    newHead={'x':snake_coords[0]['x'],'y':snake_coords[0]['y']-1}
  elif directtion==DOWN:
    newHead = {'x': snake_coords[0]['x'], 'y': snake_coords[0]['y'] + 1}
  elif directtion==LEFT:
    newHead = {'x': snake_coords[0]['x']-1, 'y': snake_coords[0]['y'] }
  elif directtion == RIGHT:
    newHead = {'x': snake_coords[0]['x']+1, 'y': snake_coords[0]['y']}
  snake_coords.insert(0,newHead)

def snake_is_alive(snake_coords): #碰壁或者碰到自身就是死了
  alive=True
  if snake_coords[0]['x'] == -1 or snake_coords[0]['x'] == map_width or snake_coords[0]['y'] == -1 or \
  snake_coords[0]['y'] == map_height:
    alive=False
  for snake_body in snake_coords[1:]:
    if snake_coords[0]['x']==snake_body['x'] and snake_coords[0]['y']==snake_body['y']:
      alive=False
  return alive

#坐标重合,表示吃到食物了,否则就没有,则移动,把
def snake_eat_foods(snake_coords,food):
  if snake_coords[0]['x']==food['x'] and snake_coords[0]['y']==food['y']:
    food['x']=random.randint(0, map_width-1)
    food['y']=random.randint(0, map_height-1)
  else:
    del snake_coords[-1]

def get_random_location(): #食物的坐标随机生成
  return {'x':random.randint(0,map_width-1),'y':random.randint(0,map_height-1)}

def draw_snake(screen, snake_coords):
  for coord in snake_coords:
    x=coord['x']*cell_size
    y=coord['y']*cell_size
    segmentRect=pygame.Rect(x,y,cell_size,cell_size)
    pygame.draw.rect(screen,dark_blue,segmentRect)

def draw_food(screen,food):
  x=food['x']*cell_size
  y=food['y']*cell_size

  foodRect=pygame.Rect(x,y,cell_size,cell_size)
  pygame.draw.rect(screen,Red,foodRect)

def draw_grid(screen):
  for x in range(0,windows_width,cell_size):
    pygame.draw.line(screen,gray,(x,0),(x,windows_height))
  for y in range(0,windows_height,cell_size):
    pygame.draw.line(screen,gray,(0,y),(windows_width,y))
def draw_score(screen, score):
  font = pygame.font.SysFont(None, 40)
  score_str = "{:,}".format(score)
  score_image=font.render('Score: '+score_str,True,Green,gray)
  score_rect=score_image.get_rect()

  score_rect.topleft=(windows_width-200,10)
  screen.blit(score_image, score_rect)

def gameover(screen):
  font=pygame.font.SysFont(None, 40)
  tips=font.render('Press Q or ESC to quit; Press anykey to continue',True, (65, 105, 225))
  screen.blit(tips,(80, 300))
  pygame.display.update()
  while True:
    for event in pygame.event.get():
      if event.type==QUIT:
        pygame.quit()
        sys.exit()
      elif event.type == KEYDOWN:
        if event.key == K_ESCAPE or event.key == K_q: # 终止程序
          pygame.quit()
          sys.exit() # 终止程序
        else:
          return # 结束此函数, 重新开始游戏

if __name__=='__main__':
  main_game()

功能抽象及多彩化设计

上面的实现中,我们采用的面向过程的实现方法,没有抽象,如果要设计更大的游戏则是不行的。我们可以采用抽象的方法,让实现更加条理化,同时逻辑更清晰。

同时,如果让食物的颜色不同,同时蛇吃到什么颜色的食物,那么它身体的一部分就变成相应的颜色,那么最终蛇会变成一条多彩蛇,想必很有意思。

下面我们结合上述两点来实现新的功能。代码如下:

'''
@colorful_snake.py
@author HelloWorld!
@time:2019.10.27
@ class is used to design a snake game
'''
import random
import pygame
from pygame.locals import *
import sys
class Settings():
  def __init__(self):
    self.windows_width=800 #游戏窗口的大小,原点在左上角
    self.windows_height=600
    self.BG_COLOR = (184,224,217)
    self.cell_size=20  #snake 的大小,需被窗口长宽整除
    self.map_width = int(self.windows_width / self.cell_size)
    self.map_height = int(self.windows_height / self.cell_size)
    self.Green = (0, 255, 0)
    self.Red = (255, 0, 0)
    self.Blue = (0, 0, 255)
    self.orange=(255,128,0)
    self.purple=(128, 0, 255)
    self.black = (0, 0, 0)
    self.white = (255, 255, 255)
    self.dark_blue = (0, 0, 139)
    self.gray = (230, 230, 230)
    #方向
    self.UP = 1
    self.DOWN = 2
    self.LEFT = 3
    self.RIGHT = 4
class Snake():
  def __init__(self,settings):
    self.cell_size=settings.cell_size
    self.snake_coords=[]
    self.direction=settings.RIGHT
    self.snake_speed=5
    self.initialize_snake(settings)
  def initialize_snake(self,settings):
    # [{'x':start_x,'y':start_y},{'x':start_x-1,'y':start_y},{'x':start_x-2,'y':start_y}]#初始化snake,也可以用列表的的列表
    start_x = random.randint(3, settings.map_width - 8)
    start_y = random.randint(3, settings.map_width - 8)
    snake_coords = [{'x': start_x, 'y': start_y,'color':settings.dark_blue}, {'x': start_x - 1, 'y': start_y,'color':settings.dark_blue},
            {'x': start_x - 2, 'y': start_y,'color':settings.dark_blue}] # 初始化snake,也可以用列表的的列表
    self.snake_coords=snake_coords
  def snake_move(self,settings):
    if self.direction == settings.UP:
      newHead = {'x': self.snake_coords[0]['x'], 'y': self.snake_coords[0]['y'] - 1,'color':settings.dark_blue}
    elif self.direction == settings.DOWN:
      newHead = {'x': self.snake_coords[0]['x'], 'y': self.snake_coords[0]['y'] + 1,'color':settings.dark_blue}
    elif self.direction == settings.LEFT:
      newHead = {'x': self.snake_coords[0]['x'] - 1, 'y': self.snake_coords[0]['y'],'color':settings.dark_blue}
    elif self.direction == settings.RIGHT:
      newHead = {'x': self.snake_coords[0]['x'] + 1, 'y': self.snake_coords[0]['y'],'color':settings.dark_blue}
    self.snake_coords.insert(0, newHead)
  def snake_is_alive(self,settings):# 碰壁或者碰到自身就是死了
    alive = True
    if self.snake_coords[0]['x'] == -1 or self.snake_coords[0]['x'] == settings.map_width or self.snake_coords[0]['y'] == -1 or \
        self.snake_coords[0]['y'] ==settings.map_height:
      alive = False
    for snake_body in self.snake_coords[1:]:
      if self.snake_coords[0]['x'] == snake_body['x'] and self.snake_coords[0]['y'] == snake_body['y']:
        alive = False
    return alive
class Food():
  def __init__(self,settings):
    self.cell_size=settings.cell_size
    self.color=self.initialize_food(settings)
    self.x= random.randint(0, settings.map_width - 1)
    self.y= random.randint(0, settings.map_height - 1)
  def initialize_food(self,settings):
    colors=[settings.Green,settings.Red,settings.Blue,settings.orange,settings.purple,settings.black]
    color=random.choice(colors)
    return color
class GameFunction():
  def __init__(self,screen):
    self.screen=screen
  def check_event(self,snake,settings):
    for event in pygame.event.get(): #键盘事件监听
      if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()
      elif event.type == pygame.KEYDOWN: #按键事件
        if (event.key==K_LEFT or event.key==K_a) and snake.direction!=settings.RIGHT:
          snake.direction=settings.LEFT
        elif (event.key==K_RIGHT or event.key==K_d) and snake.direction!=settings.LEFT:
          snake.direction=settings.RIGHT
        elif (event.key == K_UP or event.key == K_w) and snake.direction != settings.DOWN:
          snake.direction = settings.UP
        elif (event.key == K_DOWN or event.key == K_s) and snake.direction != settings.UP:
          snake.direction = settings.DOWN
        elif event.key == K_ESCAPE:
          pygame.quit()
          sys.exit()
  def snake_eat_foods(self,snake,food,settings):
    if snake.snake_coords[0]['x'] == food.x and snake.snake_coords[0]['y'] == food.y:
      snake.snake_coords[0]['color'] = food.color
      food.x = random.randint(0, settings.map_width - 1)
      food.y = random.randint(0, settings.map_height - 1)
      food.color=food.initialize_food(settings)
    else:
      for i in range(len(snake.snake_coords)-1):
        snake.snake_coords[i]['color']=snake.snake_coords[i+1]['color']
      del snake.snake_coords[-1]
  def update(self,snake,food,settings,screen,snake_speed_clock):
    screen.fill(settings.BG_COLOR) # 游戏背景刷新
    # 下面draw,是把蛇食物等画出来
    self.draw_snake(screen, snake)
    self.draw_food(screen, food)
    self.draw_score(screen,snake,settings)
    self.draw_grid(screen,settings)
    pygame.display.flip()
    # 控制执行次数
    snake_speed_clock.tick(snake.snake_speed) # 控制fps
  def draw_snake(self,screen,snake):
    for coord in snake.snake_coords:
      x = coord['x'] * snake.cell_size
      y = coord['y'] * snake.cell_size
      segmentRect = pygame.Rect(x, y, snake.cell_size, snake.cell_size)
      pygame.draw.rect(screen, coord['color'], segmentRect)
  def draw_food(self,screen, food):
    x = food.x* food.cell_size
    y = food.y * food.cell_size
    foodRect = pygame.Rect(x, y, food.cell_size, food.cell_size)
    pygame.draw.rect(screen, food.color, foodRect)
  def draw_grid(self,screen,settings):
    for x in range(0, settings.windows_width, settings.cell_size):
      pygame.draw.line(screen, settings.gray, (x, 0), (x, settings.windows_height))
    for y in range(0, settings.windows_height,settings.cell_size):
      pygame.draw.line(screen, settings.gray, (0, y), (settings.windows_width, y))
  def draw_score(self,screen, snake,settings):
    score=len(snake.snake_coords)-3
    font = pygame.font.SysFont(None, 40)
    score_str = "{:,}".format(score)
    score_image = font.render('Score: ' + score_str, True, settings.Green, settings.gray)
    score_rect = score_image.get_rect()
    score_rect.topleft = (settings.windows_width - 200, 10)
    screen.blit(score_image, score_rect)
  def gameover(self,screen):
    font = pygame.font.SysFont(None, 40)
    tips = font.render('Press Q or ESC to quit; Press anykey to continue', True, (65, 105, 225))
    screen.blit(tips, (80, 300))
    pygame.display.update()
    while True:
      for event in pygame.event.get():
        if event.type == QUIT:
          pygame.quit()
          sys.exit()
        elif event.type == KEYDOWN:
          if event.key == K_ESCAPE or event.key == K_q: # 终止程序
            pygame.quit()
            sys.exit() # 终止程序
          else:
            return # 结束此函数, 重新开始游戏
#主函数
def main_game():
  pygame.init() #初始化gygame
  settings=Settings()
  screen=pygame.display.set_mode((settings.windows_width,settings.windows_height))
  pygame.display.set_caption("贪吃蛇游戏")
  snake_speed_clock = pygame.time.Clock() # 创建Pygame时钟对象
  screen.fill(settings.white)
  gf=GameFunction(screen)
  while True:
    snake = Snake(settings)
    food = Food(settings)
    while True:
      gf.check_event(snake,settings)
      snake.snake_move(settings)
      alive = snake.snake_is_alive(settings) # 判断蛇的死活
      if not alive: # 如果挂了,则终止循环,跳出run_game函数,执行gameover
        break
      gf.snake_eat_foods(snake,food,settings)
      gf.update(snake,food,settings,screen,snake_speed_clock)
    gf.gameover(screen)        #游戏结束
if __name__=='__main__':
  main_game()

程序效果如下:

python 使用pygame工具包实现贪吃蛇游戏(多彩版)

总结

1、通过上述的代码,功能基本实现

2、多彩版的蛇的色彩太鲜艳,看起来太难受了

3、多彩版的在运行中存在不稳定情况,具体原因还没查看,请大家帮忙指出代码中的问题。

以上所述是小编给大家介绍的python 使用pygame工具包实现贪吃蛇游戏,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
Python中使用Flask、MongoDB搭建简易图片服务器
Feb 04 Python
Python使用BeautifulSoup库解析HTML基本使用教程
Mar 31 Python
python实现简单购物商城
May 21 Python
python 简单搭建阻塞式单进程,多进程,多线程服务的实例
Nov 01 Python
python打包压缩、读取指定目录下的指定类型文件
Apr 12 Python
python机器学习之神经网络实现
Oct 13 Python
linux环境下Django的安装配置详解
Jul 22 Python
春节到了 教你使用python来抢票回家
Jan 06 Python
常用python爬虫库介绍与简要说明
Jan 25 Python
python3 自动打印出最新版本执行的mysql2redis实例
Apr 09 Python
python实现图书馆抢座(自动预约)功能的示例代码
Sep 29 Python
vue.js刷新当前页面的实例讲解
Dec 29 Python
python常见字符串处理函数与用法汇总
Oct 30 #Python
pygame库实现俄罗斯方块小游戏
Oct 29 #Python
pygame实现俄罗斯方块游戏(对战篇1)
Oct 29 #Python
Numpy中对向量、矩阵的使用详解
Oct 29 #Python
pygame实现俄罗斯方块游戏(AI篇2)
Oct 29 #Python
pygame实现俄罗斯方块游戏(AI篇1)
Oct 29 #Python
基于Django统计博客文章阅读量
Oct 29 #Python
You might like
php中heredoc与nowdoc介绍
2014/12/25 PHP
Zend Framework教程之配置文件application.ini解析
2016/03/10 PHP
php生成图片验证码的方法
2016/04/15 PHP
CI框架AR操作(数组形式)实现插入多条sql数据的方法
2016/05/18 PHP
php中通过eval实现字符串格式的计算公式
2017/03/18 PHP
PHP大文件分片上传的实现方法
2018/10/28 PHP
Yii2.0 RESTful API 基础配置教程详解
2018/12/26 PHP
PHP检测一个数组有没有定义的方法步骤
2019/07/20 PHP
js 深拷贝函数
2008/12/04 Javascript
jquery 框架使用教程 AJAX篇
2009/10/11 Javascript
两种简单实现菜单高亮显示的JS类代码
2010/06/27 Javascript
jquery实现点击文字可编辑并修改保存至数据库
2014/04/15 Javascript
JavaScript计算两个日期时间段内日期的方法
2015/03/16 Javascript
jquery插件bxslider用法实例分析
2015/04/16 Javascript
Webpack 实现 Node.js 代码热替换
2015/10/22 Javascript
JS使用cookie实现DIV提示框只显示一次的方法
2015/11/05 Javascript
Jquery 1.9.1源码分析系列(十二)之筛选操作
2015/12/02 Javascript
学习JavaScript设计模式之模板方法模式
2016/01/20 Javascript
JS作用域闭包、预解释和this关键字综合实例解析
2016/12/16 Javascript
vue里面父组件修改子组件样式的方法
2018/02/03 Javascript
JavaScript递归函数定义与用法实例分析
2019/01/24 Javascript
尝试用最短的Python代码来实现服务器和代理服务器
2016/06/23 Python
python爬虫headers设置后无效的解决方法
2017/10/21 Python
分享Pycharm中一些不为人知的技巧
2018/04/03 Python
django框架自定义用户表操作示例
2018/08/07 Python
python中字符串数组逆序排列方法总结
2019/06/23 Python
python如何给字典的键对应的值为字典项的字典赋值
2019/07/05 Python
PIL对上传到Django的图片进行处理并保存的实例
2019/08/07 Python
python中的itertools的使用详解
2020/01/13 Python
python下载卫星云图合成gif的方法示例
2020/02/18 Python
Python 多线程共享变量的实现示例
2020/04/17 Python
数组越界问题
2015/10/21 面试题
农民致富事迹材料
2014/01/23 职场文书
汽车运用工程专业求职信
2014/06/18 职场文书
小学校园文化建设汇报材料
2014/08/19 职场文书
2020优秀员工演讲稿(三篇)
2019/10/17 职场文书