ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

raygui 即时模式 GUI 实战指南:从保留模式做出能点的 C 游戏设置面板

raygui 即时模式 GUI 实战指南:从保留模式做出能点的 C 游戏设置面板 raygui 即时模式 GUI 实战指南从保留模式做出能点的 C 游戏设置面板【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib用 raylib 开发 C 游戏设置面板往往是最后一块拼图控件状态到底存在哪、中文为什么变方块、窗口一拖界面就错位。raylib 生态里的即时模式 GUI 库 raygui 对这些问题给出了直接答案——控件每帧重画状态只在你自己的变量里。这是一篇从两种 GUI 范式差异切入的 raygui 教程讲清即时模式 GUI 的原理并把一个能点的 C 游戏设置面板搭出来。 先看清差异保留模式与即时模式两种范式的根本区别只有一条控件状态由谁保存——保留模式存在控件对象里即时模式存在你的变量里。维度保留模式Qt、Win32 等即时模式raygui控件生命周期创建一次长期存在的对象每帧声明一次帧末即消失状态存放控件对象内部你代码里的普通变量事件处理回调、消息队列读返回值 写回变量指针代码形态初始化、绑定、事件函数分离全部写在绘制循环里和画场景同处即时模式的代价是布局全靠手工raygui 头文件在 LIMITATIONS 一节明确写着没有自动布局机制每个控件的位置尺寸都由你传的Rectangle决定。换来的是代码与状态完全同位——界面对应的就是绘制循环里那几行声明随时可以删了重写不用维护任何对象树。文件层面也简单raygui.h单文件即整个库仓库examples/下各模块目录各放了一份如examples/shapes/raygui.h拷一份进你的src/就能开始。 第一个可运行程序三种控件搭一个设置面板最小可用形态靠三条约定RAYGUI_IMPLEMENTATION全项目只在一个.c文件里定义每个控件的第一个参数都是它自己的Rectangle数值通过指针参数写回你的变量。#include raylib.h #define RAYGUI_IMPLEMENTATION // 全项目只在一个 .c 文件里定义 #include raygui.h int main(void) { InitWindow(720, 420, 设置面板); int difficulty 2; // 下拉框选中项0 简单 / 1 普通 / 2 困难 bool dropOpen false; // 下拉框开合状态必须自己保存 float shadow 0.6f; // 阴影强度 0~1 bool vsync true; // 垂直同步开关 while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(BLACK); GuiCheckBox((Rectangle){ 30, 50, 22, 22 }, 垂直同步, vsync); GuiSliderBar((Rectangle){ 30, 100, 260, 20 }, 阴影, TextFormat(%.0f%%, shadow * 100), shadow, 0.0f, 1.0f); GuiDropdownBox((Rectangle){ 30, 150, 180, 30 }, 简单;普通;困难, difficulty, dropOpen); EndDrawing(); } CloseWindow(); return 0; }三个要点。其一编译时链接 raylib 即可Linux 下gcc panel.c -lraylib -lm -lpthread -ldl -o panel其余平台走官方 Makefile 或 CMake 同样流程。其二控件的返回值统一为结果码1 表示本帧被按下/勾选2 表示本帧数值发生了变化判非零即可知道这一帧被操作过适合在触发那一帧播放音效或落盘存档。其三复选框和滑杆把指针传进去就够了——vsync、shadow指向的内存就是控件与程序共享的那块数据这是变量是唯一真相的具体落点。 每帧重新声明控件为什么不会卡声明即渲染是即时模式 GUI 的核心控件没有构造函数不分配对象每帧做的事只有画几个矩形和一段文字开销与你每帧本来就要下的绘制调用同一量级。60 FPS 下每个控件都重新创建一遍听起来浪费实际不存在创建这个动作。以 raygui v5.0 为例它的全部主题状态就是一个全局数组guiStyle头文件注释里写得很直白384 个 int总共 1.5 KB图标集也是固定的 8 KB 数组——每帧没有需要新建的控件实例只有绘制本身。所以性能预算应该花在真正有成本的地方文本。TextFormat每帧都产生临时字符串值没变化时没必要重算把结果缓存进静态缓冲、仅当变量变化时再拼一次绘制循环就干净了static char shadowBuf[32]; if (shadow ! lastShadow) { snprintf(shadowBuf, 32, %.0f%%, shadow * 100); lastShadow shadow; } 跨帧状态哪些要自己保管raygui 不记忆任何东西所以一切这一帧和下一帧之间要活下来的东西都归你最典型的就是下拉框的开合状态。GuiDropdownBox的最后一个参数editMode是列表当前的开合状态本帧传进去列表展开与否由它决定选中结果则写回int *active。漏掉这个 bool、每帧传 false列表会在鼠标松手瞬间消失看起来就像下拉框坏了。bool menuOpen false; // 声明在绘制循环外活在你的作用域里 int quality 0; if (GuiDropdownBox((Rectangle){ 400, 60, 200, 30 }, 低;中;高;极高, quality, menuOpen)) SaveQualitySetting(quality); // 非零返回 本帧被操作同类的跨帧状态还有滚动列表的偏移量、编辑中文本的焦点行做法完全一致变量声明在循环外每帧传入传出。如果同一帧里两个可编辑控件抢输入比如两个 TextBox 重叠v5.0 提供了全局互斥模式guiControlExclusiveMode让先获得焦点的控件独占本次操作临时锁定某个控件则用GuiDisable()/GuiEnable()成对包起来。这张截图对应的仓库示例examples/shapes/shapes_pie_chart.c是状态自管的好范本右侧面板里切片数用GuiSpinner调、显示模式用三个GuiCheckBox切、内环半径用GuiSliderBar拖滚动区里每行再放一个滑杆——所有状态变量全部声明在main里控件只负责问用户要参数。 窗口拖拽时布局怎么写硬编码坐标的界面窗口一拉就错位正确做法是每帧从逻辑分辨率反推锚点控件只相对锚点排布。// 每帧取逻辑分辨率开了高分屏缩放后这里已经是缩放后的值 int sw GetScreenWidth(); int sh GetScreenHeight(); float px (float)(sw - 300 - 14); // 右缘锚点距右边 300px、留 14px 边距 float py (float)(sh - 210 - 14); // 底缘锚点 GuiWindowBox((Rectangle){ px, py, 300, 210 }, 图形设置); GuiSliderBar((Rectangle){ px 20, py 50, 260, 20 }, 泛光, TextFormat(%.1f, bloom), bloom, 0.0f, 2.0f);注意GetScreenWidth/GetScreenHeight返回的是逻辑尺寸启用了 HIGHDPI 配置后它已经是系统缩放后的值别再手动乘一次 DPI 系数否则面板会被顶出屏幕。窗口里的控件多了就引入滚动区GuiScrollPanel返回可视窗口view配合BeginScissorMode裁剪内容按固定行高示例里是每行 35px循环绘制滚动偏移量同样声明在循环外自管。 raygui 中文显示字体替换写法内置字体不含 CJK 字形中文标签会渲染成一排方块解决方式是在启动时用GuiSetFont换一张带中文的 TTF。// 把带中文字形的字体文件放进项目charset 0 表示按字体全部字形加载 Font cn LoadFontEx(fonts/source-han.ttf, 22, 0, 256); GuiSetFont(cn); // 全局换字体立即生效 GuiSetStyle(DEFAULT_TEXT_SIZE, 22); // 控件字号与字体设计字号保持一致 // 换回内置字体时 // UnloadFont(cn); GuiSetFont(GetFontDefault());两个容易忽略的点LoadFontEx的chars参数传 0 会加载字体全字集首次加载稍慢但一劳永逸换完字体记得同步DEFAULT_TEXT_SIZE字号和字体实际尺寸不匹配是文字画出控件框外最常见的原因必要时再配合GuiSetStyle(DEFAULT_TEXT_ALIGNMENT, TEXT_ALIGN_LEFT_CENTER)调整对齐。 主题配色怎么改GuiSetStyle 是唯一入口raygui 的主题就是前面说的那个 1.5 KB 全局数组所有颜色、字号、边宽改动都走GuiSetStyle(control, property, value)随时可改、改完下一帧生效。GuiSetStyle(DEFAULT_NORMAL_COLOR, 0x2e3440ff); // 影响全部控件的基础色 GuiSetStyle(SLIDER_BAR, SLIDER_BAR_COLOR_PRESSED, 0x88c0d0ff); // 只改滑杆的按下色 GuiLoadStyleDefault(); // 任何时候一键还原内置主题基础属性DEFAULT_*设置后会自动铺到所有控件所以单个控件的专属值要写在基础值之后写乱了想重来GuiLoadStyleDefault()直接覆盖回去这就是即时模式放心删了重写心态在主题层的体现。接下来值得尝试的三件事一用GuiScrollPanel加GuiWindowBox把面板撑满整块屏幕对照examples/shapes/shapes_pie_chart.c的行高、边距参数抄一遍布局手感。二给控件换一套配色先用GuiSetStyle逐项调调满意后用GuiLoadStyle从外部风格文件加载主题就能脱离代码管理。三把本文的返回码判断接进真实存档勾选那一帧落盘、读档后把值灌回变量你会很直观地体会到变量是唯一真相这句话的分量。【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表