raygui 即时模式 GUI 实战指南:给 C 游戏加上设置面板 raygui 即时模式 GUI 实战指南给 C 游戏加上设置面板【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylibraygui 是 raylib 自带的即时模式 GUI 层一个单文件头文件让你在 C 游戏或桌面程序里画出能拖、能点的设置面板。这篇从三条核心约定讲起走完控件选型、数据面板、自适应布局最后给你能直接跑的最小代码和现成接入步骤。为什么不搬重量级 GUI 框架进来Qt、wxWidgets 这类框架功能全但为游戏加一个音量、难度、开关的面板引入整棵依赖树太重学习曲线也陡。反过来手写控件命中检测、状态高亮、焦点管理全得自己抠不划算。raygui 卡在这中间声明式、无实例开销、和 raylib 同风格十几行就出第一个面板。先记住三条规则再碰控件raygui 的控件天生失忆。你可以把它想成一个只有当下这一秒记性的店员你每帧递一张小票你的变量过去他按小票把菜控件端出来顾客动了手他顺手把新数量抄回小票下一帧小票作废重新点单。真正持续存在的真相是你的变量不是控件。落到代码上就是三条约定每帧重新声明在EndDrawing前把控件调用一遍值没变它也一样画。变量即状态传给控件的是指针控件读它、写它别在外面再存一份。返回值 本帧被操作非 0 / true 只在那一帧成立下一帧归零别拿它当当前是否被按住。守住这三条后面所有控件的行为你都能自己推出来。 一个能跑的 main()滑块、复选框、按钮#include raylib.h #define RAYGUI_IMPLEMENTATION // 全项目只写一次把实现编译进程序 #include raygui.h int main(void) { InitWindow(640, 360, raygui 设置面板); SetTargetFPS(60); float volume 60.0f; // 你的变量 唯一真相 bool musicOn true; bool applied false; while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(RAYWHITE); // 返回值非 0 表示这一帧被按下或拖动过 GuiSliderBar((Rectangle){ 40, 60, 260, 24 }, 音量, TextFormat(%d, (int)volume), volume, 0.0f, 100.0f); // 返回 true 的那一帧 用户刚勾/取消 if (GuiCheckBox((Rectangle){ 40, 100, 24, 24 }, 背景音乐, musicOn)) applied !musicOn; // 按钮点击那一帧返回 true if (GuiButton((Rectangle){ 40, 140, 120, 32 }, 应用)) applied false; DrawText(TextFormat(volume%d music%d, (int)volume, musicOn), 40, 190, 20, BLACK); EndDrawing(); } CloseWindow(); return 0; }注意RAYGUI_IMPLEMENTATION全项目只在一个.c里定义其余文件裸#include就行。每个控件第一个参数都是它自己的Rectangle位置尺寸全靠它。返回值只在操作那一帧为真所以点一下就执行的动作要包在if里。️ 按交互目的选 raygui 控件控件适用场景最易错的参数GuiSliderBar/GuiSlider连续数值音量、半径、难度值传float *显示文本要自己TextFormatmin在max前GuiCheckBox是 / 否开关返回 true 只在勾选那一帧bounds宽高给成正方形GuiToggle状态指示 点击切换的按钮状态存在bool *active里不是看返回值GuiDropdownBox多选项里选一个开合状态bool editMode必须自己存选中项是int下标从 0 起GuiSpinner带步进的整数1~10 这种min/max是整数同样要管editModeGuiButton触发一次性动作返回 true 只在点击那一帧成立下拉框那条坑最深单独说bool mapOpen false; // 开合状态自己存每帧回传 int zone 0; // 选中下标 GuiDropdownBox((Rectangle){ 40, 200, 160, 30 }, 简单;普通;困难, zone, mapOpen);记住选项用分号连成一个字符串开合状态你不存下来下拉框松手就消失。 给饼图配一块可交互控制台raygui 不只能做设置面板。仓库 examples/shapes/ 里的饼图示例右侧整块就是 raygui 控制台spinner 调切片数、复选框切显示模式、滑块控内环半径底下滚动列表里每行一个滑块。核心交互代码就四行bool showValues true; bool showPct false; bool asDonut false; GuiSpinner((Rectangle){ 620, 30, 150, 30 }, Slices, sliceCount, 1, 10, false); GuiCheckBox((Rectangle){ 620, 70, 20, 20 }, Show Values, showValues); GuiCheckBox((Rectangle){ 620, 95, 20, 20 }, Percentages, showPct); GuiSliderBar((Rectangle){ 620, 130, 150, 22 }, Inner R, NULL, innerR, 0.0f, 200.0f);分界线很清楚输入与控件渲染归 raygui业务绘制归你。真正画饼的是你自己的扇形角度累加和DrawCircleSectorraygui 只负责把用户要几片、显示什么问出来不用替它画任何控件。窗口拉大时控件怎么跟着走硬编码坐标的界面窗口一拉就错位。实用做法每帧从GetScreenWidth/Height反推锚点控件只相对锚点排布。int sx GetScreenWidth(), sy GetScreenHeight(); const int panelW 260; float ax (float)(sx - panelW - 16); // 右缘锚点 float ay (float)(sy - 220 - 16); // 底缘锚点 GuiSliderBar((Rectangle){ ax 20, ay 20, panelW - 40, 22 }, 难度, TextFormat(Lv %d, level), level, 1.0f, 5.0f);注意取的是逻辑分辨率开了高分屏缩放时它已经是缩放后的值别手动再乘 DPI 系数。游戏里若还有可拖拽实体比如样条控制点每帧拿鼠标坐标减去控件bounds就能做命中检测和上面这套锚点排布不冲突。 五个高频现象与解法文字跑到框外默认字号偏大、控件又只给了 20 高 →GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, ...)对齐顺手把控件height加大。中文变方块内置字体不含 CJK 字形 →GuiSetFont(LoadFontEx(cjk.ttf, 22, 0, 256))换一张带中文的库。同帧动两个控件只生效一个操作被后声明的控件吃掉 → 用GuiDisable()/GuiEnable()做互斥保证同一时刻只有一个可编辑。每帧TextFormat掉帧绘制循环里反复拼串分配器吃不消 → 结果缓存到静态char[32]只在值变化时重算。下拉框松手就消失开合 bool 没存下来 → 每帧把它回传进editMode参数。三步把 raygui 接进现有项目拿文件raygui.h在仓库 examples/ 每个模块目录下都有同一份拷一份到你项目src/。需要整仓就git clone https://gitcode.com/GitHub_Trending/ra/raylib。放宏挑一个.c文件在#include raygui.h之前写#define RAYGUI_IMPLEMENTATION其余源文件只#include raygui.h。编译链接gcc panel.c -lraylib -o panel其他平台照 raylib 官方 Makefile / CMake 走同样的链接流程。raygui 的设计哲学就一句控件不存状态。写界面时放心删了重写只要守住每帧声明、变量为准两条约定。接下来往两个方向玩用GuiSetStyle/GuiSetStyleDefault给控件换配色和字号做出自己的主题或者翻一遍 examples/ 里带 raygui 的用例看别人怎么把布局撑满整块屏幕。【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考