AI脑洞板
完整教案
自学课件
第 8 课 · 共 35 课

让它动起来

你好,我是吴老师。

前面的课,我们画的东西都很听话,也很安静——安静到一动不动。

今天给它们加一样东西:动起来。

先给你打个预防针:今天真正拦住你的,不是"画",是擦。你马上就会看到。

读完之后,你应该能:说出"只画不擦"为什么会拖出一条线;用"先盖掉旧的、再画新的"做出干净的动画;解释"一帧"是什么;独立做出一个撞墙会反弹的弹球。

用时:约 60 分钟。准备:板子、数据线、电脑上装好 Python 和 pyserial。

看不懂的地方,整段复制给 AI,加一句"请一次只解释一个概念,讲完问我一个小问题"。


一、先做一个"会失败"的实验

我们要做一件听起来很简单的事:让一个方块从屏幕左边跑到右边。

你会怎么做?我猜大多数同学会这么说:"每隔一小会儿,把它往右画一点点。"

很好,我们就照这个做。

请帮我做一个屏幕动画实验:
在屏幕上画一个边长 14 的黄色方块,
每一小段时间把它的横坐标加 2,然后在新的位置再画一个同样的方块。
从屏幕最左边一直画到最右边。
请用中文注释,别动原来的文件。

改完让 AI 帮你装上板子 —— 它会自己打开,你不用去桌面上找它。

现在请你老实回答我一个问题:

你看到的是一个方块在移动,还是一整条黄色的粗线?

如果你的程序做对了,你看到的是一条线。

先别改。把这个画面记住,它是今天最值钱的一幕。

二、为什么会拖出一条尾巴

我们停下来想一想。

你让板子在第 10 列画了个方块,下一小会儿又让它到第 11 列画一个。那第 10 列那个呢?

答案是:它还好好地在那儿。

屏幕不会自己清除任何东西。 你画上去的点就待在那里,直到你用别的颜色把它盖掉。屏幕里既没有"橡皮擦"这个零件,也没有"上一帧"这种记忆——它只记得每个点现在是什么颜色。

所以你画了一百次,屏幕上就留下一百个方块,连成一条线。

这像什么呢?像你拿印章在纸上盖了一个,手往右挪一点再盖一个,再挪一点再盖一个——纸上留下的是一排印章,不是一个会走路的印章。

也像蜗牛爬过留下的痕迹:它确实在移动,但痕迹不会自己消失。

三、屏幕上没有橡皮擦,只有"盖住"

既然没有橡皮擦,那怎么擦?

先想想教室里的黑板:白粉笔写字,黑板擦一抹就没了。

屏幕不是黑板。它没有黑板擦。 你要擦掉一个白点,唯一的办法是——用黑笔把那个点重新描一遍。

看起来方块消失了,其实它是被黑色盖住了。

所以请记住今天最要紧的这句话:

屏幕上没有擦除,只有覆盖。

现在把程序修好:

请修改刚才的程序:
在画新位置的方块之前,先用背景色把旧位置的方块盖一遍。
也就是说,每一小段时间里做两件事:先盖掉旧的,再画上新的。
其余不变,别动原来的文件。

拖尾与正确擦除

这次你应该看到一个干干净净的方块在移动了。

再给你留个小问题

把速度调快(每次加 8 而不是加 2),尾巴会回来吗?

如果回来了,想想为什么:两步之间隔得太远,"盖掉旧的"这一步可能盖不准。 擦和画必须成对出现,中间不能漏。

四、一帧,就是翻页动画里的一页

帧与帧率

先问一个很根本的问题

我们做的这些,说到底就是:画一张、盖掉、再画一张、再盖掉。每一张都是静止的。 那你为什么觉得它在动?

动的是画面吗?不是。

动的是你的眼睛和大脑。

一个画面从眼前消失以后,它不会立刻从你的感觉里消失,还会在你脑子里多留一小会儿。 科学家叫它视觉暂留。

你可以自己试两件事:

  1. 盯着电风扇的叶片看——明明是分开的三片,转快了就看成一整片模糊的圆。
  2. 快速翻动课本页角——每页都是静止的小人,翻快了小人就动起来。

电影也是这个道理:电影每秒只放 24 张静止的照片,你的大脑自动把它们连成了连续动作。

所以动画真正的原理是:屏幕负责一帧一帧画静止的画,你的大脑负责把它们连成动作。

  • 一帧 = 一次完整的画面(盖掉旧的 + 画上新的),就是翻页动画里的一页
  • 帧率 = 一秒钟能画多少帧,就是一秒钟翻多少页

翻得太慢,你看到的是一张张静止的画;翻得够快,眼睛就把它连成了动作。

想好了再点开:为什么是 24?

这不是硬性规定,是一个"刚好够用"的数字。

  • 低于 10 帧/秒:小球开始"一蹦一蹦",你能数出它跳了几下;
  • 24 帧/秒:电影用的就是这个数——大脑已经能把前后两帧连起来了;
  • 30 帧/秒:动画的常见门槛,比电影更顺一点;
  • 60 帧/秒:很顺,但板子要画的帧数翻倍。

帧率越高画面越顺,但板子每一帧能用的时间就越少。 下一节我们就来看看,怎么让板子把这一帧画得又快又干净。

程序里的"歇一下"

程序里那个"每一小段时间",我们是用这一行做的:

time.sleep_ms(16)      # 歇 16 毫秒 —— 一秒大约 60 帧

改这个数字,动画的快慢就变了。数字越大越慢,越小越快。

但别调得太小。 板子画一帧是要花时间的,你让它歇得太少,它来不及画完就又该画下一帧了。 它不会报错,只是画面变卡——安安静静地做不好,又是一个这样的例子。

五、算一笔账:为什么"整屏重画"不划算

上一节说"每一帧要盖掉旧的"。那有同学会想:干脆每一帧把整块屏幕都涂黑,再画新的,多省事。

效果一样吗?我们数一数。

做法像什么每帧要处理的点
只盖掉旧位置那一小块用橡皮擦掉写错的一个字200 个左右
整屏涂黑重画把整页作业撕了重写76,800 个

差了快 400 倍。

打个比方:你要用一根吸管喝掉一小口水,和用同一根吸管喝掉一桶水。 吸管就那么粗,水就那么多,做得到和做不到,是明摆着的。

所以动画有一条规矩:只改该改的地方,别整屏重画。

⭐ 好在这件事不用你操心。 我们用的 screen.fill_rect / screen.fill_circle 都是只画那一块;screen.flush() 负责把画好的推上屏幕。 你要做的只有一件事:记得擦掉旧的。

六、弹球:撞的是肚子,不是中心点

终于可以做弹球了。先把规则说清楚。

弹球要记住四样东西,你可以把它想成"小球脑子里的小本子":

记什么现在是多少干什么用
位置 x、y一开始在屏幕中间现在在哪儿
速度 dx、dy每帧挪 2 和 3下一帧往哪儿跑
撞左右边dx 变号原来往右跑,改成往左跑
撞上下边dy 变号原来往下掉,改成往上飞

写成中文步骤就是:

启动时:
    小球位置 x = 120,y = 160
    小球每一帧挪动 dx = 2,dy = 3

每一帧:
    用背景色在 (x, y) 画一个小球        ← 盖掉旧的
    x = x + dx
    y = y + dy

    如果碰到了左右边:dx = -dx          ← 往回走
    如果碰到了上下边:dy = -dy

    用小球颜色在 (x, y) 画一个小球      ← 画上新的
    推上屏幕,再等一小会儿

请你找一找:哪一步是"擦",哪一步是"画"? 如果把它们的顺序调换会怎么样?

💡 这个顺序有个坑,我先不告诉你 —— 你先照着写,跑起来看看有没有留下莫名其妙的小点。 想不出来,就点下面「弹球」卡片上的「查看源码」,看开头那段注释。

一个几乎人人都会踩的坑

我们的坐标指的是小球的圆心。可小球是有大小的,还有半径。

所以判断"撞到右边"的时候,不能只看 x > 239——那时候球已经有一半跑到屏幕外面去了。

打个比方:你闭着眼睛往后退,撞到墙的是你的肚子,不是你身体中心那个点。

正确的做法是留出身位:x + 半径 > 239 就算撞上了。

这就是编程里常说的边界条件。今天是你第一次遇到它,以后会经常见。

撞的是肚子,不是中心点

还有一件事

"撞到边界就往回走"——板子是真的知道墙在哪里吗?

不。它只是比较了两个数的大小。它眼里没有墙,只有数字。

回头看看:其实你早就会做动画了

第 3 课我们点亮过板子上那颗灯,让它慢慢变亮、再慢慢变暗。

那时候我们说的是"改颜色"。今天换个角度看——它也是动画。

动画在改什么例子你哪节课做过
改位置弹球在屏幕上跑今天
改大小一个圆由小变大,像心跳今天就可以做
改颜色呼吸灯由暗到亮第 3 课

你看,动画不只是"东西在移动"。只要有一个东西在随着时间变,它就是动画。

所以动画可以写成一个很简单的公式:

动画 = 一个会变的东西 + 时间

弹球会变的是位置,呼吸灯会变的是颜色,心跳会变的是大小。 变的东西不一样,做法却是一模一样的:每隔一小会儿,把那个东西改一点点,然后重新画一次。

七、动手做

请帮我做一个弹球:
黑色背景上有一个半径 8 的黄色小球,从屏幕中间出发,
每一帧横向挪 2 个像素、纵向挪 3 个像素。
碰到屏幕四个边就反弹。
每一帧都要先用背景色盖掉旧位置,再画新位置。
点一下屏幕可以暂停和继续。
请用中文注释,别动原来的文件。

改完装上板子(它同样会自己打开),请你检查四件事:

  1. 小球后面有没有尾巴?
  2. 撞到下边和右边时,是正好贴着边反弹,还是有一半跑到屏幕外面去了?
  3. 把速度改成 5 和 7,动画变快了还是变卡了?
  4. 一直盯着看十秒钟,小球会自己乱跑或者卡住吗?

只改一个条件

挑一个来改,先说出你的预测,再动手:

✏️ 可以直接在表格里填写
我改的条件我预测会怎样实际怎样
把半径从 8 改成 24
把速度从 2、3 改成 8、12
把每帧等待从 16 改成 100
只让小球横着跑(dy = 0)

改完请回答:小球变大了以后,"擦"这一下要处理的点变多了还是变少了?动画有没有变慢?

八、自检小测

正在加载本课自检小测…

九、还想玩点什么

方向可以描述给 AI 的效果值得继续想
流星雨几十个小点从上往下掉,掉到底再回到顶上每个点都要单独记住自己的位置吗?
心跳一个圆由小变大、再变回小变大变小的时候,"擦"那一下要擦多大?
跑马灯几个方块轮流亮起来,像在跑它和"一个方块移动"是同一件事吗?
贪吃蛇蛇头往前走,身体跟着头走蛇尾那一格,应该怎么擦?
打砖块顶部一排砖块,被撞到就消失砖块消失后,那里要不要再画一次背景?

倒数第二行那道题我留给你慢慢想。看起来只是"多画几节身体",真正难的地方还是那个字:擦。


这一课的作品,就在上面那几张卡片里 —— 点「装到板子上」,用 USB 线或者蓝牙选你的板子,几秒就装好了。 装完板子会自己打开它,不用按任何按键,也不用去桌面上翻页找。

想看它是怎么写出来的,点卡片上的「查看源码」。

本节演示

会拖尾巴的方块

会拖尾巴的方块

一个故意做错的例子:只画不擦,方块会拖出一条线

会走路的方块

会走路的方块

先盖掉旧的、再画上新的,方块就走得干干净净

弹球

弹球

小球到处弹,碰到边就反弹