程序设计分析
Python对于游戏开发比较简洁,此次利用Python中的第三方库Pygame开发一个贪吃蛇游戏。
开始游戏界面:选择游戏难度(单机键盘选择):1.简单;2.一般;3.有、难
游戏界面:随机生成食物,当前得分
结束界面:最终得分,是否超过记录
拓展功能:背景音乐
一、开始游戏界面
使用while True循环对界面次序刷新,绘制字体以及添加背景图片进入当中,对按键进行监听,123 分别表示选中不同的难度,即蛇移动的速度。
import pygame, sys
import random
import time
W = 600 # 宽
H = 400 # 高
fps = 12 # 速度
size = (W, H)
ROW = 20 # 行
COL = 30 # 列
snake_color = (200, 200, 200) # 蛇的颜色
MSGCOLOR = (3, 54, 73) # 背景颜色
MSGBGCOLOR = (255, 255, 193) # 字体颜色
blue = (64, 160, 171) # 蓝色
count = 0 # 计分
pos = [160, 130] # 坐标
pos1 = [190, 200] # 坐标1
# 初始化
pygame.init()
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Greedy Snake") # 窗口标题
out = True
while out:
FPSClock = pygame.time.Clock()
img = pygame.image.load("bg.png")
screen.blit(img, (0, 0))
# 添加文字
font = pygame.font.Font("STKAITI.TTF", 24) # 字体设置
fontRect = font.render("请选择游戏难度 (单击键盘选择)", True, MSGCOLOR, MSGBGCOLOR)
fontRect1 = font.render("1:简单 2:一般 3:有、难 ", True, MSGCOLOR, MSGBGCOLOR)
screen.blit(fontRect, pos)
screen.blit(fontRect1, pos1)
for event in pygame.event.get(): # 接收单击事件
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN: # 键盘单击事件
print(event.key)
if event.key == 1073741913: # 控制台输出1
fps = 8
out = False
elif event.key == 1073741914: # 控制台输出2
fps = 16
out = False
elif event.key == 1073741915: # 控制台输出3
fps = 24
out = False
pygame.display.update()
FPSClock.tick(fps)
time.sleep(1)
二、游戏界面
1.使用point类划分
Point类可以对整个屏幕进行划分为多少个小格子,使用到python当中的类进行定义
class Point:
row = 0
col = 0
def __init__(self, row=0, col=0):
self.row = row
self.col = col
def copy(self):
return Point(row=self.row, col=self.col)
2.绘制蛇
给定初始化蛇头坐标,蛇头的颜色, 蛇的身体,均为Point类的对象。
蛇的移动方向给定一个向左。
获取顶点坐标,返回的也是Point对象
# 坐标定义 蛇头
head = Point(row=int(ROW / 2), col=int(COL / 2))
head_color = (80, 80, 128)
# 蛇的身体,使用一个列表进行储存对应的值构成一个数组,新的蛇初始化给3个长度的身体
snakenodes = [
Point(head.row, head.col),
Point(head.row, head.col + 1),
Point(head.row, head.col + 2)]
# 求出这个顶点的坐标
def rect(Point, color):
left = Point.col * (W / COL)
top = Point.row * (H / ROW)
pygame.draw.rect(screen, color, (left, top, W / COL, H / ROW))
# 移动方向
dir = 'left'
3.随机生成食物
随机食物的产生,不能出现在蛇头或者蛇的身体的位置。
# 随机产生食物
def gen_food():
while True:
pos = Point(row=random.randint(0, ROW - 1), col=random.randint(0, COL - 1))
# 判断产生的食物是否与蛇相撞
is_coll = False
# 1.与蛇头相撞
if head.row == pos.row and head.col == pos.col:
is_coll = True
# 2.食物与蛇的身体相撞
for node in snakenodes:
if node.row == pos.row and node.col == pos.col:
is_coll = True
break
if not is_coll:
break
return pos
# 食物坐标
food = gen_food()
food_color = (255, 255, 0)
4.背景音乐
pygame.mixer.music:Pygame 中控制音频流的模块。
# 设置音乐
file=r'M:\大学\Pr\音乐\Trippy Love - Vexento.mp3' # 音乐路径
pygame.mixer.init() # 初始化
track=pygame.mixer.music.load(file) # 加载音乐文件
pygame.mixer.music.play() # 开始播放音乐流
5.控制移动
对键盘上下左右键进行监听。
quit = True
while quit:
screen = pygame.display.set_mode((600, 460))
FPSClock = pygame.time.Clock()
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
# print(event.key)
if event.key == 1073741906 or event.key == pygame.K_UP:
if dir == 'left' or dir == 'right':
dir = 'up'
elif event.key == 1073741905 or event.key == pygame.K_DOWN:
if dir == 'left' or dir == 'right':
dir = 'down'
if event.key == 1073741904 or event.key == pygame.K_LEFT:
if dir == 'up' or dir == 'down':
dir = 'left'
if event.key == 1073741903 or event.key == pygame.K_RIGHT:
if dir == 'up' or dir == 'down':
dir = 'right'
6.窗口实现
在窗口当中对实体进行绘制,并且加入逻辑。
蛇头经过食物,计分的相加,以及再一次的产生新的食物。
# 1. 画一个方块,也就是整个背景方块
# pygame.draw.rect(screen, bg_color, (0, 0, W, H))
# 2. 使用图片填入的方式
img = pygame.image.load("bg.png")
screen.blit(img, (0, 0))
# 用一个白框进行分割开
pygame.draw.rect(screen, (255, 255, 255), (0, H, W, 10))
# 下方显示分数的方块
pygame.draw.rect(screen, blue, (0, H + 10, W, 60))
# 显示当前得分
font = pygame.font.Font("STKAITI.TTF", 24)
fontRect = font.render(" 当前得分 : " + str(count), True, MSGCOLOR, blue)
screen.blit(fontRect, (420, 420))
# 画出蛇头
rect(head, head_color)
# 画出食物
rect(food, food_color)
# 画出蛇身
for node in snakenodes:
rect(node, snake_color)
# 吃食物,当蛇头与食物重合的时候吃掉食物,此时蛇的长度加一,在原先的删除蛇尾的时候加上一个判断即可
eat = (head.row == food.row and head.col == food.col)
# 食物重新产生,食物重新产生的时候,对计分进行增加
if eat:
food = gen_food()
if fps == 8:
count += 3
elif fps == 16:
count += 5
elif fps == 24:
count += 10
# 处理蛇身
# 1.把蛇头插入到数组列表当中
snakenodes.insert(0, head.copy())
# 2.删除最后一个蛇尾节点,表示没有吃到食物就删除尾节点
if not eat:
snakenodes.pop()
# 移动头
if dir == 'left':
head.col -= 1
elif dir == 'right':
head.col += 1
elif dir == 'up':
head.row -= 1
elif dir == 'down':
head.row += 1
7.碰撞判断
对于不同游戏结束的不同显示:撞墙、撞到自己。
# 与墙壁相撞
dead = False
if head.row < 0 or head.col < 0 or head.row >= ROW or head.col >= COL:
dead = True
print("撞墙")
for snake in snakenodes:
if head.col == snake.col and head.row == snake.row:
dead = True
print("撞到自己")
break
if dead:
print("游戏结束")
quit = False
pygame.display.update()
FPSClock.tick(fps)
三、结束界面
1.记录得分
在前面选择不同的难度之后,每一次吃掉食物之后。分数加的也不同,在这里对最终得分记录下来,并且获取count文件进行比较,判断是否打破记录。打破记录,把新的记录写进文件当中。
# 记录最高分到count文件当中
f = open("count", "r")
counts = f.read()
if count > int(counts):
file = open("count", "w")
file.write(str(count))
file.close()
f.close()
2.得分展示
得分已经获取到了,根据是否打破了记录来绘制不同的效果。同样的使用这个pygame进行初始化构造出一个新的窗口。
若在得分没有超过count文件当中的得分记录的时候就会打印出继续加油,反之打印的是恭喜你打破记录。count得分进行输出的时候,count是一个int型的变量,要转换成string才能进行绘制,所以在上面使用到了 str() 函数,数据类型转换。
# 隔开1秒的时间,显得页面的交互不那么突然
time.sleep(1)
# 得分展示
pygame.init()
screen = pygame.display.set_mode(size)
pygame.display.set_caption("贪吃蛇")
while True:
FPSClock = pygame.time.Clock()
pygame.draw.rect(screen, MSGBGCOLOR, (0, 0, W, H))
# 添加文字
font = pygame.font.Font("STKAITI.TTF", 24)
if count <= int(counts):
fontRect = font.render(" 你的得分是: " + str(count) + " 继续加油哦!", True, MSGCOLOR, MSGBGCOLOR)
elif count > int(counts):
fontRect = font.render(" 恭喜你打破了记录!你的得分是 : " + str(count), True, MSGCOLOR, MSGBGCOLOR)
screen.blit(fontRect, (140, 140))
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
pygame.display.update()
FPSClock.tick(fps)