当前位置: 首页 > news >正文

【STM32】贪吃蛇 [阶段2](嵌入式进阶方向)

这篇博客是 承接:【项目思维】贪吃蛇(嵌入式进阶方向)中 聚焦于阶段 2 增强游戏可玩性、观赏性,提升用户交互体验,以修正 菜单系统设计与实现,这是游戏的控制操作界面,提升项目的专业性 与 用户的交互式体验的关键环节。

🎮 菜单系统实现详解(贪吃蛇嵌入式版)

目标:为贪吃蛇游戏添加一个完整的图形菜单系统,支持选择游戏、设置、声音、难度等选项。

一、菜单系统的核心概念

菜单系统的本质是:

状态驱动界面: 每个菜单页是一个状态;
选项列表渲染: 显示当前菜单项;
按键导航控制: 上下选择,左右切换,确认/返回。

二、工程代码实现

模块设计(menu.c / menu.h)

模块职责:

功能							说明
菜单结构定义					菜单项、页、选中项
菜单渲染						在OLED/TFT 上绘制菜单
按键响应						处理上下左右/确认返回按键事件
状态切换						进入游戏、设置参数、退出等
📦 菜单结构定义(menu.h)[基于模块化的结构设计来编程]
#ifndef __MENU_H__
#define __MENU_H__typedef enum {MENU_MAIN,MENU_DIFFICULTY,MENU_SOUND,MENU_ABOUT
} MenuPage;typedef enum {DIFF_EASY,DIFF_NORMAL,DIFF_HARD
} Difficulty;typedef struct {MenuPage current_page;uint8_t selected_index;uint8_t total_items;
} MenuState;// 全局菜单状态
extern MenuState menu;void Menu_Init(void);
void Menu_Draw(void);
void Menu_Next(void);       // 向下
void Menu_Previous(void);   // 向上
void Menu_Select(void);     // 确认
void Menu_Back(void);       // 返回Difficulty Menu_GetDifficulty(void);
uint8_t Menu_IsSoundOn(void);
uint8_t Menu_IsGameStartRequested(void);#endif

三、选项设计(菜单界面)

1. 主菜单(MENU_MAIN)
> ▶ Start Game▶ Difficulty▶ Sound: ON▶ About
2. 难度菜单(MENU_DIFFICULTY)
> ◉ Easy○ Normal○ Hard
3. 声音菜单(MENU_SOUND)
> Sound: ONSound: OFF

🧩 四、实现主逻辑(menu.c

1. 全局状态
MenuState menu = {.current_page = MENU_MAIN,.selected_index = 0,.total_items = 4
};static Difficulty current_difficulty = DIFF_NORMAL;
static uint8_t sound_on = 1;
static uint8_t game_start = 0;
2. 渲染函数
void Menu_Draw(void) {OLED_Clear();switch (menu.current_page) {case MENU_MAIN:OLED_ShowString(0, 0, menu.selected_index == 0 ? "> Start Game" : "  Start Game", 12);OLED_ShowString(0, 12, menu.selected_index == 1 ? "> Difficulty" : "  Difficulty", 12);OLED_ShowString(0, 24, menu.selected_index == 2 ? "> Sound: ON" : "  Sound: ON", 12);OLED_ShowString(0, 36, menu.selected_index == 3 ? "> About" : "  About", 12);break;case MENU_DIFFICULTY:OLED_ShowString(0, 0, current_difficulty == DIFF_EASY   ? "> ◉ Easy"   : "  ○ Easy", 12);OLED_ShowString(0, 12, current_difficulty == DIFF_NORMAL ? "> ◉ Normal" : "  ○ Normal", 12);OLED_ShowString(0, 24, current_difficulty == DIFF_HARD   ? "> ◉ Hard"   : "  ○ Hard", 12);break;case MENU_SOUND:OLED_ShowString(0, 0, sound_on ? "> ON" : "  ON", 12);OLED_ShowString(0, 12, !sound_on ? "> OFF" : "  OFF", 12);break;case MENU_ABOUT:OLED_ShowString(0, 0, "Snake v1.0", 12);OLED_ShowString(0, 12, "By You", 12);OLED_ShowString(0, 24, "Press Back", 12);break;}OLED_Refresh();
}
3. 按键响应函数
void Menu_Next(void) {if (++menu.selected_index >= menu.total_items) {menu.selected_index = 0;}Menu_Draw();
}void Menu_Previous(void) {if (menu.selected_index == 0)menu.selected_index = menu.total_items - 1;elsemenu.selected_index--;Menu_Draw();
}void Menu_Select(void) {switch (menu.current_page) {case MENU_MAIN:switch (menu.selected_index) {case 0: game_start = 1; break;case 1: menu.current_page = MENU_DIFFICULTY; menu.selected_index = 0; menu.total_items = 3; break;case 2: menu.current_page = MENU_SOUND; menu.selected_index = 0; menu.total_items = 2; break;case 3: menu.current_page = MENU_ABOUT; menu.selected_index = 0; menu.total_items = 1; break;}break;case MENU_DIFFICULTY:current_difficulty = (Difficulty)menu.selected_index;menu.current_page = MENU_MAIN;menu.selected_index = 1;menu.total_items = 4;break;case MENU_SOUND:sound_on = menu.selected_index == 0 ? 1 : 0;menu.current_page = MENU_MAIN;menu.selected_index = 2;menu.total_items = 4;break;case MENU_ABOUT:menu.current_page = MENU_MAIN;menu.selected_index = 3;menu.total_items = 4;break;}Menu_Draw();
}void Menu_Back(void) {menu.current_page = MENU_MAIN;menu.selected_index = 0;menu.total_items = 4;Menu_Draw();
}
4. 主循环中调用菜单逻辑(main.c
int main(void) {OLED_Init();KEY_Init();Menu_Init();Menu_Draw();while (1) {if (KEY_UP_PRESSED())      Menu_Previous();else if (KEY_DOWN_PRESSED()) Menu_Next();else if (KEY_OK_PRESSED())   Menu_Select();else if (KEY_BACK_PRESSED()) Menu_Back();if (Menu_IsGameStartRequested()) {Snake_SetDifficulty(Menu_GetDifficulty());Sound_SetEnabled(Menu_IsSoundOn());Game_Start();Menu_Init(); // 重置菜单状态Menu_Draw();}HAL_Delay(100);}
}
最终效果:
OLED 或 TFT 屏幕显示:> ▶ Start Game▶ Difficulty▶ Sound: ON▶ About按键上下移动光标,确认后进入子菜单。
另外,还可以扩展功能:
扩展							实现
可滑动菜单					支持超过 4 项,滚动显示
图标菜单						每项带图标,提升可视性
多语言支持					菜单文字抽象为可切换语言资源
动画切换						页面切换时添加过渡动画

虽然菜单系统相比于贪吃蛇 或者 其他项目的内部实现逻辑 显得过于简单,但是这却是很关键的环节之一,几乎在每一个项目中都会需要,菜单系统是游戏的“导航大脑”,实现需要结合 状态机、输入控制和界面渲染三者的融合运用。

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!

http://www.dtcms.com/a/360733.html

相关文章:

  • 【含文档+PPT+源码】基于SpringBoot+微信小程序的饮水健康之净水器保养管理系统设计与实现【包运行成功】
  • 【Linux】模拟实现Shell(下)
  • 打开模板打印
  • Ajax笔记(下)
  • 《探索C++11:现代C++语法的性能革新(上篇)》
  • 医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(八)
  • Redis 核心概念解析:从渐进式遍历、数据库管理到客户端通信协议
  • 《C++进阶之STL》【红黑树】
  • C语言数据结构之双向链表
  • 基于 DNA 的原核生物与微小真核生物分类学:分子革命下的范式重构​
  • 【JavaWeb】之HTML(对HTML细节的一些总结)
  • Notepad++近期版本避雷
  • 【golang长途旅行第35站】Redis
  • Objective-C 的坚毅与传承:在Swift时代下的不可替代性优雅草卓伊凡
  • 云市场周报 (2025.09.01):解读腾讯云向量数据库、阿里云西安节点与平台工程
  • 从零开始的云计算生活——第五十五天,黑云压城,kubernetes模块之网络组件和CoreDNS组件
  • 数组(3)
  • Proteus8 仿真教学全指南:从入门到实战的电子开发利器
  • GitHub 热榜项目 - 日榜(2025-09-01)
  • 基于YOLOv11的脑卒中目标检测及其完整数据集——推动智能医疗发展的新机遇!
  • MySQL下载及安装(Windows 11)
  • 【LeetCode】3524. 求出数组的 X 值 I (动态规划)
  • 【LeetCode 155】—最小栈 - 详解与实现
  • 阿里Qoder怎么样?实测对比TRAE SOLO 和 CodeBuddy IDE
  • 保健品跨境电商:如何筑牢产品质量与安全防线?
  • 数据库事务隔离级别与 MVCC 机制详解
  • 机器学习(四)KNN算法-分类
  • 哈希表-1.两数之和-力扣(LeetCode)
  • git将当前分支推送到远端指定分支
  • YOLO 目标检测:YOLOv3网络结构、特征输出、FPN、多尺度预测