Mind+Python turtle 课程-08 弹球小游戏
课程目录:
功能介绍
经过前面课程的学习,我们已经掌握了利用turtle库创建屏幕的方式,也了解了在屏幕上如何获取鼠标指针的坐标。这节课将作为巩固课,主要巩固我们前面所学的知识,首先我们在屏幕上制作一个碰壁小球游戏,小球在指定区域内不断的碰壁反弹,之后新建一个拦球板对象,用来检测小球是否碰到拦球板,碰到则将积分增加,完成弹球小游戏的功能。课程会分为三个任务的形式进行,下表为课程任务及涉及到的知识点。
实现功能 | 知识点 | | 巩固复习turtle库的两种不同导入方式、Screen函数以及学习随机数randint函数的使用 | | | | 巩固学习获取鼠标坐标的方法、逻辑判断语句、多条件判断语句 |
背景图片下载: 链接:https://pan.baidu.com/s/1NkWgpmbwwixKAr5miJuwfA 提取码:lxdb
项目实践
任务一:碰壁小球
1任务分析前面我们已经学过了turtle库中Screen函数和Turtle函数的使用,这节课我们首先将巩固复习一下他们的用法,利用Screen函数创建一个屏幕,之后新建小球对象,让其在屏幕内不断的进行碰壁反弹运动。那么我们通过什么进行碰壁呢?下图为宽和高为w和h的屏幕。
通过上图屏幕我们可以看出判断左右是否碰到壁,其实可以通过检测x轴的坐标是否大于w/2或者小于-w/2来判断,也就是当x轴的坐标大于w/2或者小于-w/2时证明小球碰到了左右壁。而判断上下是否碰到壁,可以通过检测y轴的坐标是否大于h/2或者小于-h/2来判断,也就是当y轴的坐标大于h/2或者小于-h/2时证明小球碰到了上下壁。
2编写程序
from turtle import *#导入turtle库的所有工具 from random import randint #导入random的randint工具 from time import sleep#导入time的sleep工具 w,h= 480,360#设置屏幕的宽和高 screen = Screen()#把Screen的对象赋值给screen screen.bgcolor("black")#设置屏蔽背景为黑色 screen.setup(w,h)#初始设置宽和高 screen.bgpic("Background.gif") #背景设置# #------------------------- ball=Turtle(shape='circle')#新建ball对象,形状为圆形 ball.speed(0)#设置ball的速度为最快. ball.penup()#提笔,不留痕迹 ball.color("yellow","yellow")#设置ball的边框颜色填充颜色 x速度 = randint(2,3)#设置初始水平速度 y速度 = randint(2,3)#设置初始垂直速度 while True :#永久循环 x=ball.xcor() + x速度#获取移动前ball的x坐标值加上小球速度的速度值,得到移动后x坐标值 y=ball.ycor() + y速度#获取移动前ball的y坐标值加上小球速度的速度值,得到移动后y坐标值 ball.goto(x,y)#让小球到达坐标为(x,y)的坐标点 if x>w/2 or x<-w/2:#判断ball是否碰左右边缘的壁 x速度 = -x速度#如果碰到壁就同一速度反方向弹开 if y>h/2 or y<-h/2:#判断ball是否碰上下边缘的壁 y速度 = -y速度#如果碰到壁就同一速度反方向弹开 |
3运行效果
运行这段程序,我们可以看到弹出了一个星空背景的屏幕,屏幕内有一个黄色小球在不断的进行碰壁反弹运动。
4代码释义
4.1代码中randint函数的使用
x速度 = randint(2,3)#设置初始水平速度 y速度 = randint(2,3)#设置初始垂直速度 |
4.1.1代码解释 通过rendint函数在指定范围内生成一个小球的运动速度,代码中分别设置了小球的水平速度和垂直速度,并且规定最大值为3,最小值为2。
4.1.2randint函数 在turtle中randint(a,b)用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n: a <= n <= b。
任务二:生成拦球杆对象
1任务分析在任务一中,我们已经绘制了一个星空背景的屏幕,并让黄色小球在不断的进行碰壁反弹运动。这里我们需要生成另一个对象,也就是拦球杆,用来拦下小球。
2编写程序from turtle import *#导入turtle库的所有工具 from random import randint #导入random的randint工具 from time import sleep#导入time的sleep工具 w,h= 480,360#设置屏幕的宽和高 screen = Screen()#把Screen的对象赋值给screen screen.bgcolor("black")#设置屏蔽背景为黑色 screen.setup(w,h)#初始设置宽和高 screen.bgpic("Background.gif") #背景设置# screen.delay(0)#这里要设为0,否则很卡 #--------------------------------------------------- square =Turtle('square')#创建一个弹球小栏板 square.shapesize(0.5,5)#设定栏板的长宽尺寸,对应像素为高5像素,长为50像素 square.speed(0)#设定栏板速度为最大 square.penup()#抬笔 square.color('blue')#设定颜色为蓝色 square.sety(50-h/2)#固定纵坐标 #---------------------------------------------------- ball=Turtle(shape='circle')#新建ball对象,形状为圆形 ball.speed(0)#设置ball的速度为最快. ball.penup()#提笔,不留痕迹 ball.color("yellow","yellow")#设置ball的填充和边框颜色 x速度 = randint(2,3)#设置初始水平速度 y速度 = randint(2,3)#设置初始垂直速度 while True :#永久循环 x=ball.xcor() + x速度#获取移动前ball的x坐标值加上小车速度,得到移动后x坐标值 y=ball.ycor() + y速度#获取移动前ball的y坐标值加上小车速度,得到移动后y坐标值 ball.goto(x,y)#让小球到达坐标为(x,y)的坐标点 if x>w/2 or x<-w/2:#判断ball是否碰左右边缘的壁 x速度 = -x速度#如果碰到壁就同一速度反方向弹开 if y>h/2 or y<-h/2:#判断ball是否碰上下边缘的壁 y速度 = -y速度#如果碰到壁就同一速度反方向弹开 sleep(0.01)#推迟0.01秒再执行 |
注意:这里一定要加上sleep(0.01)否则小球会弹得很快,无法看清效果!
3运行效果运行程序我们发现,呈现的屏幕内小黄球还是在不断的碰壁反弹运动,此可以看到比任务一多了一个蓝色的小栏板。
4代码释义
4.1代码中对象的使用
square =Turtle('square')#创建一个弹球小栏板对象 square.shapesize(0.5,5)#设定栏板的长宽尺寸 square.speed(0)#设定栏板速度为最大 square.penup()#抬笔 square.color('blue')#设定颜色为蓝色 square.sety(50-h/2)#固定纵坐标 #---------------------------------------------------- ball=Turtle(shape='circle')#新建ball对象,形状为圆形 ball.speed(0)#设置ball的速度为最快. ball.penup()#提笔,不留痕迹 ball.color("yellow","yellow")#设置ball的填充和边框颜色 |
4.1.1代码解释 生成两个对象分别是小球和篮球板,并设置它们的相关属性和方法。
4.1.2什么是对象 在Python中定义什么是对象,拿球做例子。可以操作一个球,比如捡球、踢球、抛球等。我们把这些操作称为动作。还可以通过颜色、重量和大小来描述一个球。这些就是球的属性。在Python中,一个对象的特征也称为属性,动作称为方法。
4.1.3什么是属性 属性就是你所知道的关于球的所有方面,包括球的形状、大小、颜色、重量等。
4.1.3什么是方法 方法就是可以对对象做的操作,它们是一些代码块。可以调用这些代码来完成某个工作,是不是很熟悉?方法其实就是在对象中的函数。函数能做到的,方法都能做到,包括传递参数和返回值。所以利用对象,可以把一个东西的属性和方法收集到一起。
任务三:拦球小游戏
1任务分析通过任务二我们建立了拦球板,现在我们需要通过鼠标去控制拦球板的运动,之后设置一个计分的变量,让小球碰到篮球板就反弹回去的同时计分加一,如果小球没有碰到篮球板但是碰到了下边界,那么就结束游戏,停止游戏。分为以下两步进行。
第一步:实现鼠标控制小拦板移动 其实原理和第六课小海龟走迷宫一样,这里我们只需要控制小栏板左右移动,所以我们只需获取小拦板在画布内x坐标就好了。
第二步:判断游戏是否继续 其次我们要解决判断游戏是否继续,这里我们可以通过判断小球的横坐标和纵坐标是否在栏板的范围内。下图分别为成功和失败的例图 成功 碰到小栏板需反弹 失败 没碰到小栏板,碰到了下边界
2编写程序import turtle#导入turtle库 from random import randint#导入随机数库randint函数 from time import sleep#导入时间库sleep函数 #------------------------------------------------------- screen = turtle.Screen()#赋值screen对象 w,h= 480,360#设定宽度和高度 screen.setup(w,h)#以设定好的宽度和高度来创建屏幕 screen.bgcolor("green")#设定背景色为绿色 screen.delay(0)#这里要设为0,否则很卡 #--------------------------------------------------- square = turtle.Turtle('square')#创建一个弹球小栏板 square.shapesize(0.5,5)#设定栏板的长宽尺寸,对应像素为高5像素,长为50像素 square.speed(0)#设定栏板速度为最大 square.penup()#抬笔 square.color('blue')#设定颜色为蓝色 square.sety(50-h/2)#固定纵坐标 #---------------------------------------------------- ball=turtle.Turtle(shape='circle')#创建一个圆球 ball.speed(0)#速度为最快. ball.penup()#抬笔 ball.color("yellow","yellow")#设定颜色为黄色 xspeed = randint(2,3)#设置初始水平速度 yspeed = randint(2,3)#设置初始垂直速度 #----------------------------------------------------- root = screen._root#获取根窗口对象 cv = screen._canvas#获取画布 count = 0#计次数 while True:#永久循环 mx = root.winfo_pointerx()#鼠标指针相对于计算机屏幕的x坐标 rx = cv.winfo_rootx()#画布到计算机屏幕最左边距离 bx = mx - rx - 2#画布边框宽度是2,所以要减去2 x = bx - screen.window_width() //2 # 转换成在海龟画图坐标系中x坐标 square.goto(x,-50)#使栏板移动到指定坐标 screen.update()#刷新屏幕显示 #----- x = ball.xcor() + xspeed#设置小球在水平方向移动x速度 y= ball.ycor() + yspeed#设置小球在垂直方向移动y速度 ball.goto(x,y)#设定小球的移动 if x>w/2 or x <-w/2:#如果小球跑出左右两侧边界 xspeed = - xspeed#设定小球返回 elif y>h/2 :#如果小球过了上边界 yspeed = - yspeed#设定小球返回 elif y<-h/2:#如果小球过了下边界 print("game over")#显示得分 turtle.done()#画面停止 else: ball.goto(x,y)#设定小球的移动 squareleftx = square.xcor() - 50#设定栏板的左侧横坐标 squarerightx = square.xcor() + 50#设定栏板的右侧横坐标 squareupy = square.ycor() + 5#设定栏板的上方纵坐标 squaredowny = square.ycor() - 5#设定栏板的下端纵坐标 if x< squarerightx and x >squareleftx:#如果小球的横坐标在栏板的范围内 if y < squareupy and y > squaredowny:#如果小球的纵坐标在栏板范围内 yspeed = - yspeed#反弹 count=count+1#计次 print("得分:",count)#显示得分 screen.update()#刷新屏幕显示 sleep(0.01)#推迟0.01秒再执行 |
3运行效果点击运行程序,我们可以看到小球开始向右上方移动,碰到屏幕的上方,左右两侧及栏板后就反弹。这时,我们可以通过鼠标来控制我们的栏板移动进而接球,栏板与小球每接触一次,我们就记一次得分并显示在终端中。如果小拦板接不到小球,并且小球碰到了下边界,那么游戏就会停止。基于这样的游戏功能让我们一起来试试吧,看看最高能得多少分呢?
4代码释义
4.1获取鼠标坐标控制小拦板移动
- while True:#永久循环
- mx = root.winfo_pointerx()#鼠标指针相对于计算机屏幕的x坐标
- rx = cv.winfo_rootx()#画布到计算机屏幕最左边距离
- bx = mx - rx - 2#画布边框宽度是2,所以要减去2
- x = bx - screen.window_width() //2 # 转换成在海龟画图坐标系中x坐标
- square.goto(x,-50)#使栏板移动到指定坐标
- screen.update()#刷新屏幕显示
复制代码
4.1.1代码解释 通过获取电脑中的鼠标的x轴的坐标mx,画布到计算机屏幕最左边距离rx,计算出鼠标距离画布边缘的距离bx,之后用得到的bx减去画布宽度值的一半来获取鼠标相对于画布的坐标值x。
4.1.1使用方法 相对于x坐标,以后如果需要通过鼠标去控制相应的运动,即可套用这个公式从而获得当前鼠标相对于当前画布的坐标值,从而实现坐标控制其运动。 - mx = root.winfo_pointerx()#鼠标指针相对于计算机屏幕的x坐标
- rx = cv.winfo_rootx()#画布到计算机屏幕最左边距离
- bx = mx - rx - 2#画布边框宽度是2,所以要减去2
- x = bx - screen.window_width() //2 # 转换成在海龟画图坐标系中x坐标
复制代码
4.2判断是否继续 - squareleftx = square.xcor() - 50#设定栏板的左侧横坐标
- squarerightx = square.xcor() + 50#设定栏板的右侧横坐标
- squareupy = square.ycor() + 5#设定栏板的上方纵坐标
- squaredowny = square.ycor() - 5#设定栏板的下端纵坐标
- if x< squarerightx and x >squareleftx:#如果小球的横坐标在栏板的范围内
- if y < squareupy and y > squaredowny:#如果小球的纵坐标在栏板范围内
- yspeed = - yspeed#反弹
- count=count+1#计次
- print("得分:",count)#显示得分
- screen.update()#刷新屏幕显示
复制代码
4.1.1代码解释 因为我们前面设定了小拦板的尺寸为square.shapesize(0.5,5),也就是像素高为5,长为50的小栏板。
而我们通过代码可以获取小拦板中心点的坐标(square.xcor(),square.ycor())。因此在计算其最边缘的坐标时需要减去或加上square本身的像素值。既左边减50,右边加50,上边加5,下边减5。从而获得当前小拦板的对应边缘的坐标值。之后进行判断,如果小球的坐标没有超出小拦板的坐标时,表示小球碰到了栏板,继而获得一分将得分加一,同时通过终端实时的打印当前的得分情况。否则游戏停止,终端打印game over。
项目小结通过本节课程的学习我们巩固复习turtle库的两种不同导入方式、Screen函数以及学习随机数randint函数的使用完成了碰壁小球游戏。之后建立小栏板对象,理解了对象、属性、方法的概念。最终完成拦球小游戏功能,巩固学习了获取鼠标坐标的方法、逻辑运算符、多条件判断语句等的用法。想一想作为一个游戏是不是还有很多可以加入控制的功能,比如如何增加游戏难度选择和游戏胜利提醒?
项目扩展尝试换一个背景,然后增加游戏难度设置和游戏胜利提示功能。
参考程序- import turtle#导入turtle库
- from random import randint#导入随机数库randint函数
- from time import sleep#导入时间库sleep函数
- #-------------------------------------------------------
- screen = turtle.Screen()#赋值screen对象
- w,h= 480,360#设定宽度和高度
- screen.setup(w,h)#以设定好的宽度和高度来创建屏幕
- screen.bgcolor("green")#设定背景色为绿色
- screen.delay(0)#这里要设为0,否则很卡
- #---------------------------------------------------
- #产生一个输入难度的对话框
- difficulty=screen.numinput("难度","请输入游戏的难度(1~5)",minval=1,maxval=5)
- square = turtle.Turtle('square')#创建一个弹球小栏板
- square.shapesize(0.5,10/difficulty)#设定栏板的长宽尺寸
- square.speed(0)#设定栏板速度为最大
- square.penup()#抬笔
- square.color('blue')#设定颜色为蓝色
- #----------------------------------------------------
- ball=turtle.Turtle(shape='circle')#创建一个圆球
- ball.speed(0)#速度为最快.
- ball.penup()#抬笔
- ball.color("yellow","yellow")#设定颜色为黄色
- xspeed = randint(2,3)#设置初始水平速度
- yspeed = randint(2,3)#设置初始垂直速度
- #-----------------------------------------------------
- root = screen._root#获取根窗口对象
- cv = screen._canvas#获取画布
- count = 0#计次数
-
- while True:#永久循环
- mx = root.winfo_pointerx()#鼠标指针相对于计算机屏幕的x坐标
- rx = cv.winfo_rootx()#画布到计算机屏幕最左边距离
- x = mx - rx - 2#画布边框宽度是2,所以要减去2
- x = x - screen.window_width() //2 # 转换成在海龟画图坐标系中x坐标
- square.goto(x,-100/difficulty)#使栏板移动到指定坐标
- screen.update()#刷新屏幕显示
- #-----------------------------------------------------
- x = ball.xcor() + xspeed#设置小球在水平方向移动x速度
- y= ball.ycor() + yspeed#设置小球在垂直方向移动y速度
- ball.goto(x,y)#设定小球的移动
- if x>w/2 or x <-w/2:#如果小球跑出左右两侧边界
- xspeed = - xspeed#设定小球返回
- elif y>h/2 :#如果小球过了上边界
- yspeed = - yspeed#设定小球返回
- elif y<-h/2:#如果小球过了下边界
- turtle.write("game over",font=("Arial",40,"normal"))#显示失败
- else:
- ball.goto(x,y)#设定小球的移动
- squareleftx = square.xcor() - 10/difficulty*10#设定栏板的左侧横坐标
- squarerightx = square.xcor() + 10/difficulty*10#设定栏板的右侧横坐标
- squareupy = square.ycor() + 5#设定栏板的上方纵坐标
- squaredowny = square.ycor() - 5#设定栏板的下端纵坐标
- if x< squarerightx and x >squareleftx:#如果小球的横坐标在栏板的范围内
- if y < squareupy and y > squaredowny:#如果小球的纵坐标在栏板范围内
- yspeed = - yspeed#反弹
- count=count+1#计次
- print("得分:",count)#显示得分
- screen.update()#刷新屏幕显示
- if count == 5*difficulty:#如果得了50分
- print("victory")#显示获胜
- turtle.exitonclick()#点击退出
- sleep(0.01)#推迟0.01秒再执行
复制代码
参考效果
|