Trying to convert 5yr old piston event code to current code

I'm converting an old 2015 tutorials http://piston-tutorial.logdown.com/posts/306682 (about Rust game dev using Piston) to 2020 version to learning Rust better, and hoping to push the updates.

I converted Part 1 and am working on Part 2.

I know to convert the:

for e in window {

to:

 window.draw_2d(&event, |c, g, _device| {

but I'm having trouble with:

        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);
            }
            _ => {

            }
        }

Here is the full code:

extern crate piston_window;

use piston_window::*;

struct Game {
    rotation: f64,
    x: f64,
    y: f64,
    up_d: bool, down_d: bool, left_d: bool, right_d: bool
}

impl Game {
    fn new() -> Game {
        Game { rotation : 0.0, x : 0.0, y : 0.0, up_d: false, down_d: false, left_d: false, right_d: false }
    }
    fn on_update(&mut self, upd: UpdateArgs) {
        self.rotation += 3.0 * upd.dt;
        if self.up_d {
            self.y += (-50.0) * upd.dt;
        }
        if self.down_d {
            self.y += (50.0) * upd.dt;
        }
        if self.left_d {
            self.x += (-50.0) * upd.dt;
        }
        if self.right_d {
            self.x += (50.0) * upd.dt;
        }
    }
    fn on_draw(&mut self, ren: RenderArgs, e: PistonWindow) {
        e.draw_2d(|c, g| {
            clear([0.0, 0.0, 0.0, 1.0], g);
            let center = c.transform.trans((ren.width / 2) as f64, (ren.height / 2) as f64);
            let square = rectangle::square(0.0, 0.0, 100.0);
            let red = [1.0, 0.0, 0.0, 1.0];
            rectangle(red, square, center.trans(self.x, self.y).rot_rad(self.rotation).trans(-50.0, -50.0), g); // We translate the rectangle slightly so that it's centered; otherwise only the top left corner would be centered
        });
    }
    fn on_input(&mut self, inp: Input) {
        match inp {
            Input::Press(but) => {
                match but {
                    Button::Keyboard(Key::Up) => {
                        self.up_d = true;
                    }
                    Button::Keyboard(Key::Down) => {
                        self.down_d = true;
                    }
                    Button::Keyboard(Key::Left) => {
                        self.left_d = true;
                    }
                    Button::Keyboard(Key::Right) => {
                        self.right_d = true;
                    }
                    _ => {}
                }
            }
            Input::Release(but) => {
                match but {
                    Button::Keyboard(Key::Up) => {
                        self.up_d = false;
                    }
                    Button::Keyboard(Key::Down) => {
                        self.down_d = false;
                    }
                    Button::Keyboard(Key::Left) => {
                        self.left_d = false;
                    }
                    Button::Keyboard(Key::Right) => {
                        self.right_d = false;
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

fn main() {
    let window: PistonWindow = WindowSettings::new(
        "piston-tutorial",
        [600, 600]
    )
    .exit_on_esc(true)
    .build()
    .unwrap();
    let mut game = Game::new();
    for e in window {
        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);
            }
            _ => {

            }
        }
    }
}

It looks like the Render and Update variants of the Event enum have been moved into the nested Loop enum. That assumes that I found the current docs— they don’t know anything about a draw_2d function.

The recommended way to write the event loop nowadays is, IIRC, something along the lines of:

let mut events = Events::new(EventSettings::new());
while let Some(event) = events.next(&mut window) {
    // needs using trait UpdateArgs
    if let Some(args) = event.update_args() {
        // update ...
    }
    // needs using trait RenderArgs
    if let Some(args) = event.render_args() {
        // render ...
    }
    // ...
}

(not tested)

@2e71828 This helped some! ....but so far, I've come up with the replacement code for what is commented out. I found Loop::Update(upd) and Loop::Render(ren) and "nothing for the equivalent of Event::Input(inp)".

Can anyone give me a clue?

The code:

    while let Some(event) = window.next() {
        match event {
            Event::Loop(Loop::Update(ref upd)) => game.on_update(upd),
            Event::Loop(Loop::Render(ref ren)) => game.on_draw(ren, &window),
            ???Event::Loop(Loop::???(ref inp)) => game.on_input(inp),
            _ => {}
        }
    }

    // for e in window {
    //     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);
    //         }
    //         _ => {

    //         }
    //     }
    // }

It looks like it’s Event::Input(Input, Option<u32>) now. Having never used Piston myself, I have no idea what the new parameter indicates.

Does anyone know what I should put for the Option parameter in the following code?

    while let Some(event) = window.next() {
        match event {
            Event::Loop(Loop::Update(ref upd)) => game.on_update(upd),
            Event::Loop(Loop::Render(ref ren)) => game.on_draw(ren, &mut window, &event),
            // ???Event::Loop(Loop::???(ref inp)) => game.on_input(inp),
            Event::Input(inp, ***Option<u32>***) => game.on_input(inp),
            _ => {}
        }
    }

It looks like it’s a timestamp. I also have no familiarity with piston but here’s a link to docs that say it’s a timestamp.

Docs

If you click on timestamp then it says it’s

Measured in milliseconds since initialization of window.

1 Like

Thanks to all who tried to help!
I finally figured out the problems. This conversion effort is fascinating.
Here is the converted code:

extern crate piston_window;

use piston_window::*;

struct Game {
    rotation: f64,
    x: f64,
    y: f64,
    up_d: bool,
    down_d: bool,
    left_d: bool,
    right_d: bool,
}

impl Game {
    fn new() -> Game {
        Game {
            rotation: 0.0,
            x: 0.0,
            y: 0.0,
            up_d: false,
            down_d: false,
            left_d: false,
            right_d: false,
        }
    }
    fn on_update(&mut self, upd: &UpdateArgs) {
        self.rotation += 3.0 * upd.dt;
        if self.up_d {
            self.y += (-50.0) * upd.dt;
        }
        if self.down_d {
            self.y += (50.0) * upd.dt;
        }
        if self.left_d {
            self.x += (-50.0) * upd.dt;
        }
        if self.right_d {
            self.x += (50.0) * upd.dt;
        }
    }
    fn on_draw(&mut self, ren: &RenderArgs, window: &mut PistonWindow, event: &Event) {
        let window_dimensions = ren.draw_size; 
        let width = window_dimensions[0]; 
        let height = window_dimensions[1]; 
        window.draw_2d(event, |c, g, _device| {
            clear([0.0, 0.0, 0.0, 1.0], g);
            let center = c.transform.trans((width / 2) as f64, (height / 2) as f64);
            let square = rectangle::square(0.0, 0.0, 100.0);
            let red = [1.0, 0.0, 0.0, 1.0];
            rectangle(
                red,
                square,
                center
                    .trans(self.x, self.y)
                    .rot_rad(self.rotation)
                    .trans(-50.0, -50.0),
                g,
            ); // We translate the rectangle slightly so that it's centered; otherwise only the top left corner would be centered
        });
    }
    fn on_input(&mut self, inp: &Input) {
        match inp {
            Input::Button(but) => match but.state {
                ButtonState::Press => match but.button {
                    Button::Keyboard(Key::Up) => self.up_d = true,
                    Button::Keyboard(Key::Down) => self.down_d = true,
                    Button::Keyboard(Key::Left) => self.left_d = true,
                    Button::Keyboard(Key::Right) => self.right_d = true,
                    _ => (),
                },
                ButtonState::Release => match but.button {
                    Button::Keyboard(Key::Up) => self.up_d = false,
                    Button::Keyboard(Key::Down) => self.down_d = false,
                    Button::Keyboard(Key::Left) => self.left_d = false,
                    Button::Keyboard(Key::Right) => self.right_d = false,
                    _ => (),
                },
                _ => {}
            },
            _ => {}
        }
    }
}

fn main() {
    let mut window: PistonWindow = WindowSettings::new("piston-tutorial", [600, 600])
        .exit_on_esc(true)
        .build()
        .unwrap();
    let mut game = Game::new();

    while let Some(event) = window.next() {
        match event {
            Event::Loop(Loop::Update(ref upd)) => game.on_update(upd),
            Event::Loop(Loop::Render(ref ren)) => game.on_draw(ren, &mut window, &event),
            Event::Input(ref inp, _) => game.on_input(inp),
            _ => {}
        }
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.