raygui 教程:从 0 到 1 搭出能拖能点的 C 游戏设置面板
raygui 教程从 0 到 1 搭出能拖能点的 C 游戏设置面板【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib用 raylib 写的 C 游戏想加一个设置面板最省事的方案就是 raygui一个头文件、每帧几行代码就能拿到滑块、复选框和下拉框。这篇文章按搭出一个右侧设置面板的施工线走从接入 raygui、把控件攒成面板到窗口拉伸时让界面跟着走再到上线前的问题自查。 第一步把 raygui 接进项目raygui 是单文件头文件 raygui.h 的形式在本仓库里放在 examples/ 各模块目录下如 examples/shapes/raygui.h拷一份进你自己的 src/ 即可。接入时唯一的讲究整个项目要在某一个 .c 文件里定义一个宏这个宏的作用是把 raygui 的实现代码一起编译进你的程序。// demo.c全项目仅此一个文件这样写 #define RAYGUI_IMPLEMENTATION #include raygui.h其余 .c 文件只需要#include raygui.h编译命令Linuxraylib 已编译好gcc demo.c -lraylib -lm -lpthread -ldl -lrt -o demoWindows 用 raylib 仓库里的 CMake / Makefile 走同样流程。记住口诀一处定义处处包含。这是搭 C 语言 GUI 最直接的路线没有资源文件、没有窗口描述一个头文件全搞定。️ 第二步第一帧跑起来#include raylib.h #include raygui.h // 该文件顶部先 #define RAYGUI_IMPLEMENTATION int main(void) { InitWindow(640, 360, 设置面板演示); float volume 60.0f; bool soundOn true; while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(RAYWHITE); GuiSliderBar((Rectangle){ 40, 60, 240, 22 }, 音量, TextFormat(%d, (int)volume), volume, 0.0f, 100.0f); GuiCheckBox((Rectangle){ 40, 100, 22, 22 }, 启用声音, soundOn); DrawText(TextFormat(volume%d soundOn%d, (int)volume, soundOn), 40, 150, 20, BLACK); EndDrawing(); } CloseWindow(); return 0; }跑起来会看到一条滑块、一个复选框底部状态行随拖动实时刷新。这个例子里藏着三条必须理解的约定Rectangle 定位每个控件第一个参数都是 Rectangle即 {x, y, 宽, 高}raygui 没有布局系统位置尺寸全靠你自己填。指针回写volume、soundOn传的是指针用户操作后新值直接写进你的变量不用再去取控件的值。返回值 本帧被操作控件的返回值表示本帧用户是否操作了它为 true 的那一帧正好用来触发一次性的动作。raygui 的本质也在这里体现它的工作方式像一间印钞厂每一帧都把整个面板重新印一遍上一帧的控件从不被复用。你不需要创建对象、销毁对象把变量交进去就画出来用户的操作再写回变量——写界面因此和改写一段文字一样随意完全不用操心控件的寿命。 第三步把控件攒成一个面板第一帧能跑之后任务是把控件逐个堆成面板。以饼图示例examples/shapes/shapes_pie_chart.c的右侧控制台为样板先 spinner再复选框再滑块最后下拉框各解决一类交互。下文px、py是面板左上角锚点第四步细讲。spinner 解决整数精调左右加号减号避免滑块被一次误拖好几格。int sliceCount 7; GuiSpinner((Rectangle){ px 95, py 12, 125, 25 }, Slices, sliceCount, 1, 10, false);复选框解决开 / 关切换用户勾或取消的那一帧返回值为 true是触发一次性动作的天然时机只关心状态时返回值可忽略。bool showValues true; bool showPct false; GuiCheckBox((Rectangle){ px 20, py 52, 20, 20 }, Show Values, showValues); GuiCheckBox((Rectangle){ px 20, py 82, 20, 20 }, Percentages, showPct);raygui 滑块 GuiSliderBar 解决连续数值第二个参数是左标签第三个参数是当前值文本传 NULL 时自动显示数值最后两个参数是范围上下限。float innerR 25.0f; GuiSliderBar((Rectangle){ px 80, py 142, 180, 30 }, Inner Radius, NULL, innerR, 5.0f, 200.0f);raygui 下拉框 GuiDropdownBox 解决多选项选择选项用分号连成一个字符串。要单独提醒的是第四个参数 editMode 是列表的开合状态raygui 不会替你记住它——不存的话列表一松手就消失。bool mapOpen false; // 开合状态自己存每帧继续传 int zone 0; if (GuiDropdownBox((Rectangle){ px 20, py 180, 160, 30 }, 简单;普通;困难, zone, mapOpen)) mapOpen !mapOpen;标准写法就在样条示例examples/shapes/shapes_splines_drawing.c里返回值 true 时翻转这个 bool下拉框就能正常开合。 第四步窗口一拉界面跟着走前面坐标全是硬编码窗口一拉大面板就孤在画面中间。解法每帧从窗口尺寸反推锚点控件只相对锚点排布。int sx GetScreenWidth(), sy GetScreenHeight(); const int panelW 260; float px (float)(sx - panelW - 16); // 面板贴住右缘 float py 16.0f; // 顶边留 16 像素饼图示例的 panelPos.x 就是按屏幕宽减去边距和面板宽算出来的所以窗口怎么拖面板始终贴边。注意 GetScreenWidth / GetScreenHeight 返回的是逻辑分辨率高分屏下 raylib 已经替你换算过别再手动乘 DPI 系数。如果游戏里还有 raygui 不提供、需要自己拖动的实体样条控制点、编辑器句柄等用鼠标坐标减控件 bounds 做命中检测Vector2 m GetMousePosition(); bool hovered (m.x bounds.x) (m.x bounds.x bounds.width) (m.y bounds.y) (m.y bounds.y bounds.height);hovered 为 true 就认定抓到了该控制点后续按鼠标位移量拖动即可。 插曲raygui 只负责问参数把饼图和样条两个例子并排看raygui 与你代码的分工很明确饼图示例的右侧是 raygui 控制台——spinner 调切片数、复选框切换显示模式、滑块控制内环半径但饼图每一片和标签都是示例自己的角度计算和绘制调用画出来的。样条示例同理下拉框选插值算法、滑块调线宽样条本体是你自己的插值函数画的。分界线很干净输入处理与控件渲染归 raygui业务绘制归你——它不替你把饼图画出来也不需要知道你的面板控制的是什么。第五步上线前的问题自查面板要进真游戏之前把下面四个问题过一遍都是实践中高频出现的。问文字为什么画出控件框外多半是默认字号偏大、而你给的 Rectangle 高度太小文字越界。两条路把控件加高比如高度 22 改 30或用GuiSetStyle(DEFAULT, TEXT_SIZE, 14);缩小全局字号如果文字位置不对再调一下 TEXT_ALIGNMENT 属性。问中文为什么显示成方块内置字体里没有 CJK 字形。换成一张带中文的字库初始化时调用一次即可GuiSetFont(LoadFontEx(fonts/cjk.ttf, 22, 0, 256));之后所有控件都用新字体渲染不用逐个改。问同帧操作两个控件为什么只生效一个先查 editMode 这类开合状态下拉框、spinner、文本框这类打开后可编辑的控件在打开期间会吞掉本帧的鼠标输入。如果你存的 bool 一直停在 true等于一直开着一个框后面控件的操作全被吃掉。解法和上面下拉框一段相同把状态正确写回保证同一时刻最多一个控件处于编辑中。问每帧调用 TextFormat 有问题吗TextFormat 每次都在堆上分配新字符串60 FPS 下绘制循环里每帧拼就是每秒几千次分配释放。做法是把结果缓存到静态字符数组值真变了才重算static char buf[32]; static int lastVol -1; if ((int)volume ! lastVol) { lastVol (int)volume; snprintf(buf, 32, %d, lastVol); }之后把 buf 传给滑块替代每次现拼的 TextFormat 结果。施工线到此结束。即时模式 GUI 的本质一句话界面每帧重画真实状态一直存在你的变量里——所以放心删了重写界面代码只要变量不丢。接下来值得花时间用 GuiSetStyle 试出自己的主题配色与字号或者翻 examples/ 里更多 raygui 实战用例看看别人怎么把面板铺满整块屏幕。【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考