diff --git a/User/GameEngine/GE_GUI.c b/User/GameEngine/GE_GUI.c new file mode 100644 index 0000000..8f3986a --- /dev/null +++ b/User/GameEngine/GE_GUI.c @@ -0,0 +1,174 @@ +//游戏引擎 GUI 库 + +#include "sys.h" +#include "key.h" +#include "lcd.h" + +#include "GameEngine.h" + +#include "GE_GUI.h" + +/** + * @brief 初始化 GE_GUI + */ +void GE_GUI_Init(void) +{ +} + +/** + * @brief 绘制粗矩形 + * @param x + * @param y + * @param width: 矩形的宽 + * @param height: 矩形的高 + * @param color: 矩形的颜色 + * @param thickness: 线条厚度 + */ +void GE_GUI_ThickRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color, uint16_t thickness) +{ + for (uint16_t i = 0; i < thickness; i++) + GE_Draw_Rectangle(x + i, y + i, width - 2 * i, height - 2 * i, color); +} + +/** + * @brief 文本框 + * @param x + * @param y + * @param width: 矩形的宽 + * @param height: 矩形的高 + * @param font_color: 文字颜色 + * @param fill_color: 填充颜色 + * @param rectangle_color: 边框颜色 + * @param thickness: 线条厚度 + * @param str: 字符串 + */ +void GE_GUI_TextBox( + uint16_t x, + uint16_t y, + uint16_t width, + uint16_t height, + uint16_t font_color, + uint16_t fill_color, + uint16_t rectangle_color, + uint16_t thickness, + uint8_t *str) +{ + GE_GUI_ThickRectangle(x, y, width, height, rectangle_color, thickness); + GE_Draw_Fill(x + thickness, y + thickness, width - 2 * thickness, height - 2 * thickness, fill_color); + GE_Font_Print(x + thickness + 1, y + thickness + 1, width - 2 * (thickness + 1), height - 2 * (thickness + 1), FONT_16, font_color, WHITE, TRUE, str); +} + +/** + * @brief 绘制双圈粗矩形 + * @param x: 外圈坐标 + * @param y: 外圈坐标 + * @param width: 矩形的宽 + * @param height: 矩形的高 + * @param color: 矩形的颜色 + * @param thickness: 线条厚度 + */ +void GE_GUI_DoubleThickRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color, uint16_t thickness) +{ + GE_GUI_ThickRectangle(x, y, width, height, color, thickness); + GE_GUI_ThickRectangle(x + thickness + 1, y + thickness + 1, width - (thickness + 1) * 2, height - (thickness + 1) * 2, color, thickness); +} + +/** + * @brief 消息窗口 + * @param x + * @param y + * @param width: 窗口的宽 + * @param height: 窗口的高 + * @param head: 标题 + * @param content: 内容 + * @param handler_func: 回调函数。例如,可以用延时实现延时退出,也可以用按键实现任意键退出。设置为 NULL 不执行回调,立即退出 + */ +void GE_GUI_MsgBox(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t *head, uint8_t *content, MsgBoxHandler handler_func) +{ + //边框 + GE_GUI_DoubleThickRectangle(x, y, width, height, BLACK, 2); + + //标题分隔线 + GE_Draw_Rectangle(x + 5, y + FONT_16 + 7, width - 10, 2, BLACK); + + //标题 + GE_Font_Print(x + 6, y + 6, BORDER_MAX, FONT_16, FONT_16, BLACK, WHITE, FALSE, head); + + //内容 + GE_Font_Print(x + 6, y + FONT_16 + 10, width - 12, BORDER_MAX, FONT_16, BLACK, WHITE, FALSE, content); + + //调用回调函数 + if (handler_func != NULL) + handler_func(); +} + +/** + * @brief 菜单窗口 + * @param x + * @param y + * @param width: 窗口的宽 + * @param height: 窗口的高 + * @param head: 标题 + * @param content_amount: 菜单项数 + * @param content: 菜单内容数组 + * @param handler_func: 回调函数。设置为 NULL 不执行回调 + * @retval 被选中的选项序号,从 1 开始 + */ +uint8_t GE_GUI_MenuBox( + uint16_t x, + uint16_t y, + uint16_t width, + uint16_t height, + uint8_t *head, + uint8_t content_amount, + uint8_t content[][GE_GUI_MENUBOX_CONTENT_LEN], + MenuBoxHandler handler_func) +{ + uint8_t choice_num = 1; + + //边框 + GE_GUI_DoubleThickRectangle(x, y, width, height, BLACK, 2); + + //标题分隔线 + GE_Draw_Rectangle(x + 5, y + FONT_16 + 7, width - 10, 2, BLACK); + + //标题 + GE_Font_Print(x + 6, y + 6, BORDER_MAX, FONT_16, FONT_16, BLACK, WHITE, FALSE, head); + + //绘制选项 + for (uint8_t i = 0; i < content_amount; i++) + { + if (i + 1 == choice_num) + GE_GUI_TextBox(x + 4, y + FONT_16 + 8 + i * (FONT_16 + 3), width - 8, FONT_16 + 4, WHITE, BLUE, BLACK, 1, content[i]); + else + GE_GUI_TextBox(x + 4, y + FONT_16 + 8 + i * (FONT_16 + 3), width - 8, FONT_16 + 4, BLACK, WHITE, BLACK, 1, content[i]); + } + + while (1) + { + uint8_t key = KEY_GetKeyWait(); + + if (key == KEY2) + { + break; + } + else if (key == KEY3 && choice_num > 1) + { + GE_GUI_TextBox(x + 4, y + FONT_16 + 8 + (choice_num - 1) * (FONT_16 + 3), width - 8, FONT_16 + 4, BLACK, WHITE, BLACK, 1, content[choice_num - 1]); + choice_num--; + GE_GUI_TextBox(x + 4, y + FONT_16 + 8 + (choice_num - 1) * (FONT_16 + 3), width - 8, FONT_16 + 4, WHITE, BLUE, BLACK, 1, content[choice_num - 1]); + } + else if (key == KEY1 && choice_num < content_amount) + { + GE_GUI_TextBox(x + 4, y + FONT_16 + 8 + (choice_num - 1) * (FONT_16 + 3), width - 8, FONT_16 + 4, BLACK, WHITE, BLACK, 1, content[choice_num - 1]); + choice_num++; + GE_GUI_TextBox(x + 4, y + FONT_16 + 8 + (choice_num - 1) * (FONT_16 + 3), width - 8, FONT_16 + 4, WHITE, BLUE, BLACK, 1, content[choice_num - 1]); + } + } + + //调用回调函数 + if (handler_func != NULL) + handler_func(choice_num); + + return choice_num; +} diff --git a/User/GameEngine/GE_GUI.h b/User/GameEngine/GE_GUI.h new file mode 100644 index 0000000..4f17212 --- /dev/null +++ b/User/GameEngine/GE_GUI.h @@ -0,0 +1,37 @@ +//游戏引擎 GUI 库 + +#ifndef __GE_GUI_H +#define __GE_GUI_H + +//回调函数定义 +typedef void (*MsgBoxHandler)(void); +typedef void (*MenuBoxHandler)(uint8_t choice_num); + +void GE_GUI_Init(void); + +void GE_GUI_TextBox( + uint16_t x, + uint16_t y, + uint16_t width, + uint16_t height, + uint16_t font_color, + uint16_t fill_color, + uint16_t rectangle_color, + uint16_t thickness, + uint8_t *str); + +void GE_GUI_MsgBox(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t *head, uint8_t *content, MsgBoxHandler func); + +#define GE_GUI_MENUBOX_MAX_CONTENT_NUM 10 //适用参数 5, 5, 310, 230 +#define GE_GUI_MENUBOX_CONTENT_LEN 37 //适用参数 5, 5, 310, 230 +uint8_t GE_GUI_MenuBox( + uint16_t x, + uint16_t y, + uint16_t width, + uint16_t height, + uint8_t *head, + uint8_t content_amount, + uint8_t content[][GE_GUI_MENUBOX_CONTENT_LEN], + MenuBoxHandler handler_func); + +#endif