掌握 Delta Time、FPS 查询、高精度计时器,让你的动画在任何帧率下都保持匀速。
不同设备的帧率差异巨大——60Hz 显示器每帧 16.6ms,144Hz 每帧 6.9ms。如果动画逻辑写死"每帧移动 2 像素",在 144Hz 屏幕上物体会快 2.4 倍。Delta Time(帧间隔)让速度与帧率解耦。
| 函数 | 返回值 | 说明 |
|---|---|---|
float xgeGetDelta(void) | 秒 | 上一帧到当前帧的时间间隔 |
int xgeGetFPS(void) | 整数 | 当前帧率(每秒帧数,滑动平均) |
double xgeTimer(void) | 秒 | 引擎启动以来的高精度时间 |
int64_t xgeTimeNow(void) | 纳秒 | 系统单调时钟(纳秒精度) |
void xgeSleep(uint32_t ms) | — | 当前线程休眠指定毫秒 |
gcc -O2 -I. -o ch06.exe ch06_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch06.exe
#include "xge.h"
static float g_fX = 0.0f;
static int onFrame(void* pUser) {
float dt = xgeGetDelta(); // 帧间隔(秒)
int w = xgeGetWidth();
// 每秒移动 200 像素,无论帧率多少
g_fX += 200.0f * dt;
if (g_fX > w) g_fX -= w; // 循环
xgeClear(0x081114FF);
xgeShapeCircleFill(g_fX, 300, 30, 0xFF6B5EFF);
return XGE_OK;
}static int onFrame(void* pUser) {
double elapsed = xgeTimer(); // 启动以来的秒数
char title[64];
snprintf(title, sizeof(title),
"运行时间: %.1fs | FPS: %d",
elapsed, xgeGetFPS());
xgeSetTitle(title);
xgeClear(0x0C181CFF);
return XGE_OK;
}// 测量一段代码的执行时间
int64_t t0 = xgeTimeNow();
// ... 执行耗时操作 ...
xgeShapeExDraw(pShape); // 复杂矢量渲染
int64_t t1 = xgeTimeNow();
double ms = (t1 - t0) / 1000000.0;
printf("渲染耗时: %.3f ms\n", ms);| 方式 | 配置 | 效果 |
|---|---|---|
| VSync | XGE_INIT_VSYNC | 帧率锁定为显示器刷新率(60/144 Hz) |
| 目标帧率 | d.iTargetFPS = 30 | 引擎内部 sleep 限制上限 |
| 手动 sleep | xgeSleep(16) | 自行控制,适合 OFFSCREEN 模式 |
| 不限制 | 默认(无 VSync,targetFPS=0) | 尽可能快渲染(可能 1000+ FPS) |
if (dt < 0.0001f) dt = 0.0001f; 保护。xgeSleep(1) 实际可能休眠 1-15ms(取决于 OS 调度粒度)。xgeGetFPS()。xgeTimer() 实现一个正弦波动画:y = sin(timer * 2π) * 100。iTargetFPS = 30,验证 xgeGetDelta() 约为 0.033s。权威源码为 examples/tutorial_capture/ch06_main1.c。为让截图可重复,示例将时间点固定为教学快照;实际动画请用 xgeGetDelta() 更新位置,而不要依赖每帧固定像素位移。
