From 3455559d33bf3a374de2544d29443aebdbeb4f96 Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Sat, 15 Oct 2022 16:06:47 +0200 Subject: [PATCH] Can fire with mouse --- rust/cli_player/src/ui_screens/game_screen.rs | 59 +++++++++++++++---- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/rust/cli_player/src/ui_screens/game_screen.rs b/rust/cli_player/src/ui_screens/game_screen.rs index 4a7faaf..c09650c 100644 --- a/rust/cli_player/src/ui_screens/game_screen.rs +++ b/rust/cli_player/src/ui_screens/game_screen.rs @@ -1,8 +1,9 @@ use std::cmp::max; +use std::collections::HashMap; use std::time::{Duration, Instant}; use crossterm::event; -use crossterm::event::{Event, KeyCode}; +use crossterm::event::{Event, KeyCode, MouseButton, MouseEventKind}; use tui::backend::Backend; use tui::layout::{Constraint, Direction, Layout}; use tui::style::Color; @@ -22,6 +23,8 @@ use crate::ui_screens::utils::{centered_rect_size, centered_text}; use crate::ui_screens::ScreenResult; use crate::ui_widgets::game_map_widget::{ColoredCells, GameMapWidget}; +type CoordinatesMapper = HashMap; + #[derive(Eq, PartialEq)] enum GameStatus { Pending, @@ -72,9 +75,12 @@ impl GameScreen { pub async fn show(mut self, terminal: &mut Terminal) -> Res { let mut last_tick = Instant::now(); + + let mut coordinates_mapper = CoordinatesMapper::new(); + loop { // Update UI - terminal.draw(|f| self.ui(f))?; + terminal.draw(|f| coordinates_mapper = self.ui(f))?; let timeout = TICK_RATE .checked_sub(last_tick.elapsed()) @@ -82,7 +88,10 @@ impl GameScreen { // Handle terminal events if crossterm::event::poll(timeout)? { - if let Event::Key(key) = event::read()? { + let event = event::read()?; + + // Keyboard event + if let Event::Key(key) = &event { let mut new_shoot_pos = self.curr_shoot_position; match key.code { @@ -102,9 +111,11 @@ impl GameScreen { // Shoot KeyCode::Enter if self.can_fire() => { if self.game.can_fire_at_location(self.curr_shoot_position) { - self.client.send_message(&ClientMessage::Fire { - location: self.curr_shoot_position, - }).await?; + self.client + .send_message(&ClientMessage::Fire { + location: self.curr_shoot_position, + }) + .await?; } } @@ -115,6 +126,17 @@ impl GameScreen { self.curr_shoot_position = new_shoot_pos; } } + + // Mouse event + if let Event::Mouse(mouse) = event { + if mouse.kind == MouseEventKind::Up(MouseButton::Left) { + if let Some(c) = + coordinates_mapper.get(&Coordinates::new(mouse.column, mouse.row)) + { + self.curr_shoot_position = *c; + } + } + } } // Handle incoming messages @@ -213,7 +235,7 @@ impl GameScreen { // Sunk boats let sunk_boats = ColoredCells { - color: Color::Red, + color: Color::Gray, cells: map .sunk_boats .iter() @@ -223,13 +245,13 @@ impl GameScreen { // Touched boats let touched_areas = ColoredCells { - color: Color::Rgb(245, 45, 7), + color: Color::Red, cells: map.successful_strikes.clone(), }; // Failed strikes let failed_strikes = ColoredCells { - color: Color::Gray, + color: Color::DarkGray, cells: map.failed_strikes.clone(), }; @@ -251,7 +273,7 @@ impl GameScreen { .add_colored_cells(boats) } - fn ui(&mut self, f: &mut Frame) { + fn ui(&mut self, f: &mut Frame) -> CoordinatesMapper { let status_text = self .status .status_text() @@ -260,7 +282,7 @@ impl GameScreen { // If the game is in a state where game maps can not be shown if !self.status.can_show_game_maps() { PopupScreen::new(&status_text).show_in_frame(f); - return; + return HashMap::default(); } // Draw main ui (default play UI) @@ -268,9 +290,17 @@ impl GameScreen { .player_map(&self.game.your_map, false) .set_title("YOUR map"); + let mut coordinates_mapper = HashMap::new(); let mut opponent_map = self .player_map(&self.game.opponent_map, true) - .set_title(self.opponent_name()); + .set_title(self.opponent_name()) + .set_yield_func(|c, r| { + for i in 0..r.width { + for j in 0..r.height { + coordinates_mapper.insert(Coordinates::new(r.x + i, r.y + j), c); + } + } + }); if self.can_fire() { opponent_map = opponent_map @@ -295,7 +325,7 @@ impl GameScreen { // Check if frame is too small if max_width > f.size().width || total_height > f.size().height { PopupScreen::new("Screen too small!").show_in_frame(f); - return; + return HashMap::default(); } let chunks = Layout::default() @@ -330,10 +360,13 @@ impl GameScreen { f.render_widget(opponent_map, chunks[1]); } else { f.render_widget(player_map, chunks[1]); + drop(opponent_map); } } // Render buttons // TODO : at the end of the game + + coordinates_mapper } }