【问题标题】:rust-buildgen requestAnimationFrameLoop unable to use struct method inside closurerust-buildgen requestAnimationFrameLoop 无法在闭包内使用结构方法
【发布时间】:2020-02-22 23:00:32
【问题描述】:

我正在尝试创建一个 requestAnimationFrame 循环,它将为每一帧调用 game.render()。我正在关注本教程 - https://rustwasm.github.io/wasm-bindgen/examples/request-animation-frame.html


struct Game {
    state: GameState,
    ctx: web_sys::CanvasRenderingContext2d
}

impl Game {
    fn render(self: Game) {
        self.ctx.begin_path();
        self.ctx.arc(self.state.x, 50.0, 40.0, 0.0, 2.0 * std::f64::consts::PI);
        self.ctx.stroke();
    }
}

#[wasm_bindgen(start)]
pub fn run() -> Result<(), JsValue> {

    let game = init();

    let f = Rc::new(RefCell::new(None));
    let g = f.clone();


    *g.borrow_mut() = Some(Closure::wrap(Box::new(move || {
        game.render();
        request_animation_frame(f.borrow().as_ref().unwrap());
    }) as Box<dyn FnMut()>));

    request_animation_frame(g.borrow().as_ref().unwrap());
    Ok(())
}


fn init() -> Game {
    let doc = document();
    let canvas = doc.create_element("canvas").unwrap();
    canvas.set_attribute("width", "800px").unwrap();
    canvas.set_attribute("height", "800px").unwrap();
    canvas.set_id("fp-canvas");
    body().append_child(&canvas).expect("Could not attach canvas");

    Game {
        ctx: context(),
        state: GameState {
            x: 3.0
        }
    }
}

但它给出了以下错误-


error[E0277]: expected a `std::ops::FnMut<()>` closure, found `[closure@src/lib.rs:89:51: 92:6 game:Game, f:std::rc::Rc<std::cell::RefCell<std::option::Option<wasm_bindgen::closure::Closure<dyn std::ops::FnMut()>>>>]`
  --> src/lib.rs:89:42
   |
89 |       *g.borrow_mut() = Some(Closure::wrap(Box::new(move || {
   |  __________________________________________^
90 | |         game.render();
91 | |         request_animation_frame(f.borrow().as_ref().unwrap());
92 | |     }) as Box<dyn FnMut()>));
   | |______^ expected an `FnMut<()>` closure, found `[closure@src/lib.rs:89:51: 92:6 game:Game, f:std::rc::Rc<std::cell::RefCell<std::option::Option<wasm_bindgen::closure::Closure<dyn std::ops::FnMut()>>>>]`
   |
   = help: the trait `std::ops::FnMut<()>` is not implemented for `[closure@src/lib.rs:89:51: 92:6 game:Game, f:std::rc::Rc<std::cell::RefCell<std::option::Option<wasm_bindgen::closure::Closure<dyn std::ops::FnMut()>>>>]`
   = note: wrap the `[closure@src/lib.rs:89:51: 92:6 game:Game, f:std::rc::Rc<std::cell::RefCell<std::option::Option<wasm_bindgen::closure::Closure<dyn std::ops::FnMut()>>>>]` in a closure with no arguments: `|| { /* code */ }
   = note: required for the cast to the object type `dyn std::ops::FnMut()`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `fighting-pixel`.

To learn more, run the command again with --verbose.

如果我注释掉 game.render() 它会编译。但我想保持一个将被更新以创建动画的状态。我做错了什么?为什么闭包不允许调用结构体方法?

提前感谢您的帮助。

【问题讨论】:

    标签: rust wasm-bindgen


    【解决方案1】:

    我发现了问题。 Game 结构就像 -

    impl Game {
        fn render(self: &Game) {
            self.ctx.begin_path();
            self.ctx.arc(self.state.x, 50.0, 40.0, 0.0, 2.0 * std::f64::consts::PI);
            self.ctx.stroke();
        }
    }
    

    忘记为self 加上&amp; 符号。感谢 Discord 频道#wg-wasm 的 Pauan#6666 指出这一点。

    【讨论】:

    • “忘记放 & 符号”。立即生效,感谢分享。
    【解决方案2】:

    Shimul comment 为我工作。 在这里分享一下我的游戏start_loop阻塞函数。

    有趣的线在末尾:

    draw_scene(&self.state, &self.gl_context).unwrap();
    
    impl GameGl { pub fn start_loop(mut self) -> Result<(), JsValue> {
        // Render loop
        // Dont ask me
        let f = Rc::new(RefCell::new(None));
        let g = f.clone();
        const FPS_THROTTLE: f64 = 1000.0 / 60.0; // milliseconds / frames
        let mut previous: f64 = js_sys::Date::now();
        *g.borrow_mut() = Some(Closure::wrap(Box::new(move || {
            request_animation_frame(f.borrow().as_ref().unwrap());
    
            // Get time (miliseconds)
            let now = js_sys::Date::now();
    
            // Clause: must work or sleeep ?
            // The current rotation angle 1 rad/sec
            if now < previous + FPS_THROTTLE {
               return ();
            }
    
            // Update time
            let delta_time = now - previous;
            previous = now;
    
            // Update game
            self.state.cube_rotation += delta_time as f32 * 0.001;
    
            // Draw
            draw_scene(&self.state, &self.gl_context).unwrap();
                //&self.gl, &self.program_info, &self.texture, &buffers, &state).unwrap();
    
        }) as Box<dyn FnMut()>));
    
        console::log_1(&"Requesting animation frame".into());
        request_animation_frame(g.borrow().as_ref().unwrap());
        //let program_info = 
        Ok(())
    }}
    

    【讨论】:

      猜你喜欢
      • 2022-11-27
      • 2021-09-05
      • 2022-07-07
      • 2015-03-06
      • 2020-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多