PyGame贪吃蛇的实现代码示例


Posted in Python onNovember 21, 2018

最近帮人做了个贪吃蛇的游戏(交作业用),很简单,界面如下:

开始界面:

PyGame贪吃蛇的实现代码示例

游戏中界面:

PyGame贪吃蛇的实现代码示例

是不是很简单、朴素。(欢迎大家访问GitHub)

游戏是基于PyGame框架制作的,程序核心逻辑如下:

  • 游戏界面分辨率是640*480,蛇和食物都是由1个或多个20*20像素的正方形块儿(为了方便,下文用点表示20*20像素的正方形块儿)组成,这样共有32*24个点,使用pygame.draw.rect来绘制每一个点;
  • 初始化时蛇的长度是3,食物是1个点,蛇初始的移动的方向是右,用一个数组代表蛇,数组的每个元素是蛇每个点的坐标,因此数组的第一个坐标是蛇尾,最后一个坐标是蛇头;
  • 游戏开始后,根据蛇的当前移动方向,将蛇运动方向的前方的那个点append到蛇数组的末位,再把蛇尾去掉,蛇的坐标数组就相当于往前挪了一位;
  • 如果蛇吃到了食物,即蛇头的坐标等于食物的坐标,那么在第2点中蛇尾就不用去掉,就产生了蛇长度增加的效果;食物被吃掉后,随机在空的位置(不能与蛇的身体重合)再生成一个;
  • 通过PyGame的event监控按键,改变蛇的方向,例如当蛇向右时,下一次改变方向只能向上或者向下;
  • 当蛇撞上自身或墙壁,游戏结束,蛇头装上自身,那么蛇坐标数组里就有和舌头坐标重复的数据,撞上墙壁则是蛇头坐标超过了边界,都很好判断;
  • 其他细节:做了个开始的欢迎界面;食物的颜色随机生成;吃到实物的时候有声音提示等。

代码:

#!/usr/bin/env python 
# -*- coding:utf-8 -*- 

""" 
@version: v1.0 
@author: Harp
@contact: liutao25@baidu.com 
@software: PyCharm 
@file: MySnake.py 
@time: 2018/1/15 0015 23:40 
"""


import pygame
from os import path
from sys import exit
from time import sleep
from random import choice
from itertools import product
from pygame.locals import QUIT, KEYDOWN


def direction_check(moving_direction, change_direction):
  directions = [['up', 'down'], ['left', 'right']]
  if moving_direction in directions[0] and change_direction in directions[1]:
    return change_direction
  elif moving_direction in directions[1] and change_direction in directions[0]:
    return change_direction
  return moving_direction


class Snake:

  colors = list(product([0, 64, 128, 192, 255], repeat=3))[1:-1]

  def __init__(self):
    self.map = {(x, y): 0 for x in range(32) for y in range(24)}
    self.body = [[100, 100], [120, 100], [140, 100]]
    self.head = [140, 100]
    self.food = []
    self.food_color = []
    self.moving_direction = 'right'
    self.speed = 4
    self.generate_food()
    self.game_started = False

  def check_game_status(self):
    if self.body.count(self.head) > 1:
      return True
    if self.head[0] < 0 or self.head[0] > 620 or self.head[1] < 0 or self.head[1] > 460:
      return True
    return False

  def move_head(self):
    moves = {
      'right': (20, 0),
      'up': (0, -20),
      'down': (0, 20),
      'left': (-20, 0)
    }
    step = moves[self.moving_direction]
    self.head[0] += step[0]
    self.head[1] += step[1]

  def generate_food(self):
    self.speed = len(self.body) // 16 if len(self.body) // 16 > 4 else self.speed
    for seg in self.body:
      x, y = seg
      self.map[x//20, y//20] = 1
    empty_pos = [pos for pos in self.map.keys() if not self.map[pos]]
    result = choice(empty_pos)
    self.food_color = list(choice(self.colors))
    self.food = [result[0]*20, result[1]*20]


def main():
  key_direction_dict = {
    119: 'up', # W
    115: 'down', # S
    97: 'left', # A
    100: 'right', # D
    273: 'up', # UP
    274: 'down', # DOWN
    276: 'left', # LEFT
    275: 'right', # RIGHT
  }

  fps_clock = pygame.time.Clock()
  pygame.init()
  pygame.mixer.init()
  snake = Snake()
  sound = False
  if path.exists('eat.wav'):
    sound_wav = pygame.mixer.Sound("eat.wav")
    sound = True
  title_font = pygame.font.SysFont('arial', 32)
  welcome_words = title_font.render('Welcome to My Snake', True, (0, 0, 0), (255, 255, 255))
  tips_font = pygame.font.SysFont('arial', 24)
  start_game_words = tips_font.render('Click to Start Game', True, (0, 0, 0), (255, 255, 255))
  close_game_words = tips_font.render('Press ESC to Close', True, (0, 0, 0), (255, 255, 255))
  gameover_words = title_font.render('GAME OVER', True, (205, 92, 92), (255, 255, 255))
  win_words = title_font.render('THE SNAKE IS LONG ENOUGH AND YOU WIN!', True, (0, 0, 205), (255, 255, 255))
  screen = pygame.display.set_mode((640, 480), 0, 32)
  pygame.display.set_caption('My Snake')
  new_direction = snake.moving_direction
  while 1:
    for event in pygame.event.get():
      if event.type == QUIT:
        exit()
      elif event.type == KEYDOWN:
        if event.key == 27:
          exit()
        if snake.game_started and event.key in key_direction_dict:
          direction = key_direction_dict[event.key]
          new_direction = direction_check(snake.moving_direction, direction)
      elif (not snake.game_started) and event.type == pygame.MOUSEBUTTONDOWN:
        x, y = pygame.mouse.get_pos()
        if 213 <= x <= 422 and 304 <= y <= 342:
          snake.game_started = True
    screen.fill((255, 255, 255))
    if snake.game_started:
      snake.moving_direction = new_direction # 在这里赋值,而不是在event事件的循环中赋值,避免按键太快
      snake.move_head()
      snake.body.append(snake.head[:])
      if snake.head == snake.food:
        if sound:
          sound_wav.play()
        snake.generate_food()
      else:
        snake.body.pop(0)
      for seg in snake.body:
        pygame.draw.rect(screen, [0, 0, 0], [seg[0], seg[1], 20, 20], 0)
      pygame.draw.rect(screen, snake.food_color, [snake.food[0], snake.food[1], 20, 20], 0)
      if snake.check_game_status():
        screen.blit(gameover_words, (241, 310))
        pygame.display.update()
        snake = Snake()
        new_direction = snake.moving_direction
        sleep(3)
      elif len(snake.body) == 512:
        screen.blit(win_words, (33, 210))
        pygame.display.update()
        snake = Snake()
        new_direction = snake.moving_direction
        sleep(3)
    else:
      screen.blit(welcome_words, (188, 100))
      screen.blit(start_game_words, (236, 310))
      screen.blit(close_game_words, (233, 350))
    pygame.display.update()
    fps_clock.tick(snake.speed)


if __name__ == '__main__':
  main()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python模块学习 filecmp 文件比较
Aug 27 Python
python Django批量导入数据
Mar 25 Python
插入排序_Python与PHP的实现版(推荐)
May 11 Python
python进阶_浅谈面向对象进阶
Aug 17 Python
Ubuntu下使用python读取doc和docx文档的内容方法
May 08 Python
python文件操作之批量修改文件后缀名的方法
Aug 10 Python
Python利用字典破解WIFI密码的方法
Feb 27 Python
python 获取等间隔的数组实例
Jul 04 Python
关于numpy中eye和identity的区别详解
Nov 29 Python
python 异步async库的使用说明
May 04 Python
python爬虫工具例举说明
Nov 30 Python
用python计算文件的MD5值
Dec 23 Python
python+flask实现API的方法
Nov 21 #Python
python实现事件驱动
Nov 21 #Python
python事件驱动event实现详解
Nov 21 #Python
python程序封装为win32服务的方法
Mar 07 #Python
pygame游戏之旅 添加icon和bgm音效的方法
Nov 21 #Python
pygame游戏之旅 添加游戏暂停功能
Nov 21 #Python
使用50行Python代码从零开始实现一个AI平衡小游戏
Nov 21 #Python
You might like
PHP如何抛出异常处理错误
2011/03/02 PHP
浅析PHP编程中10个最常见的错误
2014/08/08 PHP
学习php设计模式 php实现桥梁模式(bridge)
2015/12/07 PHP
PHP实现可添加水印与生成缩略图的图片处理工具类
2018/01/16 PHP
Javascript 强制类型转换函数
2009/05/17 Javascript
javascript 跨浏览器开发经验总结(五) js 事件
2010/05/19 Javascript
Jquery 一次处理多个ajax请求的代码
2011/09/02 Javascript
检查输入的是否是数字使用keyCode配合onkeypress事件
2014/01/23 Javascript
jQuery实现表单提交时判断的方法
2014/12/13 Javascript
元素绑定click点击事件方法
2015/06/08 Javascript
深入浅析JavaScript函数前面的加号和叹号
2016/07/09 Javascript
js实现固定宽高滑动轮播图效果
2017/01/13 Javascript
整理关于Bootstrap模态弹出框的慕课笔记
2017/03/29 Javascript
vue.js单页面应用实例的简单实现
2017/04/10 Javascript
JavaScript实现三级联动菜单效果
2017/08/16 Javascript
基于bootstrop常用类总结(推荐)
2017/09/11 Javascript
jsonp跨域获取百度联想词的方法分析
2019/05/13 Javascript
node实现简单的增删改查接口实例代码
2019/08/22 Javascript
原生JS运动实现轮播图
2021/01/02 Javascript
[30:51]DOTA2上海特级锦标赛主赛事日 - 3 胜者组第二轮#1Liquid VS MVP.Phx第一局
2016/03/04 DOTA
Python中用PIL库批量给图片加上序号的教程
2015/05/06 Python
Python处理Excel文件实例代码
2017/06/20 Python
Python实现求解一元二次方程的方法示例
2018/06/20 Python
Python二叉树的遍历操作示例【前序遍历,中序遍历,后序遍历,层序遍历】
2018/12/24 Python
django框架实现一次性上传多个文件功能示例【批量上传】
2019/06/19 Python
python中添加模块导入路径的方法
2021/02/03 Python
简单html5代码获取地理位置
2014/03/31 HTML / CSS
海外淘书首选:AbeBooks
2017/07/31 全球购物
eBay爱尔兰站:eBay.ie
2019/08/09 全球购物
介绍一下SQL Server的全文索引
2013/08/15 面试题
送给程序员的20个Java集合面试问题
2014/08/06 面试题
班主任工作年限证明
2014/01/12 职场文书
办公自动化专业大学生职业规划书
2014/03/06 职场文书
2015年高校教师个人工作总结
2015/05/25 职场文书
本地通过nginx配置反向代理的全过程记录
2021/03/31 Servers
Win10系统下配置Java环境变量
2021/06/13 Java/Android