
4 步用 raygui 即时模式 GUI 给 C 游戏加一块可交互设置面板【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib游戏里要加暂停菜单时,你第一行代码写什么?画个面板不难,几块DrawRectangle的事,但要让它能点、能拖、能显示当前值,就得自己写命中检测、键盘状态机。raygui 是 raylib 附带的即时模式 GUI 模块,专治这个:几十行代码,给 C 语言游戏界面加上可点击、可拖动的交互,不用窗口管理,不用事件队列。raygui 是即时模式:每帧重画全部控件,你手里的变量就是唯一状态。控件没有记忆,调用即渲染,背后没有 hidden state。所以规矩只有一条:每帧声明控件、传变量、读返回值。下面这段是一个 spinner、一个下拉框、一个滑块的最短完整程序:#include raylib.h #define RAYGUI_IMPLEMENTATION // 全项目只在一个 .c 里定义,把实现编译进来 #include raygui.h int main(void) { InitWindow(640, 420, 设置面板); int level 3, zone 0; // 数值与下拉选中项,变量即状态 bool open false; // 下拉框开合必须自己记,控件不替你存 float vol 60.0f; while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(RAYWHITE); GuiSpinner((Rectangle){ 40, 40, 140, 24 }, 等级, level, 1, 5, false); if (GuiDropdownBox((Rectangle){ 40, 90, 140, 24 }, 简单;普通;困难, zone, open)) open !open; GuiSliderBar((Rectangle){ 40, 140, 220, 20 }, 音量, TextFormat(%d, (int)vol), vol, 0.0f, 100.0f); EndDrawing(); } CloseWindow(); return 0; }就这?对,三个控件二十行真就完事。注意数据流:level把变量交给控件,控件把用户操作写回同一块内存;返回值只告诉你本帧是否被我操作过,方便你触发一次性逻辑。60 FPS 下每帧重画听起来浪费,但控件没有实例化开销——调用即渲染,没有对象要构造、没有生命周期要管理,声明就是画。头文件是单文件的,散落在examples/各模块目录下,比如examples/shapes/raygui.h,挑一份拷进你项目就行。我想画一条音量条音量、亮度这类连续量交给滑块。它吃两个文本参数:左标签和当前值。当前值要自己格式化再传——控件不知道你的 float 该按百分比还是按分数显示,它只负责画你给它的那串字符。返回值在被拖动的帧非 0,可拿来触发值变了的逻辑:float master 0.8f; GuiSliderBar((Rectangle){ 40, 80, 220, 20 }, 主音量, TextFormat(%d%%, (int)(master * 100)), master, 0.0f, 1.0f);组合起来是什么样?官方饼图示例右侧的控制台里就有滑块,拖内环半径时图表即时跟着变:我想做一个开关开/关有两种控件,分工不同。GuiCheckBox在勾选/取消的那一帧返回true——就是操作发生的那个瞬间——适合触发一次性动作;GuiToggle是按钮形态的状态指示,时刻显示当前状态,适合放面板角落:bool musicOn true, muted false; if (GuiCheckBox((Rectangle){ 40, 120, 22, 22 }, 背景音乐, musicOn)) LogText(音乐开关: %d, musicOn); // 只会在切换的那帧执行 GuiToggle((Rectangle){ 40, 150, 120, 28 }, 静音, muted);我想让用户选难度下拉框选项用分号连成字符串,选中项是从 0 开始的int下标。容易漏的点:开合状态editMode得自己存一个变量、每帧回传,不然菜单一松手就消失。惯例写法是:本帧返回 true 就翻转它:int diff 0; bool diffOpen false; if (GuiDropdownBox((Rectangle){ 40, 200, 160, 30 }, 简单;普通;困难, diff, diffOpen)) diffOpen !diffOpen;样条编辑器示例里下拉框和滑块、可拖控制点同屏共存,分工很清楚:输入归 raygui,业务绘制归你,这条线划得干净: 错误写法 → 修正:RAYGUI_IMPLEMENTATION 放哪最常见的翻车点:把#define RAYGUI_IMPLEMENTATION写进了自己项目的头文件。ui.h被每个 .c 包含,于是每个文件都编译一份 raygui 实现,链接时满屏multiple definition of GuiSliderBar。这个宏必须只出现在一个翻译单元里:// ui.h —— 其余文件只 include 它,不带 define #include raygui.h // ui.c —— 全项目唯一编译进实现的地方 #define RAYGUI_IMPLEMENTATION #include raygui.h单文件项目同理:define 写在main.c的 include 之前即可。让控件跟着窗口缩放坐标硬编码,窗口一拉就错位。实用做法:每帧从当前分辨率反推锚点,控件只相对锚点排布。GetScreenWidth/Height拿到的是逻辑分辨率,高分屏缩放开启时它已经是缩放后的值,别再手动乘 DPI 系数:int sx GetScreenWidth(), sy GetScreenHeight(); float ax (float)(sx - 276); // 右缘锚点:260 宽面板 16 边距 float ay (float)(sy - 216); // 底缘锚点 GuiSliderBar((Rectangle){ ax 20, ay, 220, 20 }, 难度, TextFormat(%d, level), level, 1.0f, 5.0f);屏幕管理示例里的全屏菜单就是这个思路的完整版,整块菜单贴着窗口边缘和中心布局:踩坑速查四种现象占了日常问题的绝大多数,都一行能修:现象原因一行修法文字画到控件框外默认字号偏大,控件高度只有 20 像素GuiSetStyle(DEFAULT, TEXT_SIZE, 12);并加大控件高度中文显示成方块内置字体不含 CJK 字形GuiSetFont(LoadFontEx(fonts/cjk.ttf, 22, 0, 256));同帧两个可编辑控件,只有一个生效输入被后声明的控件吃掉给控件传editMode,保证同一时刻只有一个可编辑每帧TextFormat掉帧绘制循环里反复拼串,分配频繁结果缓存进静态char[32],只在值变化时重算 下一步可以玩什么换主题:GuiSetStyle(DEFAULT, BORDER_COLOR, GetColor(#3a3f4b))逐属性调,或用GuiLoadStyle一次性载入.rsg主题文件看examples/里更复杂的布局:shapes_pie_chart.c的滚动面板加可编辑文本框、models_animation_blending.c的双列控件面板,看别人怎么把整块屏幕排满可编辑文本三件套:GuiTextBox、GuiValueBox、GuiSpinner(开头已经用过),全都吃editMode,同一时刻只编辑一个的规矩同样适用【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考