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编写分析Python程序性能的工具的教程
Apr 01 Python
举例讲解Python中的身份运算符的使用方法
Oct 13 Python
Python中列表、字典、元组数据结构的简单学习笔记
Mar 20 Python
django模型层(model)进行建表、查询与删除的基础教程
Nov 21 Python
pandas.cut具体使用总结
Jun 24 Python
Django Rest framework频率原理与限制
Jul 26 Python
Python使用py2neo操作图数据库neo4j的方法详解
Jan 13 Python
python GUI库图形界面开发之PyQt5窗口控件QWidget详细使用方法
Feb 26 Python
使用openCV去除文字中乱入的线条实例
Jun 02 Python
keras 自定义loss层+接受输入实例
Jun 28 Python
python实现企业微信定时发送文本消息的示例代码
Nov 24 Python
pandas取dataframe特定行列的实现方法
May 24 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
融入意大利的咖啡文化
2021/03/03 咖啡文化
PHP SEO优化之URL优化方法
2011/04/21 PHP
PHP获取网页标题的3种实现方法代码实例
2014/04/11 PHP
PHP中数组的分组排序实例
2014/06/01 PHP
Nginx下配置codeigniter框架方法
2015/04/07 PHP
PHP实现原生态图片上传封装类方法
2016/11/08 PHP
PHP实现数组转JSon和JSon转数组的方法示例
2018/06/14 PHP
Laravel中的chunk组块结果集处理与注意问题
2018/08/15 PHP
php判断目录存在的简单方法
2019/09/26 PHP
js动态添加事件并可传参数示例代码
2013/10/21 Javascript
禁止页面刷新让F5快捷键及右键都无效
2014/01/22 Javascript
js的回调函数详解
2015/01/05 Javascript
JavaScript获取对象在页面中位置坐标的方法
2016/02/03 Javascript
js replace(a,b)之替换字符串中所有指定字符的方法
2016/08/17 Javascript
AngularJS轻松实现双击排序的功能
2016/08/30 Javascript
原生js开发的日历插件
2017/02/04 Javascript
详解vue跨组件通信的几种方法
2017/06/15 Javascript
Layui实现带查询条件的分页
2019/07/27 Javascript
解决$store.getters调用不执行的问题
2019/11/08 Javascript
Vue学习之常用指令实例详解
2020/01/06 Javascript
vscode 插件开发 + vue的操作方法
2020/06/05 Javascript
vue+iview实现分页及查询功能
2020/11/17 Vue.js
[00:34]拔城逐梦,热血永恒!2020(秋)完美世界城市挑战赛报名开启
2020/10/09 DOTA
opencv3/Python 稠密光流calcOpticalFlowFarneback详解
2019/12/11 Python
python 图像的离散傅立叶变换实例
2020/01/02 Python
Python3使用tesserocr识别字母数字验证码的实现
2021/01/29 Python
印度化妆品购物网站:Nykaa
2018/07/22 全球购物
世界排名第一的万圣节服装店:Spirit Halloween
2018/10/16 全球购物
error和exception有什么区别
2012/10/02 面试题
什么是封装
2013/03/26 面试题
党员群众路线承诺书
2014/05/20 职场文书
社区维稳工作方案
2014/06/06 职场文书
画展观后感
2015/06/17 职场文书
幼儿园毕业致辞
2015/07/29 职场文书
表扬信范文
2019/04/22 职场文书
python实战之一步一步教你绘制小猪佩奇
2021/04/22 Python