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中字典的合并值相加与异或对比
Jun 04 Python
Python错误: SyntaxError: Non-ASCII character解决办法
Jun 08 Python
python语言中with as的用法使用详解
Feb 23 Python
Python3.4 splinter(模拟填写表单)使用方法
Oct 13 Python
python代码 输入数字使其反向输出的方法
Dec 22 Python
Python的log日志功能及设置方法
Jul 11 Python
cProfile Python性能分析工具使用详解
Jul 22 Python
Django 用户认证组件使用详解
Jul 23 Python
python matplotlib库直方图绘制详解
Aug 10 Python
如何教少儿学习Python编程
Jul 10 Python
python 实现图片批量压缩的示例
Dec 18 Python
pytorch 运行一段时间后出现GPU OOM的问题
Jun 02 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
DC动画很好看?新作烂得令人发指,名叫《红色之子》
2020/04/09 欧美动漫
php中存储用户ID和密码到mysql数据库的方法
2013/02/06 PHP
PHP读取大文件的几种方法介绍
2016/10/27 PHP
PHP数组内存利用率低和弱类型详细解读
2017/08/10 PHP
PHP实现的文件浏览器功能简单示例
2019/09/12 PHP
JS测试显示屏分辨率以及屏幕尺寸的方法
2013/11/22 Javascript
JavaScript中实现sprintf、printf函数
2015/01/27 Javascript
js插件设置innerHTML时在IE8下提示“未知运行时错误”解决方法
2015/04/25 Javascript
详细解读JavaScript编程中的Promise使用
2015/07/27 Javascript
js确认框confirm()用法实例详解
2016/01/07 Javascript
javascript实现起伏的水波背景效果
2016/05/16 Javascript
jquery实现图片平滑滚动详解
2017/03/22 jQuery
JS将unicode码转中文方法
2017/05/08 Javascript
JavaScript基础进阶之数组方法总结(推荐)
2017/09/04 Javascript
Validform验证时可以为空否则按照指定格式验证
2017/10/20 Javascript
jquery的 filter()方法使用教程
2018/03/22 jQuery
JavaScript实现数字前补“0”的五种方法示例
2019/01/03 Javascript
什么时候不能在 Node.js 中使用 Lock Files
2019/06/24 Javascript
js利用拖放实现添加删除
2020/08/27 Javascript
vue-cli3自动消除console.log()的调试信息方式
2020/10/21 Javascript
JavaScript 中判断变量是否为数字的示例代码
2020/10/22 Javascript
python ElementTree 基本读操作示例
2009/04/09 Python
Python读取mp3中ID3信息的方法
2015/03/05 Python
Python抓取百度查询结果的方法
2015/07/08 Python
python简单实现刷新智联简历
2016/03/30 Python
Python自定义函数定义,参数,调用代码解析
2017/12/27 Python
python topN 取最大的N个数或最小的N个数方法
2018/06/04 Python
Python 实用技巧之利用Shell通配符做字符串匹配
2019/08/23 Python
简单了解django文件下载方式
2020/02/10 Python
python实现一次性封装多条sql语句(begin end)
2020/06/06 Python
Python 处理日期时间的Arrow库使用
2020/08/18 Python
啤酒销售实习自我鉴定
2013/09/24 职场文书
招商业务员岗位职责
2013/12/16 职场文书
趣味运动会广播稿
2014/09/13 职场文书
MySQL中IO问题的深入分析与优化
2022/04/02 MySQL
Javascript webpack动态import
2022/04/19 Javascript