#帧率 #循环 # #独立 #比率 #游戏

game-loop

一个实现帧率独立游戏循环的 Rust crate

22 个版本 (4 个稳定版)

1.2.0 2024 年 5 月 7 日
1.1.0 2024 年 2 月 15 日
1.0.1 2024 年 1 月 16 日
1.0.0 2023 年 8 月 27 日
0.4.0 2020 年 1 月 10 日

#49游戏开发

Download history 411/week @ 2024-05-04 81/week @ 2024-05-11 85/week @ 2024-05-18 95/week @ 2024-05-25 90/week @ 2024-06-01 55/week @ 2024-06-08 64/week @ 2024-06-15 76/week @ 2024-06-22 20/week @ 2024-06-29 46/week @ 2024-07-06 47/week @ 2024-07-13 67/week @ 2024-07-20 78/week @ 2024-07-27 41/week @ 2024-08-03 50/week @ 2024-08-10 23/week @ 2024-08-17

每月 201 次下载
用于 6 个 crate (5 个直接使用)

MIT 许可证

220KB
277

游戏循环

一个实现帧率独立游戏循环的 Rust crate。代码基于 "Fix Your Timestep!",它非常轻量级,支持本地执行和编译为 wasm。

用法

use game_loop::game_loop;

fn main() {
    let game = YourGame::new();

    game_loop(game, 240, 0.1, |g| {
        g.game.your_update_function();
    }, |g| {
        g.game.your_render_function();
    });
}

240 的值是每秒更新的次数。它 不是 帧率。帧率限制取决于您的环境和图形管道。在 Web 环境中,帧率由 requestAnimationFrame 控制,否则渲染会尽可能快地调用。如果启用了 vsync,大多数图形硬件将通过同步阻塞代码来限制队列中排队的帧数。库中没有内置的帧率限制机制,但如果您想添加,也很容易。请参阅示例 "Game of Life" 渲染函数 了解简单方法。

0.1 的值是最大帧时间,它作为您的函数无法跟上每秒 240 次更新时的一个 出口。否则,您的游戏会陷入“死亡螺旋”,越来越落后。例如,如果您的渲染函数需要 0.5 秒,则只会发生 24 次更新而不是 120 次。这会减慢您的游戏速度,但这比崩溃要好。

g 闭包参数允许您访问您的 game 状态,它可以是你喜欢的一切。您还可以访问游戏循环的运行时间、已发生更新的次数等。它还提供了一个 blending_factor,您可以在渲染函数中使用它来插值帧并产生更平滑的动画。请参阅上面的文章以获取更多解释。

默认情况下,自上一帧以来累积的时间是在调用您的渲染函数之前立即测量的。但是,您可以在需要访问 g.blending_factor() 之前调用 g.re_accumulate() 以获得更精确的计时。这对于您的渲染函数在绘制之前执行工作(例如计算光照)很有用。

在Web环境中,requestAnimationFrame仅在浏览器标签页处于活动状态时运行。设置最大帧时间可以确保您的游戏不会在更新方面落后太多,并且实际上是暂停的。此外,game_loop 是异步的,并立即返回而不是阻塞直到调用 g.exit()。除此之外,接口完全相同。

窗口化

现在该软件包支持在 WinitTAO 窗口中运行与帧率无关的游戏循环。您可以在 Cargo.toml 中启用此功能

[dependencies]
game-loop = { version = "*", features = ["winit"] } # or tao

启用这些功能之一后,界面会有一些不同

fn main() {
    let event_loop = EventLoop::new();

    let window = WindowBuilder::new().build(&event_loop).unwrap();
    let window = Arc::new(window);

    let game = YourGame::new();

    game_loop(event_loop, window, game, 240, 0.1, |g| {
        g.game.your_update_function();
    }, |g| {
        g.game.your_render_function(&g.window);
    }, |g, event| {
        g.game.your_window_handler(event);
    });
}

值得注意的是,game_loop 函数现在接受 event_loopwindow 参数以及一个用于处理窗口事件(如调整大小或关闭)的第三个闭包。窗口可以通过 g 闭包参数访问。这样,您可以将图形上下文绑定到它或设置其标题等。

Winit 还支持 wasm,从理论上讲它应该可以正常工作,但我还没有测试它。有关更多信息,请参阅 winit 文档

示例 1:生命游戏

有一个 生命游戏示例,展示了如何以基本形式使用该软件包,不使用 wasm 或窗口化。您可以使用以下命令运行它

cargo run --example game_of_life

Game of Life

示例 2:使用 WASM

有一个 wasm 示例,展示了如何在网页浏览器中使用该软件包。您可以使用以下命令运行它

cd examples/using_wasm && ./run_example

然后在您的网页浏览器中打开 localhost:8000。计数器在网页上只是简单地滴答作响

Using WASM

示例 3:使用 Winit 窗口

有一个 Winit 示例,展示了如何与 winit 窗口一起使用该软件包。您可以使用以下命令运行它

cargo run --example using_winit --features winit

计数器在窗口标题上简单地滴答作响

Using Winit

示例 4:使用 TAO 窗口

有一个 TAO 示例,展示了如何与具有原生菜单栏的 TAO 窗口一起使用该软件包。您可以使用以下命令运行它

cargo run --example using_tao --features tao

计数器在窗口标题上简单地滴答作响

Using TAO

许可证

MIT

依赖关系

~0–38MB
~619K SLoC