突然想把去年写的小游戏练习整合一下,写一个简单的教学文章吧。
该篇主要讲解利用python中turtle包制作小游戏,不涉及pygame的使用,仅用pycharm就可实现
0.理清游戏思路
要实现的效果如下图所示:
黑色是蛇,红色利用随机函数生成的苹果,蛇没吃到一个苹果,就会增一节,同时下一个苹果随机生成在框内。
蛇的运动通过刷新页面来表示,每刷新一次,画图函数会在蛇头位置多画一个小方格,并删除蛇尾位置的小方格。以此来实现蛇的运动。
蛇不可撞到边框,否则游戏失败(停止运行)。
其中,蛇和苹果利用海龟画图(turtle)实现。
1.turtle库
turtle是python自带的一个库,主要用于画图。(据说是像海龟爬图?
turtle库中自带许多画图函数:(这里只列举贪吃蛇所用到的部分函数)
up() | 起笔函数 |
goto(x,y) | 去到(x,y)位置的函数 |
forward(size) | 朝特定方向走,参数表示画线的长度 |
left(size) | 转向函数,参数为调转度数(蛇每次调转90度,则填90) |
begin_fill() | 无参,开始绘图(落笔) |
end_fill() | 无参,绘图结束 |
color(color_name) | 设置线条颜色,括号内填写颜色名称 |
因为该"画图"动作需要循环调用,因此可以写一个函数将该功能包裹起来,以方便多次循环使用。
该部分代码:
from turtle import *
from random import randrange
#注意导包,(以下需要用到随机函数,所以也要导包随机函数)
def square(x,y,size,color_name): #函数名称可自定义,参数:需要用的什么就设置什么
up()
goto(x,y) #画笔移动到某一点
color(color_name) #设置画笔颜色
begin_fill() #落笔开画
forward(size) #画笔画直线
left(90) #转向90度 以下代码段表示每次画一个小方格
forward(size)
left(90)
forward(size)
left(90)
forward(size)
left(90)
end_fill() #绘图结束
2.定义小蛇和苹果
蛇的初始长度肯定不能是一个小方格吧
这里我的初始小蛇定义了四个小方格的长度,每个小方格为10;(可自定义,提示:最好为整数,避免蛇头与苹果”对不上“的情况出现。)
snack=[[0,0],[10,0],[20,0],[30,0]]
apple_x=randrange(-20,20)*10 #定义小苹果,和苹果的位置坐标
apple_y=randrange(-20,20)*10
aim_x=0
aim_y=10 #蛇的起始位置坐标
定义动作函数
def change(x,y):
global aim_x,aim_y
aim_x=x
aim_y=y
3.”撞墙“的判断
先贴一下我的代码段
def inside():
if -210<=snack[-1][0]<=200 and -210<=snack[-1][1]<210 :
return True
else:
return False
inside函数判断小蛇是否在画布内,即是否撞墙。
这里我把画布的大小设置为420*420(210是均分坐标,从-210到+210)。因为蛇的每一节身子长度为10,所以判断条件为小蛇头部是否小于等于200的大小,小于返回true,可以继续运行,否则false,结束运行。
4.函数循环使用
相当于是把上述函数嵌套在一个新的Loop函数内了,以方便于每刷新一次就调用一次Loop。
clear()和update()连用——刷新:擦除旧的线,画上新的线。
def gameLoop (): #自定义循环函数
global apple_x,apple_y #需要用到外面的全局变量
clear() #擦除旧图的函数,清理函数
snack.append([snack[-1][0]+aim_x,snack[-1][1]+aim_y]) #小蛇的出现位置
if not inside(): #判断是否还在画布内
return
if snack[-1][0]!=apple_x or snack[-1][1]!=apple_y :
snack.pop(0) #判断小蛇安全前行,擦除尾部,使用pop函数删除
else:
apple_x=randrange(-20,20)*10 #吃到苹果,则随机生成另一个新的苹果
apple_y=randrange(-20,20)*10
for n in range(len(snack)):
square(snack[n][0],snack[n][1],10,"black") #调用画图函数,定义黑色小蛇,红色苹果
square(apple_x,apple_y,10,"red")
ontimer(gameLoop,200) #调用循环函数,每隔一段时间调用一次
update() #更新
5.收尾:设置画布、隐藏海龟画图小箭头、监听函数的使用、以及键盘操控
注意:setup(420,420,0,0)意为设置一个420*420大小的平面画布,先前210是正向坐标!!
setup(420,420,0,0) #设置画布
hideturtle() #隐藏海龟画图的小标签,为了美观
tracer(False) #不显示轨迹路线
listen() #监听函数
onkey(lambda :change(0,10),"w") #键盘操控,点击相应案件实现改变方向操作
onkey(lambda :change(0,-10),"s")
onkey(lambda :change(10,0),"d")
onkey(lambda :change(-10,0),"a")
gameLoop() #循环函数
done()
———————————————————————————————————————————
来一个代码整合:
from turtle import *
from random import randrange
def square(x,y,size,color_name):
up()
goto(x,y)
color(color_name)
begin_fill()
forward(size)
left(90)
forward(size)
left(90)
forward(size)
left(90)
forward(size)
left(90)
end_fill()
snack=[[0,0],[10,0],[20,0],[30,0]]
apple_x=randrange(-20,20)*10
apple_y=randrange(-20,20)*10
aim_x=0
aim_y=10
def change(x,y):
global aim_x,aim_y
aim_x=x
aim_y=y
def inside():
if -210<=snack[-1][0]<=200 and -210<=snack[-1][1]<210 :
return True
else:
return False
def gameLoop ():
global apple_x,apple_y
clear()
snack.append([snack[-1][0]+aim_x,snack[-1][1]+aim_y])
if not inside():
return
if snack[-1][0]!=apple_x or snack[-1][1]!=apple_y :
snack.pop(0)
else:
apple_x=randrange(-20,20)*10
apple_y=randrange(-20,20)*10
for n in range(len(snack)):
square(snack[n][0],snack[n][1],10,"black")
square(apple_x,apple_y,10,"red")
ontimer(gameLoop,200)
update()
setup(420,420,0,0)
hideturtle()
tracer(False)
listen()
onkey(lambda :change(0,10),"w")
onkey(lambda :change(0,-10),"s")
onkey(lambda :change(10,0),"d")
onkey(lambda :change(-10,0),"a")
gameLoop()
done()