第5 章 弹球游戏 盖房子需要事先设计好所有细节,确保无误后才开始动工。编程则不同,即使程序 编写无误,也经常需要在程序编写完成后进行参数调整,而且可以在已经实现的功能基 础上,添加新的功能。从本章开始,我们编写的许多游戏程序都会先实现基本的功能,然 后在其中添加新的元素,使游戏更丰富、更出色。 5.弹跳的球 1 开始一个新的Scratch程序。把小猫角色删掉,添加一个你喜欢的游戏场景(例如 “太空”类别中的Stars)。 选择角色库中的Bal 作为新角色,把它调整到你喜欢的大小。请实现Bal 的以下功能。 (1)Bal 每一步移动的距离为10(可用 ) 。 (2)Bal 碰到舞台边缘会反弹(可 用 ) 。 (3)Bal 不停地移动和反弹 。 (4)Bal 移动的初始方向为45°(可 用 ) 。 (5)Bal 在单 击 后开始移动 。 试一试你的程序效果 。 5.添加挡板 2 选择角色库中的Paddle作为新角色,调整到合适的大小。请实现Paddle的以下 零基础学Scratch编程 48 功能。 )。 (1)Paddle永远跟着鼠标移动(可 用 (2)Paddle在单 击 后开始移动 。 试一试你的程序效果 。 5.让球碰到挡板就反弹 3 由于使用了积木 ,球碰到舞台边缘后就会反弹,怎样让球碰到挡板也能反 弹呢? 1所示的脚本片段( 碰到……?” 一个简单的处理办法是为Bal 添加如图5.提示:“ 积 木要在“侦测”类别中找,然后改变默认的积木参数)。 这段脚本的意义是说,如果Bal 碰到了Paddle,就将 移动方向改为向后转,当然效果就是反弹回去了。请 你将如图5. 1所示的脚本片段放在一个单独的、以 开始并且不断重复执行的脚本程序内。之所以图5.让球碰到挡板就反弹 1 要把脚本片段放在重复执行的积木语句内,是因为: 侦测本身只是一个动作,被侦测的事件可能发生了,也可能没有发生;不管事件是否发生 了,侦测这个动作都会执行,或者说不管是否侦测到事件,这个积木语句都会执行完成; 如果想要不断侦测,就必须不断重复执行这一侦测的语句。初学者容易犯的一个错误就 是没有把侦测语句放在重复执行的积木中,以为只要没有侦测到事件,就会不断侦测 下去。 试一下你的程序,效果如何? 在大部分情况下,球都能被挡板反弹,但是如果你快速 把挡板移到球的中间位置,球会不断抖动却无法离开挡板(你多试几次就能复现这种情 况),这是为什么呢? 对照着脚本程序,考虑当挡板一下子出现在球中间位置时,它的执行应该是怎样的? 程序侦测发现Bal 碰到了Paddle,因此Bal 向右转180°改变了移动方向;如果球移动但 还没有来得及离开挡板时,程序又侦测发现Bal 碰到了Paddle(显然两者碰到一起了), 那么Bal 又会向后转,结果就是回到了最初的方向;球继续移动,但还没有来得及离开挡 板,又被侦测碰到了Paddle,于是再次回转;……如此不断反复,表现出来就是Bal 在原 第5章弹球游戏 地抖动打转。 明白了原因,我们就能够修正这个问题了:只要在Bal 转向后,确保移动并离开了 Paddle之后,再侦测是否碰到Paddle就行了。这里有个简单的实现方法,就是在Bal 转 向后,让脚本程序等待1秒钟,再继续下一次的侦测。 请你整理一下你的程序,顺便让球在转向前先播放一下WaterDrop声音(在“效果” 类别内),看看是不是与如图5. 2所示的一样。 图5.脚本程序1 2 5.游戏结束 4 我们希望实现这样的功能:当球碰到舞台下边缘时,游戏结束。可以有不同的方法 实现这一功能,下面介绍其中的一种。 单击背景区的图标,再切换到背景面板,选择线段工具 ,设置填充颜色为与背景、 球、挡板都不同的颜色,例如红色,然后增加线段宽度,在背景底边画一条横贯背景的较 粗的横线,如图5. 3所示。 画了线以后,球碰到舞台下边缘的事件就变成球碰到这条红线。虽然这条线不是角 色,无法用5.但由于这条线颜色与游戏中其他颜色不 3节中侦测角色相碰的积木语句, al 添加如图5.其中, 同,可以侦测球是否碰到该颜色。请为B4所示的脚本程序, 碰(“) 到颜 零基础学Scratch编程 图5.在背景底边画线 3 色”积木改变颜色参数的方法如下:将该积木语句拖到编程 区,然后用鼠标单击参数位置的颜色块,这时会弹出设置颜 色、饱和度和亮度的对话框;单击对话框下部的取色图标 , 会在舞台区出现一个圆形的放大镜,放大镜中间的小方框为 取色点;移动放大镜,使得取色点在背景底部的横线上,单击 鼠标左键取色即可,5所示;s 如图5.然后按Ec键或在编辑图5.4 脚本程序 2 区空白处单击,即可让设置颜色的对话框消失,从而完成颜 色参数的设定。“等待……” 积木会使脚本程序停留在这一语句上,直到等待的情况发 生,才执行后面的语句。 请自己玩一下这个游戏吧,是不是很不错? 5.游戏得分 为游戏添加得分的概念,为此要增加计分的功能:游戏开始时得分为0,每用挡板反 弹一次球,得分就加1。 第5章弹球游戏 图5.在舞台区取色 5 为了实现这个功能,需要有一个数来表示当前的游戏得分,这个数会不断变化。我 们在程序中为这个变化的数起个名字:score。类似score这样,在程序中有特定名称,所 表示的数值会变化的对象,称为变量。 在积木区选择“变量”类别,然后单击“建立一个变量”,在弹出对话框中填写变量名, 按钮,6所示。在“然后单击“确定” 如图5.变量”类别的积木区下会自动出现 ,同时 舞台区左上角出现 。单击 前面的复选框,可以控制 是否显示, 也能用鼠标单击并拖动 到新的显示位置。用“显示变量……” 和“隐藏变 图5.新建变量 6 零基础学Scratch编程 量……”积木也可以控制变量是否显示 。 请按图5. 7修改原先控制球被挡板反弹的脚本程序。其中, 保证每次游 戏开始时得分为0,称为变量的初始化,而每次侦测到Bal 碰到Paddle,则让score增加1。 变量的初始化应该在程序开始时进行,并且只进行一次,而变量值的改变则根据实际需 要,可以进行多次。 图5.脚本程序3 7 请你玩一下游戏,观察左上角显示的score值的变化情况。 5.更多游戏效果 6 动脑动手,尝试实现以下新功能。 (1)设定球总是从某个特定位置开始游戏。提示:可参考3.4节,在游戏一开始先 1. 将Bal 移到指定位置 。 (2)球每碰到一次挡板,颜色就改变一次。 (3)球每碰到一次挡板,速度就快一点儿。提示:可以新建一个变量sped,表示 第5章弹球游戏 ,其中, 来自于新建sped变量后出现的 Bal 当前的速度。初始化时,速度为10;每碰到一次挡板,让sped增加1。原先的 可改为 。这一积木语句 表明:变量可以代替数值参数来使用。 (4)目前,球碰到挡板后反弹方向是向后转,但球碰到舞台边缘则不同。从我们的经 验可以知道,球碰到舞台边缘的反弹方向更符合生活常识。所以请你改变Bal 碰到 Paddle后的反弹方向,使它更符合生活中的情况。你可以参考图5. 8中关于方向的说明。 图5.反弹角度与Srth中的方向 8 cac 、和 。 在Scratch中预先设置了一些变量,例如,在“运动”类积木区中有 你可以直接使用 获得角色当前的运动方向。 你可能已经注意到了,在Scratch桌面编辑器中,各种积木除了有不同类别的颜色, 还有不同类别的形状。我们最常用的积木左右两端是平的,表示该积木是一条可执行的 语句;像 和 这样顶端是圆弧的积木,表示一段脚本程序的开始;像 和 这样左右两端是尖的积木,表示一种判断条件,同类的还有“运算”类别中的 、和 ,分别表示大于、小于和等于的判断条件;左右两端为圆弧 的积木表示某种可计算的结果,例如,各种变量(计算结果就是变量的值)、“运算”类别中 加、减、乘、除等多种运算。 对于弹球游戏来说,如果Bal 初始的方向是45°,那么不管怎样反弹,Bal 的方向只 可能是45°、135°、-45°、-135°中的一个。假设Paddle总是在Bal 的下方,那么两者相 碰时,Bl 的方向只可能是135或-°因此只要像图5.aaddl a° 135, 9那样控制Bl 碰到Pe 后的反弹方向即可。 零基础学Scratch编程 图5.控制Bl 碰到Pe后的反弹方向 9 aaddl 5.双人对战 7 5.1 游戏设计 7. 将弹球游戏的方向转90°, 增加一个挡板, 10所示的双人 换个背景, 可以得到如图5. 对战游戏(提示:改变挡板的方向,就可以让挡板竖起来;改变挡板颜色需要在Paddle的 造型面板中,选中挡板,然后设置轮廓颜色)。 图5.双人对战游戏 10 第5章弹球游戏 一些基本的想法如下。 (1)左边的挡板用W、S键控制上下移动(不允许移出舞台)。 (2)右边的挡板用上、下键控制上下移动(不允许移出舞台)。 (3)球碰到上下边界或左右挡板都发生反弹。 (4)球碰到左右哪边的边界,哪边就输,游戏结束。 (5)实现一些基础的游戏效果, 采用如图5. 例如, 10所示的足球场图片作为舞台背 景(提示:导入图片后,转换为矢量图,然后改变球场大小);在背景的脚本中循环播放背 景音乐(提示:最好音乐循环播放时听不出停顿切换,声音库中“可循环”类别下的Dance ChilOut就不错);当球碰到挡板反弹时播放声音。 对于按键控制挡板移动的功能,请阅读附录B的内容作为参考。 7.判断游戏输赢 5.2 5.在这个双人对战游 3节用侦测是否碰到特定颜色的方法来判断游戏是否应结束, 戏中,当然也可以用相同的方法。只要在左边界和右边界分别用不同的颜色画线,就可 根据碰到的特定颜色,知道是哪一边获胜。如果要保证背景左右完全对称,即左右边界 颜色相同,该怎么办呢? 可以使用“侦测”类别积木区中的 ,其中,左边的参 数可选舞台或某个角色,右边的参数“x坐标”表示该角色在水平方向上的位置;而“运动” 类积木区中的 表示当前角色在水平方向上的位置。如果球的 x 坐标小于左边挡板 的 x 坐标,说明球在左边挡板的左侧,即球碰到了左边的边界,右边获胜;否则,球碰到右 边的边界,左边获胜。 在判断输赢的基础上,当游戏结束时,最好将输赢结果显示出来。这里提供一种实 现的思路:为舞台新建两个背景,分别写上文字表示左边赢和右边赢, 11所示, 如图5.分 别为它们命名(例如“左赢”和“右赢”)。当游戏结束时,用“外观”类别中的 积木 将背景切换为相应的背景。 请你编程实现这个双人对战的游戏。 零基础学Scratch编程 图5.表示左边赢和右边赢的背景 11 5.本章小结 8 本章从弹球游戏的实现开始,用到了碰到角色和碰到颜色的事件侦测,引入了变量 来表示游戏得分。在以后的编程中,会越来越多地用到各类计算,有了变量来代表实际 程序运行时具体的值,就能预先设计编写出计算的式子,从而在实际运行时根据当前变 量的值进行计算,得到符合当前程序运行情况的结果。我们经常会用变量来计数(例如 计分和计时),表示运动的方向和速度。变量是非常重要的编程概念,从使用具体的值到 使用变量,可能思维上会有些不习惯,应在后续的编程学习中逐渐体会,练得多了自然就 能掌握这种思维方式。 在弹球游戏中,可以为Bal 这个角色编写多个脚本程序,例如,一个脚本负责设置球 初始的位置、移动方向和速度,然后控制球不断移动;一个脚本负责侦测判断游戏是否结 束;一个脚本负责侦测球与挡板接触并设置相应的弹球效果。多个脚本分别负责不同的 功能,同时运行,又相互配合。将一个复杂的任务分解成多个子任务,并由不同的程序来 实现,这是非常重要的编程方法。不同的程序应该分工明确,各司其职,这样才有可能相 互配合好。对于球与挡板相碰的侦测与相应处理,如果分工不明确,让球和挡板都来处 理,那么球就可能被分别控制着转180°,结果转了360°,仍沿原方向移动。不同脚本程序 有时需要相互等待来协调彼此的行为。例如,游戏中当球被反弹改变方向后,需要等待 一小段时间,让控制球移动的脚本确实将球移动离开挡板之后,再进行与挡板接触的侦 测判断。本书后面还将学习通过消息机制来协调不同脚本程序的方法。