Coder Social home page Coder Social logo

game-loop's Introduction

Game Loop

A Rust crate that implements a frame-rate-independent game loop. The code is based on "Fix Your Timestep!", it's extremely lightweight and supports both native execution and compilation to wasm.

Usage

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();
    });
}

The value 240 is the number of updates per second. It is not the frame rate. In web environments, the frame rate is controlled by requestAnimationFrame, otherwise render is called as quickly as possible.

The value 0.1 is the maximum frame time which serves as an escape hatch if your functions can't keep up with 240 updates per second. Otherwise, your game would 'death spiral' falling further and further behind. For example, if your render function takes 0.5 seconds, only 24 updates would occur instead of 120. This slows your game down but that's better than crashing.

The g closure argument lets you access your game state which can be anything you like. You can also access the game loop's running time, how many updates there have been, etc. It also provides a blending_factor that you may use in your render function to interpolate frames and produce smoother animations. See the article above for more explanation.

By default, the amount of accumulated time since the last frame is measured immediately before your render function is called. However, you can call g.re_accumulate() right before you need to access g.blending_factor() for more precise timings. This is useful if your render function does work before it gets round to drawing, such as computing lighting.

In web environments, requestAnimationFrame only runs when the browser tab is active. Setting a maximum frame time ensures your game doesn't fall far behind on its updates and is effectively paused. Also, game_loop is asynchronous and returns immediately rather than blocking until g.exit() is called. Other than that, the interface is exactly the same.

Windowing

The crate now supports running a frame-rate independent game loop inside a Winit or TAO window. You can enable this in your Cargo.toml:

[dependencies]
game_loop = { version = "*", features = ["winit"] } # or tao

With one of these features enabled, the interface is a little bit different:

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);
    });
}

Notably, the game_loop function now takes event_loop and window arguments and a third closure for handling window events such as resizing or closing. The window can be accessed through the g closure argument. This is so you can bind a graphics context to it or set its title, etc.

Winit also supports wasm so in theory it should Just Work, but I haven't tested it. Please refer to winit documentation for more information.

Example 1: Game of Life

There's a Game of Life example that shows how to use the crate in its basic form, without wasm or windowing. You can run it with:

cargo run --example game_of_life

Game of Life

Example 2: Using WASM

There's a wasm example that shows how to use the crate in a web browser. You can run it with:

cd examples/using_wasm && ./run_example

Then open localhost:8000 in your web browser. The counters just tick up on the web page:

Using WASM

Example 3: Using a Winit Window

There's a Winit example that shows how to use the crate alongside a winit window. You can run it with:

cargo run --example using_winit --features winit

The counters just tick up on the window title:

Using Winit

Example 4: Using a TAO Window

There's a TAO example that shows how to use the crate alongside a TAO window with a native menu bar. You can run it with:

cargo run --example using_tao --features tao

The counters just tick up on the window title:

Using TAO

License

MIT

game-loop's People

Contributors

tuzz avatar parasyte avatar pvdberg1998 avatar bcheidemann avatar zetah11 avatar matt328 avatar mkrasnitski avatar tallonkh avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.