How can i make game loop with rust (to WASM)

Hello all!
I wanna make game loop (from scratch) in rust to then compile the code in WASM.
How can I do that?

No idea…

Game loop - is a function that repeats itself at a given frame rate (FPS - f64)

fn game_loop(fps: f64) {
input();
update();
render();
}

Wanna make a web wasm game. Please help!

more about game loop

What your after is covered in the documentation. Post back if you have anything specific.

Thnx

  1. I don’t know how to write it “correctly” and fast.

  2. Also don’t know can i do compile to wasm standart libery function for work with time (Dutation etc)

Maybe somebody’s written something like this before…

Is there a specific reason not to use the web’s requestAnimationFrame API?

Here’s an example: https://rustwasm.github.io/docs/wasm-bindgen/examples/request-animation-frame.html

Thanx for answer !
But i need set specific frame rate (fps) for update… and control it

If I’m right to understand, requestAnimationFrame works as fast as it can and browser can raise or lower the frequency (fps)

This JS lib seems to be based off “fix your timestep” and bases its core cycle on requestAnimationFrame:

Might be a good project to port this to Rust! :slight_smile:

Here’s my code for an “animation loop” in WASM: https://github.com/anlumo/webgl_rust_demo/blob/master/src/renderer.rs

Unlike the example in the official documentation, it actually compiles and works.

The project is a demo of a rotating cube on a web page in WebGL, so it might be interesting for you as a whole.

Note that you can’t really make a loop in WASM, because the browser needs to do its own event handling in the same thread. You can only work with callbacks, such as the one provided by request_animation_frame.

1 Like

Nice example!

However, I think what @LukeMiloch is referring to is that requestAnimationFrame() doesn’t definitively run at 60fps… if the browser gets busy, it can run less frequently - so the value of perf.now() - start_time can be very large, leading to odd behavior in a game.

Of course visually it won’t matter since the rendering can only happen on a repaint anyway - but for collision detection and things like that, updating based on time passed to a low fps render tick (and the big gap of deltatime due to that) is a problem.

Yes, request_animation_frame also isn’t called at all when the tab is not the frontmost in that window. Additionally, on my 144Hz monitor, it’s probably going to called way more than 60 times a second.

However, nothing stops you from scheduling another fixed-duration timer for non-drawing things like physics. The lifetimes might get a little tricky then, though. You’re going to have to use Rc<RefCell<_>> a lot for that.

3 Likes

I think I’m going to try my hand at porting that MainLoop example into awsm sometime in the next couple weeks or so…

But in the meantime I did export an easy-to-use function takes a callback and calls it every requestAnimationFrame tick with total time, delta time, and elapsed time. It returns a cancel function: https://docs.rs/awsm/0.0.3/awsm/tick/fn.start_raf_ticker_timestamp.html

Usage is like:

let cancel_fn = start_raf_ticker_timestamp(|time_stamp| {
    let Timestamp {time, delta, elapsed} = time_stamp;
});

(currently, if you want to cancel from within the loop you can do that but it’s a little tricky… there’s a demo here)

1 Like