use argh::FromArgs; use dungeon::*; use graphics::*; struct Game { window: Window, dungeon: Dungeon, // to ensure the most recently-pressed direction key is used: current_dir: Option<(Direction, Key)>, } impl Game { fn new(window: Window) -> Self { // Initial game state let dungeon = Dungeon::new(); Self { window, dungeon, current_dir: None, } } fn player_dir(&mut self) -> Option { const MOVE_KEYS: [(Direction, [Key; 2]); 4] = [ (Direction::North, [Key::Up, Key::W]), (Direction::West, [Key::Left, Key::A]), (Direction::South, [Key::Down, Key::S]), (Direction::East, [Key::Right, Key::D]), ]; // if a key was just pressed, use it for the new direction to move in for (dir, keys) in MOVE_KEYS { for key in keys { if self.window.is_key_pressed(key) { self.current_dir = Some((dir, key)); return Some(dir); } } } // otherwise, use existing direction, so long as the key is still down match self.current_dir { Some((dir, key)) if self.window.is_key_down(key) => return Some(dir), _ => self.current_dir = None, } // otherwise, use any key that is already down for (dir, keys) in MOVE_KEYS { for key in keys { if self.window.is_key_down(key) { self.current_dir = Some((dir, key)); return Some(dir); } } } // otherwise, no direction key is pressed, so return None None } fn run(&mut self) { // Main game loop while self.window.is_open() { // Handle keyboard input if self.window.is_key_pressed(Key::F3) { self.window.toggle_debug(); } let inputs = PlayerInput { direction: self.player_dir(), }; // Update game state self.dungeon.update(inputs, self.window.delta_time()); // Draw a single frame self.window.draw_frame(&self.dungeon); } } } /// Play a dungeon crawl game #[derive(FromArgs)] struct Args { /// enable vsync #[argh(switch)] vsync: bool, /// enable verbose logging #[argh(switch, short = 'v')] verbose: bool, } fn main() -> Result<()> { // Parse arguments let args: Args = argh::from_env(); // Load the window let window = WindowBuilder::new() .vsync(args.vsync) .verbose(args.verbose) .build()?; Game::new(window).run(); Ok(()) }