emoon / rust_minifb

Cross platfrom window and framebuffer crate for Rust
MIT License
1k stars 95 forks source link

update vs update_with_buffer #283

Closed DuckDuckWhale closed 2 years ago

DuckDuckWhale commented 2 years ago

I just wrote a bug by mistaking update_with_buffer as a superset of update, thinking that it also takes in keyboard events when it does not, leading to the window not responding after the first key press. Maybe a better name like set_framebuffer could avoid the confusion, considering the crate is not yet 1.0?

It apparently does and it turns out that I didn't update the window before checking for keyboard event in the while loop condition. Still, it might be a good idea to make it explicit in the docs? Also, found a weird behavior with key repeat below. I can make a separate issue for it if you'd like.

DuckDuckWhale commented 2 years ago

After some more testing:

loop {
    buffer = get_new_buffer();
    window.update_with_buffer(&buffer, width, width).unwrap();
    while !window.is_key_pressed(Key::Space, KeyRepeat::Yes) {
        window.update();
    }
}

Results in the key not being repeated, while

loop {
    buffer = get_new_buffer();
    window.update_with_buffer(&buffer, width, width).unwrap();
    while !window.is_key_pressed(Key::Space, KeyRepeat::Yes) {
        window.update_with_buffer(&buffer, width, width).unwrap();
    }
}

...works fine. I couldn't figure out why this happens from reading the docs for update and update_with_buffer.

emoon commented 2 years ago

So the docs can be clarified, but if you look at all the examples the are structured like this:

    while window.is_open() && !window.is_key_down(Key::Escape) {
        let new_size = window.get_size();
        // .. more code here
        // read somes keys here 
        window.get_keys().iter().for_each(|key| match key {
            Key::W => println!("holding w!"),
            Key::T => println!("holding t!"),
            _ => (),
        });
        // .. update here
         window
            .update_with_buffer(&buffer, new_size.0, new_size.1)
            .unwrap();
    }

So user code is expected to follow a similar pattern.

DuckDuckWhale commented 2 years ago

Thanks for the response. In my case I only care about one key, so iterating over all possible keys seem a bit verbose. Am I using is_key_pressed wrong? And why would update_with_buffer work yet update doesn't? (I don't change the image in the loop so updating with buffer seems unnecessary here.)

emoon commented 2 years ago

Should only ever call update_with_buffer or update during each loop, they should never be called twice.

emoon commented 2 years ago

Something like this (untested) should work fine

    while window.is_open() {
        if window.is_key_down(Key::Space) {
           println!("space!");
        }
        window.update();
    }
emoon commented 2 years ago

docs has now been updated to state that only one of update_with_buffer and update should be called for a single window.

emoon commented 2 years ago

Closing this, if you still have issues post (here) again.

DuckDuckWhale commented 2 years ago

Should only ever call update_with_buffer or update during each loop, they should never be called twice.

Does this mean that they shouldn't be called consecutively twice without checking for keys etc. (which I was doing)?

docs has now been updated to state that only one of update_with_buffer and update should be called for a single window.

Does this mean that for a given window, only one of the two methods can be called, i.e. once update_with_buffer is called, it is now invalid to call update on the same window, in the next iteration, and only update_with_buffer is valid to call? If so I don't really understand the point. Under the scenario where the window content (framebuffer) is only set once in the very beginning and not changed and only the key presses are of interest, isn't it unnecessary to update the framebuffer again?

emoon commented 2 years ago

Usually applications pick one of the other.

  1. Applications has a buffer to display then they will always call update_with_buffer regardless of the buffer been updated or not.
  2. Applications that does their own custom rendering (such as OpenGL/etc) uses update

Switching between them isn't directly support but should work, something like this should do the trick, but is really untested.

while window.is_open() {
    if window.is_key_down(Keys::Space) {
        ...
    }

    if needs_to_update_buffer {
        window.update_with_buffer(...);
    } else {
        window.update();
    }
}