理解 XGE 的两种帧驱动模式——自动游戏循环与手动驱动,掌握帧回调的编写规范与退出机制。
图形应用的核心是一个无限循环:每帧执行 输入处理 → 逻辑更新 → 渲染绘制 → 呈现到屏幕。XGE 将这个循环封装在 xgeRun() 内部,你只需提供一个帧回调函数。
int (*)(void* pUser)。返回 XGE_OK (0) 继续循环;返回任何其他值(通常为 XGE_ERROR 或自定义正整数)将终止循环。
// 帧回调类型
typedef int (*xge_scene_proc)(void* pUser);
// 进入主循环(阻塞直到回调返回非 XGE_OK 或调用 xgeQuit)
int xgeRun(xge_scene_proc procFrame, void* pUser);
// 请求退出主循环(可在任意线程调用)
void xgeQuit(void);| 模式 | 常量 | 行为 |
|---|---|---|
| 游戏循环 | XGE_RUN_GAME_LOOP (0) | 引擎自动驱动:每帧调用回调 → 渲染 → 呈现 → 等待 VSync/帧率限制 |
| 手动 | XGE_RUN_MANUAL (1) | xgeRun 不阻塞;你自己决定何时调用 xgeFrame() |
gcc -O2 -I. -o ch03.exe ch03_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch03.exe
#include "xge.h"
typedef struct {
float fAngle;
int iFrameCount;
} AppState;
static int onFrame(void* pUser) {
AppState* app = (AppState*)pUser;
float dt = xgeGetDelta(); // 帧间隔(秒)
// 更新逻辑
app->fAngle += dt * 90.0f; // 每秒旋转 90°
app->iFrameCount++;
// 渲染
xgeClear(0x0A0F14FF);
// ... 绘制旋转图形(后续章节详解)
// 300 帧后自动退出(演示用)
if (app->iFrameCount >= 300)
return XGE_ERROR; // 非 XGE_OK → 退出循环
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800; d.iHeight = 600;
d.sTitle = "Game Loop";
d.iRunMode = XGE_RUN_GAME_LOOP;
xgeInit(&d);
AppState app = {0};
xgeRun(onFrame, &app); // 阻塞直到退出
xgeUnit();
return 0;
}static int onFrame(void* pUser) {
xgeClear(0x0C181CFF);
// 按 ESC 退出
if (xgeKeyPressed(XGE_KEY_ESCAPE)) {
xgeQuit(); // 设置退出标志,本帧结束后循环终止
}
return XGE_OK; // 仍返回 OK,xgeQuit 会覆盖
}xgeQuit() 不会立即中断当前帧——它设置一个标志,循环在本帧回调返回后检查该标志并退出。因此 xgeQuit() 后面的代码仍会执行。
// xgeRun 内部伪代码(GAME_LOOP 模式)
while (!quit_requested) {
pollEvents(); // 1. 收集输入事件
dispatchToScene(); // 2. 分发到场景栈
result = procFrame(pUser); // 3. 调用你的回调
if (result != XGE_OK) break;
render(); // 4. 提交渲染命令
present(); // 5. 交换帧缓冲
frameTiming(); // 6. 帧率限制 / Delta 计算
}pUser 传入。XGE_OK = 继续;其他值 = 退出且 xgeRun 返回该值。你可以用不同返回值区分退出原因。xgeQuit() 可从任意线程调用(如网络线程收到断开通知),但渲染 API 只能在帧回调线程调用。xgeQuit() 实现定时退出。pUser 传递一个计数器结构体,在标题栏显示当前帧号。iRunMode 改为 XGE_RUN_MANUAL,观察 xgeRun 是否立即返回(预习第 4 章)。权威源码为 examples/tutorial_capture/ch03_main1.c。它将帧回调的一个确定时刻渲染到离屏目标;使用 --frames N 可验证循环会自动退出,使用 --capture 可生成下图。
