2

I'm currently teaching myself Rust with a roguelike tutorial, and I'm attempting to get a key press to move a character diagonally which would mean player_x -=1, player_y -= 1 for up left.

No matter which way I try to arrange the code, I keep getting error messages from the compiler. I couldn't find any example of this anywhere in the documentation or on GitHub.

Key { code: Escape, .. } => return true, // exit game

// movement keys
Key { code: Up, .. } => *player_y -= 1,
Key { code: Down, .. } => *player_y += 1,
Key { code: Left, .. } => *player_x -= 1,
Key { code: Right, .. } => *player_x += 1,
Key { printable: 'k', .. } => *player_y -= 1,
Key { printable: 'k', .. } => *player_x -= 1,

_ => {}

You can kind of see what I'm trying to do here, but this throws an error message saying the pattern is unreachable, how would I fix this code?

Here's the full code, it's fairly small, not sure what would be alone necessary to compile:

extern crate tcod;
extern crate input;

use tcod::console::*;
use tcod::colors;

// actual size of the window
const SCREEN_WIDTH: i32 = 80;
const SCREEN_HEIGHT: i32 = 50;

const LIMIT_FPS: i32 = 20;  // 20 frames-per-second maximum


fn handle_keys(root: &mut Root, player_x: &mut i32, player_y: &mut i32) -> bool {
    use tcod::input::Key;
    use tcod::input::KeyCode::*;

    let key = root.wait_for_keypress(true);
    match key {
        Key { code: Enter, alt: true, .. } => {
            // Alt+Enter: toggle fullscreen
            let fullscreen = root.is_fullscreen();
            root.set_fullscreen(!fullscreen);
        }
        Key { code: Escape, .. } => return true,  // exit game

        // movement keys
        Key { code: Up, .. } => *player_y -= 1,
        Key { code: Down, .. } => *player_y += 1,
        Key { code: Left, .. } => *player_x -= 1,
        Key { code: Right, .. } => *player_x += 1,
        Key { printable: 'k', ..} => *player_y -= 1,
        Key { printable: 'k', ..} => *player_x -= 1,

        _ => {},
    }

    false
}

fn main() {
    let mut root = Root::initializer()
        .font("terminal8x8_gs_tc.png", FontLayout::Tcod)
        .font_type(FontType::Greyscale)
        .size(SCREEN_WIDTH, SCREEN_HEIGHT)
        .title("Rust/libtcod tutorial")
        .init();

    tcod::system::set_fps(LIMIT_FPS);

    let mut player_x = SCREEN_WIDTH / 2;
    let mut player_y = SCREEN_HEIGHT / 2;

    while !root.window_closed() {
        root.set_default_foreground(colors::WHITE);
        root.put_char(player_x, player_y, '@', BackgroundFlag::None);

        root.flush();

        root.put_char(player_x, player_y, ' ', BackgroundFlag::None);

        // handle keys and exit game if needed
        let exit = handle_keys(&mut root, &mut player_x, &mut player_y);
        if exit {
            break
        }
    }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
lerugray
  • 369
  • 3
  • 12

2 Answers2

9

How to assign 2 variables simultaneously in Rust?

You cannot. You can bind two variables at once:

let (a, b) = (1, 2);

If you aren't trying to create new bindings, you need to have two assignment statements:

let mut a = 1;
let mut b = 2;

a = 3;
b = 4;

In your case, for a match statement, you need to introduce a block:

let key = 42;
let mut a = 1;
let mut b = 2;

match key {
    0 => {
        a += 1;
        b -= 1;
    }
    _ => {
        a -= 10;
        b *= 100;
    }
}

You could also have the match expression evaluate to a tuple, which you then create new bindings for and apply them afterwards:

let key = 42;
let mut x = 1;
let mut y = 2;

let (d_x, d_y) = match key {
    0 => (1, -1),
    _ => (10, 10),
};

x += d_x;
y += d_y;

I strongly recommend reading The Rust Programming Language instead of trying to learn Rust by intuition or trial and error. It has an entire chapter on the match statement.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
1

The second printable: 'k' is unreachable, since the first will match instead. What you want is doing both assignments in the same arm of the match, like this:

Key { printable: 'k', .. } => {
    *player_y -= 1;
    *player_x -= 1;
}
Rasmus Kaj
  • 4,224
  • 1
  • 20
  • 23
  • Perfect! This syntax was just what I was looking for, would have never guessed using the semi colon's there, thank you! – lerugray Dec 07 '17 at 16:18