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中的函数用法入门教程
Sep 02 Python
wxPython框架类和面板类的使用实例
Sep 28 Python
python读取word文档的方法
May 09 Python
利用python爬取散文网的文章实例教程
Jun 18 Python
python+pygame简单画板实现代码实例
Dec 13 Python
python模块smtplib实现纯文本邮件发送功能
May 22 Python
Python实现获取邮箱内容并解析的方法示例
Jun 16 Python
Python小工具之消耗系统指定大小内存的方法
Dec 03 Python
Python实现读取并写入Excel文件过程解析
May 27 Python
python字符串的index和find的区别详解
Jun 20 Python
python 动态渲染 mysql 配置文件的示例
Nov 20 Python
Selenium浏览器自动化如何上传文件
Apr 06 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生成16位随机数的代码(两种方法)
2014/09/16 PHP
javascript window对象属性整理
2009/10/24 Javascript
Firefox下提示illegal character并出现乱码的原因
2010/03/25 Javascript
Prototype的Class.create函数解析
2011/09/22 Javascript
jquery实现marquee效果(文字或者图片的水平垂直滚动)
2013/01/07 Javascript
Textarea根据内容自适应高度
2013/10/28 Javascript
javascript判断office版本示例
2014/04/11 Javascript
javascript性能优化之DOM交互操作实例分析
2015/12/12 Javascript
javascript中的 object 和 function小结
2016/08/14 Javascript
Bootstrap图片轮播效果详解
2017/10/17 Javascript
vue2.0实现前端星星评分功能组件实例代码
2018/02/12 Javascript
node puppeteer(headless chrome)实现网站登录
2018/05/09 Javascript
在element-ui的el-tree组件中用render函数生成el-button的实例代码
2018/11/05 Javascript
用Cordova打包Vue项目的方法步骤
2019/02/02 Javascript
layui框架与SSM前后台交互的方法
2019/09/12 Javascript
[01:33]真香警告!DOTA2勇士令状不朽珍藏Ⅱ饰品欣赏
2018/06/26 DOTA
Python的迭代器和生成器使用实例
2015/01/14 Python
python字典操作实例详解
2017/11/16 Python
python学习笔记之列表(list)与元组(tuple)详解
2017/11/23 Python
Python浅复制中对象生存周期实例分析
2018/04/02 Python
python实现电脑自动关机
2018/06/20 Python
对python3中pathlib库的Path类的使用详解
2018/10/14 Python
在python中将字符串转为json对象并取值的方法
2018/12/31 Python
使用python将请求的requests headers参数格式化方法
2019/01/02 Python
Django的用户模块与权限系统的示例代码
2019/07/24 Python
python实现二分类的卡方分箱示例
2019/11/22 Python
numpy 声明空数组详解
2019/12/05 Python
Python3 获取文件属性的方式(时间、大小等)
2020/03/12 Python
iPython pylab模式启动方式
2020/04/24 Python
美国新兴城市生活方式零售商:VILLA
2017/12/06 全球购物
美国著名的家居用品购物网站:Bed Bath & Beyond
2018/01/05 全球购物
Proenza Schouler官方网站:纽约女装和配饰品牌
2019/01/03 全球购物
产品促销活动策划书
2014/01/15 职场文书
供应链金融服务方案
2014/05/25 职场文书
房屋鉴定委托书范本
2014/09/23 职场文书
小学生作文之《压岁钱的烦恼》
2019/09/27 职场文书