news 2026/9/2 14:18:27

100 行把 UI 接进 raylib:raygui 即时模式控件实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
100 行把 UI 接进 raylib:raygui 即时模式控件实战

100 行把 UI 接进 raylib:raygui 即时模式控件实战

【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib

raylib 项目里画 2D、3D 场景的人很多,但要做个设置页、调试面板就卡住了——不想为界面单独引入 Qt 这种重型依赖。raygui 是仓库自带的即时模式 GUI(IMGUI,每帧直接重绘全部控件、不缓存控件状态),单头文件、零额外构建配置,放进行程循环里调用函数就出界面。这篇文章从 20 行可编译的最小例子开始,走到 3D 相机调试面板,最后聊几个真实会踩的坑。

先让一个按钮亮起来

最小目标是:窗口里出现一个按钮,点一下,界面上的计数跟着变。整份代码可以编译运行:

#include "raylib.h" #define RAYGUI_IMPLEMENTATION // 展开 raygui 实现,必须写在 include 之前 #include "raygui.h" int main(void) { InitWindow(800, 450, "raygui 最小示例"); int clicks = 0; // 即时模式:状态就是普通变量,没有控件对象 while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(RAYWHITE); // 点击的那一帧返回值非 0,无需注册回调 if (GuiButton((Rectangle){ 10, 10, 140, 40 }, "点我")) clicks++; DrawText(TextFormat("已点击 %d 次", clicks), 10, 70, 20, BLACK); EndDrawing(); } CloseWindow(); return 0; }

和保留模式 UI 的本质区别在这里:raygui 的控件没有生命周期,clicks这种状态完全由你自己声明、自己更新,控件函数只是"画出来 + 本帧检测输入"。为什么这样反而省心?因为不存在控件销毁时忘删回调、状态对象泄漏这类问题,UI 状态和游戏状态是同一批变量。注意#define RAYGUI_IMPLEMENTATION必须出现在#include "raygui.h"之前,且整个工程只允许有一个 .c 文件这样写,否则会重复定义。

3 行让滑块跟手

想让玩家(或你自己)实时调参数,核心就是"把变量的地址传给控件",控件替你处理鼠标拖动逻辑:

float width = 200.0f, roundness = 0.2f; bool fill = true; // 每帧循环内: GuiSliderBar((Rectangle){ 600, 40, 150, 20 }, "Width", TextFormat("%.0f", width), &width, 50, 500); GuiSliderBar((Rectangle){ 600, 70, 150, 20 }, "Roundness", TextFormat("%.2f", roundness), &roundness, 0, 1); GuiCheckBox((Rectangle){ 600, 110, 20, 20 }, "Filled", &fill); if (fill) DrawRectangleRounded((Rectangle){ 100, 150, width, 150 }, roundness, 20, RAYBLUE);

GuiSliderBar要求float *,所以widthroundness用 float;如果参数是整数,换GuiValueBox(可键盘输入)或GuiSpinner(带上下箭头)更合适。右边第三个参数是给滑块尾部显示的文字,传NULL就只留左侧标签。官方圆角矩形绘制示例就是这个套路:右侧一排滑块加复选框,实时控制左侧图形的宽、高、圆角和线宽,完整效果长这样:

把调试面板塞进 3D 场景

相机调试面板是 3D 开发里最高频的需求。注意当前仓库的Camera就是Camera3D,字段是position / target / up / fovy / projection(没有旧版文档里的rotation),代码要对准这些字段:

void DrawDebugPanel(Camera *cam) { GuiGroupBox((Rectangle){ 10, 10, 260, 180 }, "Camera"); GuiSliderBar((Rectangle){ 30, 50, 200, 20 }, "FovY", TextFormat("%.0f", cam->fovy), &cam->fovy, 20, 90); GuiSliderBar((Rectangle){ 30, 80, 200, 20 }, "Height", NULL, &cam->position.y, 0, 100); GuiSliderBar((Rectangle){ 30, 110, 200, 20 }, "Dist", NULL, &cam->position.z, -50, 50); // projection 是 int 枚举,用独立 bool 桥接一下 static bool ortho = false; if (GuiCheckBox((Rectangle){ 30, 145, 20, 20 }, "Ortho", &ortho)) cam->projection = ortho ? CAMERA_ORTHOGRAPHIC : CAMERA_PERSPECTIVE; }

GuiGroupBox只画一个带标题的边框,真正的控件坐标你自己摆在它内部。GuiCheckBoxbool *projection是 int,这里用局部 bool 捕获"勾选动作发生"的返回值再同步进相机,比强转指针干净。面板函数放进每帧循环,和场景一起绘制即可——2D 面板画在 3D 场景之后,坐标就是屏幕坐标,不需要投影变换。

2 行改掉控件配色 🎨

默认灰白风格想换成自己的美术风格,用GuiSetStyle按"控件 + 属性"逐条覆盖,颜色直接传 raylib 的 Color 数值:

// 只改按钮的正常态底色和文字色 GuiSetStyle(BUTTON, BASE_COLOR_NORMAL, GREEN); GuiSetStyle(BUTTON, TEXT_COLOR_NORMAL, RAYWHITE); GuiButton((Rectangle){ 10, 10, 120, 30 }, "自定义样式");

属性枚举(BASE_COLOR_NORMALTEXT_COLOR_PRESSED等)和控件枚举(BUTTONSLIDERDEFAULT……)都定义在 raygui.h 里,DEFAULT控件改的是全局默认值,适合开局统一刷一遍圆角、间距、描边宽度。想要一整套主题,可以用官方样式工具生成.rbg样式文件后用GuiLoadStyle("style.rbg")加载,比手写几十条GuiSetStyle省事得多。

三个容易翻车的坑 🕳️

  • 下拉框选项是分号字符串。5.0 版GuiDropdownBox的第二个参数是"Easy;Normal;Hard"这种分号分隔串,不再是旧教程里的字符串数组,传错类型编译就会报错:
int active = 0; // 当前选中项索引 GuiDropdownBox((Rectangle){ 250, 10, 140, 30 }, "Easy;Normal;Hard", &active, false);
  • 中文会显示成方块。raygui 默认内置字体只有拉丁字形,界面要出中文,先用LoadFont加载一份覆盖中文字形的 ttf 再应用到 raygui,别指望改样式能解决。
  • 控件别出屏GetScreenHeight()是窗口内边高,把面板写在窗口高度范围内;窗口动态缩放时把硬编码坐标换成GetScreenWidth() - 面板宽 - 边距这类相对算式,参考圆角矩形示例里滑块坐标的写法。

延伸资源

想往下走,直接看仓库里这些文件,每份都带可运行代码和效果图:

  • raygui.h:单头文件实现,所有控件的签名和枚举都在这
  • shapes_rounded_rectangle_drawing.c:滑块 + 复选框调参数的完整范例
  • core_3d_camera_free.c:3D 相机操作,配合上面的调试面板用
  • examples/examples_list.txt:全部示例清单,按目录找带 GUI 的例子
  • projects/CMake/:CMake 工程模板,照抄可编译结构

跑通最小按钮只是起点——把参数面板、滚动列表(GuiScrollPanel)、颜色选择器(GuiColorPicker)组合起来,游戏内的配置界面基本就齐了。

【免费下载链接】raylibA simple and easy-to-use library to enjoy videogames programming项目地址: https://gitcode.com/GitHub_Trending/ra/raylib

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 14:17:43

小空间嵌入式空调怎么选?无外机打孔与安装避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 14:14:02

通用智能的本质是适应而非预设:Agent与RAG的架构实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 14:13:52

低空三维遥感场景智能感知:从点云到可理解的语义三维世界

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 14:09:08

AI前沿模型开发暂停呼吁:技术监管、开发者影响与应对策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华