应用定位:烹饪生活模拟类小应用
技术栈:HarmonyOS NEXT + ArkTS + Stage模型
源码行数:150行
核心亮点:多食谱配方系统、Progress烹饪进度、定时器制作流程、食材列表展示
一、引言
做饭模拟器是本系列中第一个引入**预设配方(Recipe)**系统的应用。它模拟了从"选择食谱→准备食材→开始烹饪→完成菜品"的完整做饭流程。
与之前的模拟器相比,做饭模拟器引入了几个全新的设计概念:
- 复合数据结构:每个食谱包含菜品名称、食材列表和风味描述的二维数组
- 进度动画:烹饪过程中Progress从0到100实时增长
- 厨艺等级:每次成功做菜增加厨艺值
- 二阶段交互:开始烹饪(进度动画)→ 完成菜品(展示结果)
二、需求分析
2.1 功能需求
| 需求ID | 功能 | 描述 |
|---|---|---|
| F1 | 食谱选择 | 5种食谱可选(番茄炒蛋/红烧肉/凉拌黄瓜/番茄面/饺子) |
| F2 | 食材展示 | 每种食谱显示所需食材列表 |
| F3 | 烹饪进度 | Progress从0到100模拟烹饪过程 |
| F4 | 厨艺系统 | 每次做菜成功后厨艺+1 |
| F5 | 暂停机制 | 烹饪过程中可以暂停 |
| F6 | 换菜功能 | 不烹饪时可以切换食谱 |
| F7 | 作品记录 | 显示最新做好的菜品名称 |
2.2 数据模型
private recipes: string[][] = [ ['🍅 番茄炒蛋', '🥚 鸡蛋', '🍅 番茄', '🧂 盐', '🛢️ 油'], ['🥩 红烧肉', '🥩 五花肉', '🧄 姜', '🍶 酱油', '🍬 糖'], ['🥗 凉拌黄瓜', '🥒 黄瓜', '🧄 蒜', '🌶️ 辣椒', '🧂 醋'], ['🍜 番茄面', '🍝 面条', '🍅 番茄', '🥬 青菜', '🥚 鸡蛋'], ['🥟 饺子', '🥟 面皮', '🥩 肉馅', '🥬 白菜', '🧂 调料'] ];数据结构设计说明:
- 第一维(外层数组):5种不同食谱
- 第二维(内层数组):每种食谱的详细内容
[0]:菜品名称(带emoji)[1]~[4]:所需食材(带emoji)
三、食谱系统实现
3.1 切换食谱
Button('🔄 换一道菜') .onClick(() => { if (this.isCooking) { this.message = '先做完这道菜再换吧!'; return; } this.recipeIndex = (this.recipeIndex + 1) % this.recipes.length; this.dishName = ''; this.message = '换一道菜:' + this.recipes[this.recipeIndex][0]; }) .backgroundColor('#2196F3')守卫条件:烹饪中不能切换食谱。这保证了状态的稳定性——避免了"正在炒番茄炒蛋突然变成红烧肉"的荒谬情况。
循环索引:(this.recipeIndex + 1) % this.recipes.length实现食谱的循环切换。
3.2 食材展示
Column() { ForEach(this.recipes[this.recipeIndex], (item: string, idx: number) => { if (idx > 0) { Row() { Text(item) .fontSize(15) .margin({ left: 20 }) Text('✅') .fontSize(14) .fontColor('#4CAF50') .margin({ left: 10 }) } .margin({ bottom: 3 }) } }) }索引过滤:if (idx > 0)排除菜品名称(第一个元素),只显示食材列表。每个食材后加 ✅ 表示"已备齐"。
四、烹饪定时器
4.1 开始烹饪
startCooking() { this.isCooking = true; this.progress = 0; this.message = '正在做 ' + this.recipes[this.recipeIndex][0] + ' ...'; this.intervalId = setInterval(() => { this.progress += 10; if (this.progress >= 100) { this.cookCount++; this.skill++; this.dishName = this.recipes[this.recipeIndex][0]; this.message = '🎉 ' + this.dishName + ' 做好了!味道好极了!'; this.stopCooking(); } }, 800); }进度递进:每次定时器触发progress += 10,间隔800ms。从0到100需要100/10 = 10次,共10 × 800ms = 8秒完成一道菜。
完成检测:if (this.progress >= 100)—— 使用>=而不是===确保容错。
自动完成:烹饪完成后自动调用stopCooking()停止定时器。
4.2 暂停/停止
stopCooking() { this.isCooking = false; if (this.intervalId !== -1) { clearInterval(this.intervalId); this.intervalId = -1; } }与跑步模拟器相同的定时器清理模式。
4.3 暂停按钮
Button('⏸️ 暂停') .onClick(() => { this.stopCooking(); }) .backgroundColor('#FF9800')与跑步模拟器不同——跑步模拟器的暂停可以恢复,而做饭模拟器的"暂停"实际上是"取消"当前烹饪(进度不会保存)。这是设计选择——用户可以重新开始烹饪。
五、Progress进度展示
if (this.isCooking) { Progress({ value: this.progress, total: 100, type: ProgressType.Linear }) .width('80%') .color('#FF5722') .margin({ bottom: 10 }) }进度条在烹饪中显示,完成或暂停后消失。这是一种"进度可视化"模式——让用户直观看到任务完成度。
颜色选择:使用深橙色#FF5722配合"烹饪"主题,与食物颜色呼应。
六、厨艺系统
Text('已做 ' + this.cookCount + ' 道菜 | 厨艺 ' + this.skill + ' 级')厨艺skill和菜品数量cookCount始终同步增长——每次完成一道菜,厨艺+1。这是一个简化的设计,更复杂的实现可以是:
// 进阶版:不同菜品加成不同 if (this.recipes[this.recipeIndex][0].includes('红烧')) { this.skill += 3; // 复杂菜品厨艺加成更多 } else { this.skill += 1; }七、状态流转
┌──────────┐ │ 选择食谱 │ ◄──── 换一道菜 └─────┬────┘ │ 点击"开始做菜" v ┌──────────┐ │ 烹饪中 │ ◄──── Progress: 0% → 100% │ isCooking │ └─────┬────┘ ⏸️ 暂停 │ Progress ≥ 100% │ │ v v ┌──────────┐ ┌──────────┐ │ 暂停状态 │ │ 完成菜品 │ └──────────┘ │ 显示作品 │ └──────────┘八、UI布局
8.1 主界面结构
标题: 🍳 做饭模拟器 消息提示 厨师emoji (👨🍳 / 😊) 菜品名称 统计: 已做X道菜 | 厨艺X级 进度条 (烹饪中显示) 食材列表 (✅格式) 操作按钮行 (开始/暂停 + 换菜) 作品展示 (最新作品) 重置按钮8.2 菜品名称展示
Text(this.recipes[this.recipeIndex][0]) .fontSize(22) .fontWeight(FontWeight.Bold)菜名使用大号加粗字体,是界面中的视觉焦点。
九、扩展思路
9.1 食材库存
@State ingredients: Map<string, number> = new Map([ ['🥚 鸡蛋', 5], ['🍅 番茄', 3], ]);烹饪时消耗对应食材,不足时无法制作。
9.2 火候控制
@State heat: number = 50; // 0-100 Button('🔥 大火') .onClick(() => { this.heat = Math.min(100, this.heat + 10); }) Button('🔥 小火') .onClick(() => { this.heat = Math.max(0, this.heat - 10); })火候影响烹饪速度和成功率。
9.3 翻锅动画
使用鸿蒙动画API:
Image('pan.png') .rotate({ angle: this.isCooking ? 30 : 0 }) .animation({ duration: 500, curve: Curve.EaseInOut })9.4 创意菜谱
允许用户发明新菜谱,组合不同食材:
@State customRecipe: string[] = [];十、总结
做饭模拟器展示了ArkTS在"流程化任务模拟"场景下的开发模式:
- 二维食谱数据:用数组嵌套管理复合数据
- 烹饪进度系统:Progress从0到100的定时增长
- 状态互斥:烹饪中不能切换食谱
- 厨艺积累:完成任务后永久提升能力值
- 食材展示:使用索引过滤和ForEach渲染