1. 案例目的
想亲手为机器人做一款好玩又有趣的小游戏吗?不知道大家有没有玩过经典的《Flappy Bird》,虽然玩法简单,却非常考验反应力。在本案例中,我们将通过机器人的屏幕编程,一步一步实现一款简易版的《Flappy Bird》小游戏,带你体验从画面显示到游戏逻辑实现的完整过程。
2. 使用材料

3. 软件平台
4. 理论知识
《Flappy bird》游戏的必要要素:
搭建合理的游戏场景
让管道不断出现并移动
控制角色不断跳动
设计合理的计分系统
思考:飞跃管道的关键是什么?需要设计哪些?应该怎么去设计这个玩法?

状态切换:定义游戏的开始界面、运行状态、结束结算。控制各阶段的平滑过渡。
核心循环:在运行状态下,高频执行画面与逻辑更新。
判定机制:集成得分算法、碰撞检测以及游戏终结的边界判定。
需要用的积木说明
核心积木:在本案例中,我们主要使用“TFT”积木库中的积木来完成游戏设计。因为无论是界面绘制、角色显示,还是游戏元素的动态变化,都离不开屏幕显示功能,所以“TFT”积木库将成为本案例的核心。

积木有 5 个重要的参数:
具体内容:填入希望呈现的文本内容,可以用变量进行代替
位置 x / y: 长方形左上角的坐标。
颜色:表示填充的文本的颜色
缩放:这个表示填充文本的字体大小比例,需要通过点击白色的三角形获得的参数,这个参数的意思是形成文本中的最小像素大小,如果是1则表示1个像素,如果是60则代表文本的将60个像素认为是一个最小单位。
而还需要用的绘制具体图案的两个积木:“绘制长方形”和“绘制圆形”积木,其相较文本撰写而言有为了描述几何形状的几何参数。


5. 文本工具的设计
- 文本的绘制:开始界面和结束界面中都会用到不少文字。如果每次都重新设置文字大小、颜色和位置,不仅步骤繁琐,也容易出错。因此,我们可以先制作一个“文字自动化工具”,也就是一个自定义积木。通过这个积木,就能统一控制文字的样式和显示方式,做到“一次定义,重复使用”,后续无论是开始界面还是结束界面,都能更加高效地完成绘制。

通过上述的自定义函数,投入不同的变量,进行填充,就可以完成不同文本的撰写啦。

我们可以发现上述的文本绘制工具中,位置x的实现是一个居中的显示效果,那为什么“width”变量应该这么设置呢?
- 界面绘制:当这个自定义文字积木完成后,开始界面和结束界面的绘制就会轻松很多。我们只需要调用对应的积木,并输入想要显示的文字内容,就可以快速搭建出完整的游戏界面。这样不仅能减少重复操作,也能让整个界面的风格更加统一。


在开始界面里,我们不需要放太多东西,只要放最必要的提示就够了:
游戏的名字
怎么开始游戏
让玩家一看就知道:哦,原来是这个游戏,按一下就出发啦~
而结束界面就不一样了,它要告诉玩家两件事:
游戏结束了(可以加一句“Game Over”)
你得了多少分——这才是大家最关心的问题!
所以,我们需要提前准备好一个分数变量,名字就叫“score”(分数)。每得一分,就把“score”增加 1,这样在游戏结束的时候,直接调用说:“SCORE”: “score” 就搞定啦!
可以通过尝试以及“SCALE”的计算,将我们的开始和结束界面进行绘制,具体的文本应该显示在哪个位置才不会发生重叠。
6. 核心元素的设计
- 绘制小球: 小球是我们游戏里的核心主角,它在运动过程中位置会不断变化,因此每次更新画面时,都需要先把上一帧所在的位置擦掉,再在新位置绘制出来。具体做法是:利用“上一帧的小球 y 坐标”找到旧的球位,然后用背景色(也就是黑色)画一个稍大的圆形,像橡皮擦一样把旧球盖住;接着再在新的坐标位置画出当前的小球。这样快速重复,小球就能在屏幕上“跑”出连续移动的效果啦!

PS:这里的“X ball radius”表示小球始终贴近屏幕左侧运动,也就是说,小球的横坐标基本保持不变,主要变化的是纵坐标。
同学们一定很好奇:“previous ball y”和“ball y”这俩家伙具体会是什么关系呢?上下帧之间小球的变化应该是怎样的呢?别着急,我们慢慢来探索~ 首先要知道,小球需要靠我们不断按下按键才能托住它、不让它掉下去,所以在没有按下按键的时候,我们必须给小球加上一个自动掉落的过程,不然它就会一直悬在半空中,那就太假啦!
- 小球的运动:我们知道,现实世界里小球一旦悬空,就会在重力的作用下越落越快——这是一个加速下落的过程。为了在游戏里模拟这种真实感,我们可以设置两个变量:一个是加速度(让速度不断增加),另一个是速度(决定每次下落多少距离)。同时,我们把游戏的画面更新按“帧”来拆分,每一帧都是一小步,就像动画片一样连续播放。这样,我们就能得到一个简单又好用的速度公式,用来计算小球每一帧的新速度啦!

无论是速度还是加速度,都可以自行设置初值。
而当得到了速度之后我们小球的下落就非常自然地得到啦,而“previous ball y”的值就是上一帧的“ball y”:

当我们按下按键时,按照游戏规则,小球就会向上“弹”一下,就像我们在掂排球一样,这时候,原本下落的速度被全部抵消,并且小球开始向上运动。所以我们可以简单地把速度归零,然后借助加速度来改变小球的 y 坐标值——这里不用想太多,直接拿加速度当作一个常数就行(纯粹为了方便😉),这样就能让小球轻轻跳起来啦!而且因为这个功能相对来说是一个独立的部分,我们可以直接将其总结为一个函数:

“Button pressed”这个积木只负责一件事:检查按键有没有被按下,就像一个门卫只看你有没有敲门🚪。而“playing”变量是一个布尔变量(也就是“真/假”开关),它的任务是判断游戏是不是还在进行中——如果游戏结束了,小球就不能再动了,对吧?所以这两个小伙伴各司其职,一起控制着游戏的节奏~
如果我们按按键按得太快、太猛,小球就会一直往上窜,就像火箭一样——万一它窜出了屏幕上方,我们就没法玩下去了。这时候有两种选择:要么直接提示游戏失败,要么给它加个“天花板”。这里我们选择对上方移动做出限制,不允许小球超出屏幕顶部。所以一旦发现“ball y”变得太小(也就是位置太高),我们就需要强制把它拉回来,让它的坐标保持在屏幕范围内,这样小球就不会飞丢啦~

提到“playing”,我们在每一帧的小球运动中,显然还需要判断其是否掉落到底部或者碰到管道导致游戏失败,在这里我们先完成掉落到底部的判断,这个非常简单,只需要用“ball y”和屏幕高度进行比较即可:

而当完成以上部分,我们的小球每一帧的运动就已经完成了,我们同样可以将其总结成一个函数,定义成“step ball”:

绘制管道:
管道的绘制思路其实和小球很像:它也要在移动过程中不断擦掉旧位置、画到新位置。不过和小球不一样的是,管道不是一个单独的图形,而是由上下两部分组成的,中间还要留出一条空隙,让小球能够灵巧地穿过去~
所以我们在绘制管道时,不能只画一个方块就完事,而是要分别处理:
上方管道的位置和高度
下方管道的位置和高度
以及中间那条通道的间距,我们叫它 “gap”(空隙)
只有把这三位“小伙伴”都安排好,管道才能既好看又公平,让玩家有机会钻过去!
管道的 y 值其实特别好确定,只要比较一下屏幕高度、空隙间距和 0 这几个数,就能轻松算出来啦~而真正让管道“动起来”的关键是“pipe x”,它决定了管道会不会从右向左一路飘过来。很显然,为了实现管道不断左移的效果,“pipe x”必须是一个不断减小的量,就像赛跑时不停往后退的起点线一样,每帧都减少一点点,管道就自然“走”到我们面前了。

还是与小球的相关积木类似,我们可以通过"帧"去区分管道的变化,
- 首先就是管道的左移,我们既可以设定成它是一个恒定的速率移动,比如:

当然为了游戏更有趣味,当我们获得的分数越来越高,难度应该越来越大,所以我们可以将“pipe x”的值跟我们的“score”进行挂钩,实现一个递增的难度:

- 当整组管道向左移动到一定程度后,如果剩余宽度已经小于设定值,就说明当前这一组管道已经成功通过。
这时,就可以重置管道位置,并随机生成新的高度,开始下一轮挑战。这样,游戏中的障碍就会不断循环出现。

同样我们可以获得一个“step pipe”积木去描述了管道的帧运动:

- 碰撞检测: 前面说过,小球一旦撞到管道,游戏就得结束啦。所以碰撞检测是整个游戏逻辑中最最关键的一步,绝对不能马虎!由于小球一直待在屏幕左侧附近,所以碰撞基本上都发生在左边这一片区域。因为小球与底部的碰撞,我们已经在“step ball”里完成,这里,我们主要考虑与管道的碰撞。
首先,因为我们的移动机制是保持小球的水平位置不动,移动管道,因此当发生碰撞时,管道已经移动到了最左侧的位置,因此肯定满足一个条件是“pipe x <= pipe width”:

其次,我们的小球应该是碰到了两个管道中间间隙的上沿或者是下沿,因此可以得到第二个条件:

当两个条件全满足时,设定“playing”为错即可完成碰撞检测。
PS:你有没有发现,前文里所有跟“ball y”有关的运算,都偷偷多了一个“÷10”?这是为什么呢?其实很简单:因为我们从头到尾都还没给这些变量做过初始赋值!为了让小球移动的精度更高、不出现一堆小数,我们一开始就把 “ball y”变量“放大”了(比如放大10倍)。这样一来,所有内部计算都用放大后的整数,又快又准——但在做碰撞检测或者显示的时候,如果你也放大了,要记得“÷10”把它变回真实大小,不然小球可就飞到天上去啦!所以写代码时,一定要根据实际情况,该放大时放大,该还原时还原哦!
- 变量初值定义:

7. 挑战一下
以上的内容已经包括了游戏的主体部分,你现在已经掌握了从零设计一个完整互动游戏的全部核心思想:
变量 → 移动 → 边界限制 → 碰撞检测 → 得分 → 界面 → 优化
快去你的编程环境里动手拼积木吧!运行成功的那一刻,你会超级有成就感。可行版只需要将以上积木进行拼接即可完成:

参考代码:Jumpy Ball 游戏案例