在没有 AI 的情况下,也能"养"出生命?
你好,我是吴老师。
上一课我们用了一堆云端 AI(语音、大模型、生图)做出菜谱。这一课我们反着来——不用任何 AI,就在板子上"养"一个电子宠物,它会饿、会开心、会睡觉。
听起来像魔法?其实不是。它的"生命",全靠三个东西:
- 一组状态:饥饿度、心情、年龄……
- 让状态自己变化的东西:时间(用
millis()) - 让状态被人改变的东西:触摸(喂食、玩耍)
本课一句话:电子宠物不是"AI 会思考",而是"一组数字,被时间悄悄改变,又被你的手指改变"。宠物"活不活着",取决于你有没有让"时间和互动"去动这些数字。这跟菜谱课的"AI 生成"完全不同——这是本地规则。
一、先"养"出一个宠物
先别听我讲,让板子演示一遍。
请使用课程的 esp32s3-touchboard-hardware-dev Skill,
烧录本课配套程序 assets/codes/demo01_pet:
板子屏幕上有一只"电子宠物"(一个用图形凑成的小家伙),
面板上显示它的「饥饿度」「心情」,还有三个按钮:喂食、玩耍、睡觉。
你点"喂食"它的问题会变小,点"玩耍"它心情变好,
但你不碰它,它的饥饿度会慢慢涨、心情会慢慢掉。
烧录后用中文注释。烧录后告诉我:不碰它会怎样?点"喂食"后哪里变了?
几秒后,屏幕上出现一只小东西,旁边有"饥饿度""心情"两栏和"喂食/玩耍/睡觉"三个按钮。你一直不碰它,会看到饥饿度一点点涨、心情一点点掉;你点"喂食",饥饿度立刻降下来。
二、拆开看:宠物"活着"靠三件事
1. 状态——一组会变的数字
宠物不是"一幅图",而是六个数字(一个结构体):
宠物 = {
饥饿度: 50 // 0(不饿)~ 100(很饿)
心情: 80 // 0(难过)~ 100(开心)
年龄: 0 // 出生多久
上次喂食: 0 // 上次喂食是开机后第几毫秒
上次玩耍: 0
上次睡觉: 0
}
这跟背单词课的"掌握度"、番茄钟课的"完成数"是同一个概念——状态 = 记住一个"现在怎么样"的数。
2. 时间让状态自然变化(关键!)
宠物最神奇的一点:你不碰它,它也在变。 靠的就是 millis() 这个"不断增长的数"。
每一帧(比如每 100 毫秒):
现在时刻 = millis()
如果(现在时刻 - 上次喂食)> 某个间隔:
饥饿度 + 1 // 一段时间没喂 → 变饿
如果(现在时刻 - 上次玩耍)> 某个间隔:
心情 - 1 // 一段时间没玩 → 变不开心
看出重点了吗? 是时间流逝在推动数字变化,不是你在操作它。"饿"不是宠物"感觉"到的,是"上次喂食的时间距离现在够久了,所以饥饿度加一"判断出来的。 这就叫"状态随时间推移而变化"。
3. 触摸让状态被人改变
你点"喂食",就是主动改这个数字:
点喂食:
饥饿度 = 饥饿度 - 30 // 吃饱了,不饿
上次喂食 = 现在时刻 // 记下这次喂食时间,重新计时
所以宠物"活了"的逻辑,其实就是:时间让它慢慢变差,你用手指让它变好。 你不理它,它就会饿、会难过;你照顾它,它就精神。
三、为什么"时间"能让它"活"起来?——再讲透一点
这一课最值得琢磨的,就是这个:凭什么几个数字被时间推着走,它就"像活的"?
关键在于:状态和时间是"耦合"的。 你喂食,会重置"上次喂食"这个时间点,于是"变饿"的时钟重新开始走。宠物之所以"活",是因为:
你每一次的"照顾",都改变了它接下来的"命运"。 你不喂它,它时钟继续走、继续变饿;你一喂,时钟归零、重新计时。
这跟真实生命很像:你要定时喂、陪它玩,它才健康。它的"生命感",来自"你做的行为和它的状态之间的因果"—— 不是来自什么遥不可及的 AI 魔法。
⚠️ 给比喻划边界:说宠物"活"了,是很形象的形容,但它没有生命、没有感觉。它只是一组数字,在按规则变。你连续一个月不理它,它不是"死了",只是"饥饿度到了 100、心情到了 0"这两组数字而已。它不会心碎,也不会恨你。
四、不让它"死":再加一个规则
电子宠物的"寿命"其实很残酷——不理它,它就一直恶化。为了让你有"照顾"的动力,我们加一条规则:当饥饿度或心情到某个极限,就提示"宠物生病了,快照顾它"。
如果 饥饿度 > 80 或 心情 < 20:
屏幕提示"它有点难受,快喂它/陪它玩"
宠物表情变"苦脸"
你看,这又是一个条件判断——数字到了某个值,就触发一件事。跟番茄钟"到点提醒"、背单词"答错进错题本"是同类的判断。
五、分析:这个电子宠物用了哪些技术?
不用 AI,但它用到的编程概念其实不少:
| 技术 / 概念 | 在这里干什么 | 你之前在哪学过 |
|---|---|---|
| 结构体 | 把饥饿度/心情/年龄打包成"一个宠物" | 第 36 课(掌握度状态) |
millis() 计时 | "现在 - 上次发生时间"判断该不该变化 | 第 6/37 课 |
| 状态随时间的条件判断 | 时间够久了,就加/减一个数 | 本课核心 |
| 触摸区域判断 | "喂食/玩耍/睡觉"三个按钮 | 第 8 课(按钮=区域判断) |
| 重绘 | 状态一变就重画宠物画面 | 第 6/7 课 |
| 图形绘制 | 用 fillCircle/drawString 凑出宠物 | 第 3 章(绘图) |
| TF 卡(可选) | "今天照顾了几次"存本地,断电不忘 | 第 14 课 |
⚠️ 重要理解:这个宠物不联网、不用云 API、不用大模型。 它活得好不好,完全是板上这段"写死的规则"在起作用。这就是"本地规则"和"AI 云端"的区别——菜谱课靠 AI 生成创意,电子宠物靠你写死的规则体现"生命"。
六、改一个条件,看它能怎么"活"
| 我想改 | 该动哪部分 | 我预测会发生什么 |
|---|---|---|
| 把"变饿"变慢(让宠物更耐饿) | 变饿的那个时间间隔 | 胃饿得更慢 |
| 心情掉得更快 | 心情减的值 | 更容易难过 |
| 喂食加的分更多 | 喂食减的数字 | 一下就不饿了 |
| 饥饿度到 100 就"生病"提示 | 那个极限值 | 更早生病提示 |
| 加一个"今天喂了 X 次"存 TF 卡 | 状态 + 存储 | 断电不忘 |
先预测,再验证。 你会发现:改的全是"数字"和"规则"(多快变饿、变多少、何时生病),宠物"活"的底层逻辑(时间推动 + 触摸改变)一点没变。
七、如果它没按你想的来
| 现象 | 先查什么 |
|---|---|
| 宠物不"变" | millis() 用对了吗?是不是"现在时刻 - 上次发生时间"而不是"数秒"? |
| 状态永远不变 | 算状态的逻辑放在 loop 里了吗?有没有每帧去查? |
| 点了按钮没反应 | 触摸区域判断对吗?"喂食"按钮的坐标写对了吗? |
| 状态跳变太剧烈 | 判断间隔够不够?是不是每帧都加了 1? |
| 断电后"照顾次数"没了 | 存了内存——要持久得存 TF 卡(第 14 课) |
记住:宠物"变"是每帧去查"时间距离",不是"它自己会动"。查得对,它就"活";查得不对,它就"不动"。
八、下课前,把"电子宠物"讲给我听
先别看 AI 的回答,自己说一遍:
- 电子宠物的"生命"靠哪三样东西?没有 AI,它怎么"活"?
- 宠物"变饿"是"感觉"到还是"判断"出来的?怎么判断?
- 为什么你"喂食"会重置时间?它和"变饿的时钟"是什么关系?
- 宠物生病提示是怎么来的?本质是什么?
- 这个项目用了哪些技术?哪个是"它像活的一样"的关键?
- 电子宠物和菜谱课(用 AI)最大区别是什么?
今天请留下三样东西:一只你调"养"过的宠物(改过一个参数)、一句"它为什么像活的"的解释、以及一个你加的规则(比如"生病提示")。
九、最后留给你:状态 + 时间 = 一切"会动"的东西
这一课你掌握了一个超通用的编程思维:
任何"看起来会自己动"的程序,背后都是"一组状态 + 时间推动 + 条件和手指改变"。
| 程序 | 状态 | 时间推动 | 你改变它 |
|---|---|---|---|
| 电子宠物 | 饥饿度/心情 | 时间变饿变难过 | 喂食/玩耍 |
| 番茄钟 | 剩余时间 | 每秒减少 | 开始/暂停 |
| 背单词"掌握度" | 0/1/2/3 | (答错掉回去) | 答题 |
| 游戏里的血条 | 生命值 | 受击减少 | 加血 |
| 签到打卡 | 连续天数 | 一天一天过 | 当天签到 |
一旦你摸清这个模式,几乎所有"会动"的程序你都能看透了。
下一课我们再加上 AI——让板子不仅"记住"你的心情,还能听懂它、回应它。但你会发现:情绪识别靠 AI,情绪管理还是靠"状态 + 规则"。
教师备课备注(不作为课堂口播)
课程定位
- 第九章「AI 生活」唯一的纯本地课。与第 43 课(用 AI)形成对照:菜谱课"靠云端生成创意",电子宠物"靠本地规则体现生命"。核心落点是"状态随时间推移而变化"这一编程思维,不是宠物画得多好看。
- 不联网、不用云 API、不用大模型。难点不是代码,而是让学生理解"为什么一组数字被时间推着走,它就像活的"——答案是"状态与时间耦合,你的行为改变它的命运"。
- 与第 36 课(掌握度)、第 37 课(番茄钟状态机)、第 14 课(TF 卡)呼应。
millis()计时 + 状态更新是知识点核心。
本课新增的核心知识点
- 状态 = 一组会变的数字(结构体:饥饿度/心情/年龄等)。
- 时间推动状态(
现在时刻 - 上次发生时间超阈值就增减)——"状态随时间而变化",这是"像活的"的关键。 - 触摸改变状态(喂食重置
上次喂食,让时钟重走)——"你的行为改变它的命运"。 - 条件判断触发事件(饥饿/心情到极限 → 生病提示)。
- 本地规则 vs AI 云端:电子宠物纯本地,与第 43 课对照。
必须避免的错误
- 不要说"宠物会思考/有感觉/伤心了"。它是一组数字在按规则变。要说"它只是饥饿度到了某个值"。
- 不要说"宠物自己会动"。是每帧去检查"时间距离",到了就改数字。
- 不要引入复杂的 AI 或联网。本课重点就是"本地规则 + 状态 + 时间"。
- 不要过度追求"宠物画得好看"。重点讲"状态如何被时间改变"。
执行约束
- FQBN:
esp32:esp32:esp32s3:FlashSize=16M,PartitionScheme=app3M_fat9M_16MB,CDCOnBoot=cdc,PSRAM=opi - 依赖:
TFT_eSPI、FT6336、Adafruit_NeoPixel(可选,灯反馈)、font/ChineseFont16.h;本课不需要网络/云 API。 - 屏幕/触摸引脚同前课;中文用
drawUtf8(与第 34 课一致的 util)。 - 若加"照顾次数存 TF 卡",用 SD_MMC 6 线
setPins(38,40,39,41,48,47)(第 14 课)。
课堂执行要点
- 顺序建议:demo01(现象:不碰它变饿、喂食变好)→ 状态拆解 → 时间推动讲透 → 触摸改变 → 生病提示规则 → 改一个条件 → 下课前复述。
- 灵魂追问 ①:"它不碰为什么会变?"——引出
millis(现在-上次) 的超阈值判。 - 灵魂追问 ②:"为什么喂食能救它?"——引出"重置上次喂食时间"= 影响它接下来的命运。
- 观察表先预测后实测。
- 可与第 43 课对照小实验:同一个"饲养",一个靠 AI、一个靠规则,哪种更像"真的"?——引导认识"本地规则的可控性"vs"AI 的生成性"。
待办与遗留
demo01_pet源码已写(纯本地,状态机+触摸+图形),尚未实板验证。吴老师实板验收重点:① 状态随时间变化是否平滑;② 触摸区域判断;③ 生病提示触发;④ 图形绘制是否像"宠物"。- 若做"认识几天/照顾次数存 TF 卡"扩展,需接第 14 课,待实板验证 SD 读写。