python制作贪吃蛇游戏
游戏思路
游戏环境初始化:
使用 turtle 设置游戏窗口,定义窗口的大小、背景颜色和标题。
初始化得分板用于显示当前分数和最高分。
贪吃蛇的创建:
设置蛇头的起始位置、颜色和形状。在这段代码中,蛇被定义为一系列“segments”的集合,初始只有一个代表蛇头。
为蛇定义移动方向,初始化为“停止”。
食物的生成:
创建食物对象,并将其放置在屏幕上的随机位置。
控制机制:
为游戏定义键盘响应事件,允许玩家使用键盘(W, A, S, D 键)来控制蛇的移动方向。
创建移动函数 move() 来根据蛇头的当前方向更新其位置。
游戏主循环:
创建一个无限循环 while True:,用于不断更新屏幕、检测碰撞以及移动蛇。
检查蛇头是否与屏幕边缘相撞,如果是,游戏结束并重置蛇的位置。
检查蛇头是否与食物相撞,如果是,移动食物到新的位置,增长蛇的长度,并更新得分。
更新贪吃蛇身体,确保蛇身跟随头部移动。
检查蛇头是否与身体的其他部分相撞,如果是,游戏结束。
得分和游戏结束逻辑:
通过在碰撞的情况下重置游戏来处理游戏结束,隐藏蛇身,清空分数并重置延迟。
在吃到食物时增加得分,并且可能更新最高分。
延迟和速度控制:
设置游戏每一帧的延迟时间 delay,以控制蛇的移动速度。
在蛇吃到食物后,适当减少延迟时间,让游戏随着蛇的增长逐渐加快。
绘制和更新得分板:
使用 turtle 写出得分板上的文字,每次得分更新时,清除得分板并重新写上新的得分信息。
游戏难点
蛇身增长逻辑:处理蛇在吃到食物之后如何增长是一个挑战。需要更新蛇的segments数组,并且在蛇移动时保持身段间的相对位置关系。
碰撞检测:需要准确检测到蛇头与食物的碰撞以及蛇头与身体其它部分的碰撞,还有蛇头与墙的碰撞。
移动和控制:要流畅地控制贪吃蛇的移动,尤其是当蛇长度增加时,其移动会变得更为复杂,需要在不出现bug的前提下正确处理用户的输入。
性能管理:随着游戏进行,蛇变长和分数的增加可能会导致游戏速度加快,这可能会对游戏的性能造成影响,特别是在使用turtle模块的情况下,因为它并不是为高性能的游戏设计的。
游戏后续改进
加入音效,当蛇吃到食物或游戏结束时可以播放音效。
改善图形,使用更高级的图形库如pygame或pyglet代替turtle,这可以提供更流畅的动画和更丰富的视觉效果。
增加游戏功能:
添加不同级别的难度,例如随着分数的增加墙或障碍物出现,或者增加蛇的速度。
引入不同类型的“食物”,其中一些可能暂时加快或减慢蛇的速度,或者使蛇暂时缩短。
实现一个高分榜,用于记录玩家的高分。
代码改进:
优化碰撞检测算法,以处理更长的蛇以及更快的速度。
如果碰撞检测变得性能瓶颈,可以考虑减少检测频率或者使用空间分割技术来减少每个时间步需要检测的碰撞数量。
使用面向对象编程,定义一个蛇类和食物类,使得代码更加模块化和可复用。
渐进增加难度:
让游戏难度能够随着游戏时间的增长而逐渐增加,如通过递减delay来提高蛇的移动速度,或者是通过增加游戏场景中障碍物的数量。
贪吃蛇代码
import turtle
import time
import random
delay = 0.1
score = 0
high_score = 0
# 设置屏幕
wn = turtle.Screen()
wn.title("贪吃蛇游戏")
wn.bgcolor("black")
wn.setup(width=600, height=600)
wn.tracer(0) # 关闭屏幕更新
# 贪吃蛇的头部
head = turtle.Turtle()
head.speed(0)
head.shape("square")
head.color("white")
head.penup()
head.goto(0, 0)
head.direction = "stop"
# 食物
food = turtle.Turtle()
food.speed(0)
food.shape("circle")
food.color("red")
food.penup()
food.goto(0, 100)
segments = []
# 计分板
score_board = turtle.Turtle()
score_board.speed(0)
score_board.shape("square")
score_board.color("white")
score_board.penup()
score_board.hideturtle()
score_board.goto(0, 260)
score_board.write("得分:0 最高分:0", align="center", font=("Courier", 24, "normal"))
# 函数:控制移动方向
def go_up():
if head.direction != "down":
head.direction = "up"
def go_down():
if head.direction != "up":
head.direction = "down"
def go_left():
if head.direction != "right":
head.direction = "left"
def go_right():
if head.direction != "left":
head.direction = "right"
def move():
if head.direction == "up":
y = head.ycor()
head.sety(y + 20)
if head.direction == "down":
y = head.ycor()
head.sety(y - 20)
if head.direction == "left":
x = head.xcor()
head.setx(x - 20)
if head.direction == "right":
x = head.xcor()
head.setx(x + 20)
# 键盘绑定
wn.listen()
wn.onkeypress(go_up, "w")
wn.onkeypress(go_down, "s")
wn.onkeypress(go_left, "a")
wn.onkeypress(go_right, "d")
# 主游戏循环
while True:
wn.update()
# 检查碰撞边界
if head.xcor()>290 or head.xcor()<-290 or head.ycor()>290 or head.ycor()<-290:
time.sleep(1)
head.goto(0, 0)
head.direction = "stop"
# 隐藏段
for segment in segments:
segment.goto(1000, 1000)
# 清除段的列表
segments.clear()
# 重置分数
score = 0
# 重置延迟
delay = 0.1
score_board.clear()
score_board.write("得分:{} 最高分:{}".format(score, high_score), align="center", font=("Courier", 24, "normal"))
# 检查食物碰撞
if head.distance(food) < 20:
# 移动食物到随机位置
x = random.randint(-290, 290)
y = random.randint(-290, 290)
food.goto(x, y)
# 添加段
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("grey")
new_segment.penup()
segments.append(new_segment)
# 缩短延迟
delay -= 0.001
# 增加分数
score += 10
if score > high_score:
high_score = score
score_board.clear()
score_board.write("得分:{} 最高分:{}".format(score, high_score), align="center", font=("Courier", 24, "normal"))
# 移动段的末尾到第一个
for index in range(len(segments)-1, 0, -1):
x = segments[index-1].xcor()
y = segments[index-1].ycor()
segments[index].goto(x, y)
# 移动段0 到头部位置
if len(segments) > 0:
x = head.xcor()
y = head.ycor()
segments[0].goto(x,y)
move()
# 检查头部和身体的碰撞
for segment in segments:
if segment.distance(head) < 20:
time.sleep(1)
head.goto(0,0)
head.direction = "stop"
# 隐藏段
for segment in segments:
segment.goto(1000, 1000)
# 清除段
segments.clear()
# 重置得分
score = 0
# 重置延迟
delay = 0.1
# 更新得分显示
score_board.clear()
score_board.write("得分:{} 最高分:{}".format(score, high_score), align="center", font=("Courier", 24, "normal"))
time.sleep(delay)
wn.mainloop()