I am trying to write a game in Rust using piston_window(0.77.0) library. Starting from their hello world example I thought I would start by separating of rendering logic into a method using Event as parameter since according to documentation it is returned by window.next().
use piston_window::*;
pub struct UI<'a> {
window: &'a mut PistonWindow,
}
impl <'a> UI<'a> {
pub fn new(window: &mut PistonWindow) -> UI {
UI {
window,
}
}
fn render(&self, event: &Event) {
self.window.draw_2d(&event, |context, graphics| {
clear([1.0; 4], graphics);
rectangle(
[1.0, 0.0, 0.0, 1.0],
[0.0, 0.0, 100.0, 100.0],
context.transform,
graphics);
});
}
pub fn run(&mut self) {
use Loop::Render;
use Event::Loop;
while let Some(event) = self.window.next() {
match event {
Loop(Render(_)) => self.render(&event),
_ => {}
}
}
}
}
However this ends with an error:
self.window.draw_2d(&event, |context, graphics| {
the trait piston_window::GenericEvent is not implemented for &piston_window::Event
Code without extracted render method works as expected.
pub fn run(&mut self) {
use Loop::Render;
use Event::Loop;
while let Some(event) = self.window.next() {
match event {
Loop(Render(_)) => {
self.window.draw_2d(&event, |context, graphics| {
clear([1.0; 4], graphics);
rectangle(
[1.0, 0.0, 0.0, 1.0],
[0.0, 0.0, 100.0, 100.0],
context.transform,
graphics);
});
},
_ => {}
}
}
}
How can I extract this? Is there something I am overlooking?
The event variable has type &Event, not Event, so you are actually trying to pass an &&Event to window.draw_2d. Event implements GenericEvent but &Event does not, which is why you see that error.
You just need to do:
self.window.draw_2d(event, |context, graphics| {
...
}
instead of:
self.window.draw_2d(&event, |context, graphics| {
...
}
To be fair on the Rust compiler, it couldn't have done much more to point you in the right direction. When I compile your code, the full error message is:
error[E0277]: the trait bound `&piston_window::Event: piston_window::GenericEvent` is not satisfied
--> src/main.rs:34:21
|
34 | self.window.draw_2d(&event, |context, graphics| {
| ^^^^^^^ the trait `piston_window::GenericEvent` is not implemented for `&piston_window::Event`
|
= help: the following implementations were found:
<piston_window::Event as piston_window::GenericEvent>
That last "help" part is telling you that piston_window::Event does have the right implementation, while the preceding error is saying that &piston_window::Event does not.
Related
I have this structure
#[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
struct ProjUniform {
view_proj: [[f32; 3]; 3],
}
impl ProjUniform {
fn new() -> Self {
Self {
view_proj: [[0.0, 0.0, 0.0],
[1.0, 1.0, 0.5],
[0.0, 0.0, 1.0],
]
}
}
}
I pass to gpu like this:
let proj_uniform = ProjUniform::new();
let proj_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
label: Some("Proj Buffer"),
contents: bytemuck::cast_slice(&[proj_uniform]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST
});
Now I've debugged this, and I don't get the correct mat3 structure in the shader. it is off and twisted. How do I debug this thing?
This is shader code:
[[block]]
struct ProjectUniform {
view_proj: mat3x3<f32>;
};
[[group(1), binding(0)]]
var<uniform> project: ProjectUniform;
I am trying to create a requestAnimationFrame loop, which will call game.render() for every frame. I am following this tutorial - 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
}
}
}
But it gives following error -
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.
If I comment out game.render() it compiles. But I want to keep a state which will be updated to create an animation. What I am doing wrong? Why Closure doesn't allow to call struct methods?
Thanks in advance for your help.
I found the issue. The Game struct would be like -
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();
}
}
Forgot to put & symbol for self. Thanks Pauan#6666 from Discord channel #wg-wasm for pointing that out.
Shimul comment worked for me.
I share here my game start_loop blocking function.
where the insteresting line is at the end:
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(())
}}
I am trying to do error handling when using .iter() in combination with .flat_map, which has an .iter().map() within it.
The scenario is getting all the Events that belong to a set of organisations, where the nested .iter().map() is used to get the participants of each event, combine that with the event and return an EventResponse stuct.
A non-specific-scenario way of describing the issue would be 'How to get Result<Vec<T>, err> from nested flat_map of Result<Vec<T>, err>, which has nested map of Result<T, err>'
Below is an abstracted/simplified version of the code I'm using, that gives me the same errors as my actual code.
struct Event {
id: usize,
}
#[derive(Debug)]
struct EventResponse {
id: usize,
participants: Vec<i32>,
}
fn main() {
let orgs = vec![1, 3, 14, 12];
let events: Result<Vec<EventResponse>, &str> = orgs
.iter()
.flat_map::<Result<Vec<EventResponse>, &str>, _>(|org_id| {
get_events_for(*org_id)
.map_err(|_| "That Org id does not exist")
.map(|events| {
events
.iter()
.map::<Result<EventResponse, &str>, _>(|event| {
get_event_with_participants(event)
.map(|event_response| event_response)
.map_err(|_| "Participants for that event were not found")
})
.collect()
})
})
.collect();
}
fn get_events_for(id: usize) -> Result<Vec<Event>, ()> {
// pretend we are checking against a database of existing org ids, if the org id does not exist, then return an error
if id == 3 {
Ok(vec![Event { id }])
} else {
Err(())
}
}
fn get_event_with_participants(event: &Event) -> Result<EventResponse, ()> {
//pretend the participants are fetched from a database
let foundParticipants = true;
if foundParticipants {
Ok(EventResponse {
id: event.id,
participants: vec![1, 2, 5],
})
} else {
Err(())
}
}
Playground
The type annotations are to show what is expected to be returned at each stage. I expect events to be of type Result<Vec<EventResponse>, &str> but I am getting 2 errors:
error[E0277]: a collection of type `std::vec::Vec<EventResponse>` cannot be built from an iterator over elements of type `std::result::Result<EventResponse, &str>`
--> example.rs:27:26
|
27 | .collect()
| ^^^^^^^ a collection of type `std::vec::Vec<EventResponse>` cannot be built from `std::iter::Iterator<Item=std::result::Result<EventResponse, &str>>`
|
= help: the trait `std::iter::FromIterator<std::result::Result<EventResponse, &str>>` is not implemented for `std::vec::Vec<EventResponse>`
error[E0277]: a collection of type `std::result::Result<std::vec::Vec<EventResponse>, &str>` cannot be built from an iterator over elements of type `std::vec::Vec<EventResponse>`
--> example.rs:30:10
|
30 | .collect();
| ^^^^^^^ a collection of type `std::result::Result<std::vec::Vec<EventResponse>, &str>` cannot be built from `std::iter::Iterator<Item=std::vec::Vec<EventResponse>>`
|
= help: the trait `std::iter::FromIterator<std::vec::Vec<EventResponse>>` is not implemented for `std::result::Result<std::vec::Vec<EventResponse>, &str>`
EDIT: The get_events_for function cannot be modified, however, the get_event_with_participants function can be modified, if that helps.
Being interested in the problem, I tried to implement this with map and try_fold. Using flat_map directly didn't work for me, as I couldn't get around the fact that the first inner loop has to produce a Result. I moved the error messages into the functions, but that could easily be undone if you explicitly wanted to avoid it.
struct Event {
id: usize,
}
#[derive(Debug)]
struct EventResponse {
id: usize,
participants: Vec<i32>,
}
fn main() {
let orgs = vec![1, 3, 14, 12];
let events: Result<Vec<EventResponse>, &str> = orgs
.iter()
.map(|org_id| {
get_events_for(*org_id)?
.iter()
.map(get_event_with_participants)
.collect::<Result<Vec<_>, _>>()
})
.collect::<Result<Vec<_>, _>>()
.map(|org_responses| org_responses.into_iter().flatten().collect());
}
fn get_events_for(id: usize) -> Result<Vec<Event>, &'static str> {
// pretend we are checking against a database of existing org ids, if the org id does not exist, then return an error
if id == 3 {
Ok(vec![Event { id }])
} else {
Err("That Org id does not exist")
}
}
fn get_event_with_participants(event: &Event) -> Result<EventResponse, &'static str> {
//pretend the participants are fetched from a database
let foundParticipants = true;
if foundParticipants {
Ok(EventResponse {
id: event.id,
participants: vec![1, 2, 5],
})
} else {
Err("Participants for that event were not found")
}
}
For try_fold, the main function would become:
fn main() {
let orgs = vec![1, 3, 14, 12];
let events: Result<Vec<EventResponse>, &str> =
orgs.iter().try_fold(Vec::new(), |mut responses, &org| {
responses = get_events_for(org)?
.into_iter()
.try_fold(responses, |mut responses, event| {
let response = get_event_with_participants(&event)?;
responses.push(response);
Ok(responses)
})?;
Ok(responses)
});
}
Personally I'm a fan of the map version, as modifying a Vec using try_fold feels awkward since you have to return the accumulator despite modifying the Vec directly.
Another version to consider is to just use loops, which appears to be far simpler in this situation since you can use the ? operator for errors:
fn main() {
let orgs = vec![1, 3, 14, 12];
let events = get_all_responses(orgs);
}
fn get_all_responses(
orgs: impl IntoIterator<Item = usize>,
) -> Result<Vec<EventResponse>, &'static str> {
let mut responses = Vec::new();
for org in orgs.into_iter() {
for event in get_events_for(org)? {
responses.push(get_event_with_participants(&event)?)
}
}
Ok(responses)
}
I'm struggling with a SpinButton in Rust using Relm. (Disclaimer, I'm a noob with Rust and GTK)
#![feature(proc_macro)]
extern crate gtk;
use chrono::{NaiveTime, Duration};
use gtk::prelude::*;
use gtk::{
WidgetExt,
ContainerExt,
EntryExt,
Adjustment
};
use relm::Widget;
use relm_attributes::widget;
#[derive(Msg, Debug)]
pub enum Msg {
Changed,
Display,
}
#[widget]
impl Widget for DurationSpin {
fn model(m: Duration) -> Duration {
m
}
fn update(&mut self, event: Msg) {
match event {
Msg::Display => self.format_display(),
Msg::Changed => {
println!("update, self.spin_btn.get_value_as_int() = {:?}", self.spin_btn.get_value_as_int());
self.model = Duration::minutes(self.spin_btn.get_value_as_int() as i64)
},
};
}
fn format_display(&mut self) {
println!("format_display, self.spin_btn.get_value_as_int() = {:?}", self.spin_btn.get_value_as_int());
let minus = self.model.num_hours() * 60;
self.spin_btn.set_text(&format!("{:02}:{:02}",
self.model.num_hours(), self.model.num_minutes() - minus));
}
view! {
#[name="spin_btn"]
gtk::SpinButton {
max_width_chars: 5,
width_chars: 5,
max_length: 5,
numeric: false,
output => (Msg::Display, Inhibit(false)),
value_changed => Msg::Changed,
adjustment: &Adjustment::new(self.model.num_minutes() as f64, 0.0, 720.0, 1.0, 60.0, 0.0),
}
}
}
(whole project here: https://github.com/Geobert/rusty_flexi)
My issue is that clicking on "+" makes get_value_as_int always returns '1'.
It seems that my output signal is causing this as deactivating the connection solves the bug but I can't see what's wrong with it.
It seems the output signal handler must not be asynchronous. That means you should not use relm message passing in this case.
You should do something like:
fn init_view(&mut self) {
let hours = self.model.num_hours();
let minutes = self.model.num_minutes();
self.spin_btn.connect_output(move |spin_btn| {
let minus = hours * 60;
spin_btn.set_text(&format!("{:02}:{:02}",
hours, minutes - minus));
Inhibit(false)
});
}
and remove output => (Msg::Display, Inhibit(false)),
I have a problem with this code:
extern crate piston_window;
extern crate find_folder;
extern crate gfx_graphics;
extern crate gfx;
extern crate gfx_device_gl;
use piston_window::*;
use gfx_device_gl::{Resources, Output, CommandBuffer};
use gfx_graphics::GfxGraphics;
struct Object {
x: f64,
y: f64,
sprite: Option<Texture<Resources>>,
}
impl Object {
fn new() -> Object {
Object {
x: 0.0,
y: 0.0,
sprite: None,
}
}
fn mov(&mut self, x: f64, y: f64) {
self.x = x;
self.y = y;
}
fn render(&self,
g: &mut GfxGraphics<Resources, CommandBuffer<Resources>, Output>,
view: math::Matrix2d) {
let square = rectangle::square(0.0, 0.0, 100.0);
let red = [1.0, 0.0, 0.0, 1.0];
match self.sprite {
None => {
rectangle(red,
square,
view.trans(self.x, self.y).trans(-50.0, -50.0),
g);
}
Some(ref sprite) => {
image(sprite, view.trans(self.x, self.y).trans(-50.0, -50.0), g);
}
}
}
fn setSprite(&mut self, sprite: Texture<Resources>) {
self.sprite = Some(sprite);
}
}
struct Game {
position: f64,
one: bool,
two: bool,
three: bool,
four: bool,
five: bool,
six: bool,
seven: bool,
eight: bool,
nine: bool,
player: Object,
}
impl Game {
fn new() -> Game {
Game {
rotation: 0.0,
player: Object::new(),
one: false,
two: false,
three: false,
four: false,
five: false,
six: false,
seven: false,
eight: false,
nine: false,
}
}
fn on_load(&mut self, w: &PistonWindow) {
let assets = find_folder::Search::ParentsThenKids(3, 3) //Cerca la cartella assets
.for_folder("assets").unwrap();
let tris = assets.join("x.png");
let tris = Texture::from_path(&mut *w.factory, &tris, Flip::None, &TextureSettings::new())
.unwrap();
self.player.setSprite(tris);
}
fn on_update(&mut self, upd: UpdateArgs) {
self.position += 3.0 * upd.dt;
if self.one {
self.player.mov(100.0, 100.0);
}
if self.two {
self.player.mov(100.0, 200.0);
}
if self.three {
self.player.mov(100.0, 300.0);
}
if self.four {
self.player.mov(200.0, 100.0);
}
if self.five {
self.player.mov(300.0, 100.0);
}
if self.six {
self.player.mov(200.0, 200.0);
}
if self.seven {
self.player.mov(200.0, 300.0);
}
if self.eight {
self.player.mov(300.0, 200.0);
}
if self.nine {
self.player.mov(300.0, 300.0);
}
}
fn on_draw(&mut self, ren: RenderArgs, e: PistonWindow) {
e.draw_2d(|c, g| {
clear([0.0, 0.0, 0.0], g);
let center = c.transf((ren.width / 2) as f64, (ren.eight / 2) as f64);
self.player.render(g, center);
});
}
fn on_input(&mut self, inp: Input) {
match inp {
Input::Press(but) => {
match but {
Button::Keyboard(Key::D1) => {
self.one = true;
}
Button::Keyboard(Key::D2) => {
self.two = true;
}
Button::Keyboard(Key::D3) => {
self.three = true;
}
Button::Keyboard(Key::D4) => {
self.four = true;
}
Button::Keyboard(Key::D5) => {
self.five = true;
}
Button::Keyboard(Key::D6) => {
self.six = true;
}
Button::Keyboard(Key::D7) => {
self.seven = true;
}
Button::Keyboard(Key::D8) => {
self.eight = true;
}
Button::Keyboard(Key::D9) => {
self.nine = true;
}
_ => {}
}
}
}
}
}
fn main() {
let title = "Tris"; //Titolo della finestra
let mut window: PistonWindow = WindowSettings::new(title, [800, 600]) //Crea la finestra
.exit_on_esc(true)
.build()
.unwrap_or_else(|e| { panic!("Failed to build PistonWindow: {}", e) });
let mut game = Game::new();
game.on_load(&window);
let assets = find_folder::Search::ParentsThenKids(3, 3) //Cerca la cartella assets
.for_folder("assets").unwrap();
let tris = assets.join("tris.png");
let tris = Texture::from_path(&mut window.factory,
&tris,
Flip::None,
&TextureSettings::new())
.unwrap();
let x = assets.join("x.png");
let x = Texture::from_path(&mut window.factory, &x, Flip::None, &TextureSettings::new())
.unwrap();
let o = assets.join("o.png");
let o = Texture::from_path(&mut window.factory, &o, Flip::None, &TextureSettings::new())
.unwrap();
while let Some(e) = window.next() {
// Inizia il ciclo e disegna la roba sotto
window.draw_2d(&e, |c, g| {
clear([0.0, 0.0, 0.0, 0.0], g);
image(&tris, c.transform, g);
});
match e.event {
Some(Event::Update(upd)) => {
game.on_update(upd);
}
Some(Event::Render(ren)) => {
game.on_draw(ren, e);
}
Some(Event::Input(inp)) => {
game.on_input(inp);
}
_ => {}
}
}
}
(Playground)
When I try to compile it, it says the error:
the trait bound `gfx_device_gl::Resources: gfx_core::Resources` is not
satisfied [E0277]
src/main.rs:14 sprite: Option<Texture<Resources>>,
And the second error:
error: the trait bound `gfx_device_gl::Resources: gfx_core::Resources`
is not satisfied [E0277]
src/main.rs:39 fn setSprite(&mut self, sprite: Texture<Resources>) {
src/main.rs:40 self.sprite = Some(sprite);
src/main.rs:41 }
How should I fix it? I looked online but found nothing about it.
I was getting an identical compile error on very similar code and setting
gfx_device_gl = "=0.9.0"
in Cargo.toml caused it to stop happening for me. Previously, I was using 0.11.0.
After changing this, I get other (I believe separate/independent) compilation errors, but perhaps this solves your predicament.