Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] How to limit FPS? #380

Closed
alexmozaidze opened this issue Jan 28, 2022 · 14 comments
Closed

[Question] How to limit FPS? #380

alexmozaidze opened this issue Jan 28, 2022 · 14 comments

Comments

@alexmozaidze
Copy link

alexmozaidze commented Jan 28, 2022

I want to test wether delta time in my game works as expected and want to test the game on different fps, but there's no function to do that, can you add one, please? It's not even necessary for it to work on all platforms, just desktop would be nice, for debugging and stuff.

@buxx
Copy link

buxx commented Jan 31, 2022

Hello @alexmozaidze , do https://docs.rs/macroquad/latest/macroquad/time/index.html is useful for you ?

@alexmozaidze
Copy link
Author

Time module is useful for counting fps but not for limiting it.

@buxx
Copy link

buxx commented Feb 1, 2022

My personal usage of this module is to make a sleep according to previous frame duration. By targeting my desired fps.

@alexmozaidze
Copy link
Author

I don't know how to do that, I couldn't get any examples on the internet to work. Can you show an example of how to do that?

@buxx
Copy link

buxx commented Feb 1, 2022

There is an example :

let minimum_frame_time = 1. / 60.; // 60 FPS
let frame_time = get_frame_time();
println!("Frame time: {}ms", frame_time * 1000.);
if frame_time < minimum_frame_time {
    let time_to_sleep = (minimum_frame_time - frame_time) * 1000.;
    println!("Sleep for {}ms", time_to_sleep);
    std::thread::sleep(std::time::Duration::from_millis(time_to_sleep as u64));
}

But this is not wasm compatible :( (std::thread cannot be used with wasm).

Anyone know how to make a sleep with wasm ?

@buxx
Copy link

buxx commented Feb 1, 2022

I asked some information about sleep and wasm. There is the response I got :


You can't create a synchronous one, but to make an async one do this:

  1. In your Javascript code declare this function:
export function js_sleep(ms) {
    let id;
    const promise = new Promise(resolve => id = setTimeout(resolve, ms));
    return [promise, id];
}
export function clear_timeout(x) {
    clearTimeout(x)
}
  1. Write this Rust glue code:
#[wasm_bindgen(module = "/path/to/the/module.js")]
extern "C" {
    fn js_sleep(millis: u32) -> js_sys::Array;
    fn clear_timeout(id: i32);
}

pub async fn sleep(time: Duration) {
    let millis = u32::try_from(time.as_millis()).unwrap_or(u32::MAX);
    let tuple = js_sleep(millis);
    let promise = Promise::from(tuple.get(0));
    let id = tuple.get(1).as_f64().unwrap() as i32;
    struct Sleep {
        future: JsFuture,
        id: i32,
    }
    impl Future for Sleep {
        type Output = ();
        fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
            Pin::new(&mut self.future).poll(cx).map(|res| { res.unwrap(); })
        }
    }
    impl Drop for Sleep {
        fn drop(&mut self) {
            clear_timeout(self.id);
        }
    }
    Sleep {
        future: JsFuture::from(promise),
        id,
    }
    .await
}

From then on you should be able to call sleep in Rust

@alexmozaidze
Copy link
Author

With all that info, I now realize that having a function to limit fps is pretty limiting since it would take away the control from the developer. I'll change the title so it's easier to find by others. Thank you for helping me!

@alexmozaidze alexmozaidze changed the title [Feature Request] Add a way to limit fps for debugging purposes [Question] How to limit FPS? Feb 1, 2022
@DaLynX
Copy link

DaLynX commented Feb 9, 2022

Hi, I am trying to achieve this but am still missing some bits like where to put this js code and how to regenerate a fully working gl.js file. Would you have some advice for that?

Also, don't you think this could be integrated in macroquad? Some developers like me 🙃 would be interested in having a sleep function.

@buxx
Copy link

buxx commented Feb 9, 2022

I'm interested too. I tried by adding a sleep function (like in previous example) but I failed. @not-fl3 I have a question : Use a async_std::task::sleep could be a solution ?

@DaLynX
Copy link

DaLynX commented Feb 9, 2022

It seems that's not supported in wasm yet: async-rs/async-std#220

@not-fl3
Copy link
Owner

not-fl3 commented Feb 10, 2022

Hi, I am trying to achieve this but am still missing some bits like where to put this js code and how to regenerate a fully working gl.js file. Would you have some advice for that?

Also, don't you think this could be integrated in macroquad? Some developers like me upside_down_face would be interested in having a sleep function.

There is no way to limit FPS on wasm, unfortunately: browser will send requestAnimationFrame frames as fast as it feels so, and there is not much we can do about it.

The only workaround: you can skip frames in your update logic, something like

if time_passed < desired frame_time {
  next_frame().await;
}

@DaLynX
Copy link

DaLynX commented Feb 11, 2022

Right, I was trying to use thread::sleep so of course it didn't work but using macroquad::time::get_time() in an if block for my update code works fine. Thanks for pointing me to the right direction!

@des54321
Copy link

@not-fl3

Is there a reason macroquad doesn't seem to give a way to change the fps above 60?

@brettchalupa
Copy link

Curious about the question above ☝️

In theory, I don't see any reason why target_fps or max_fps couldn't be configured

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants