Can fire with mouse
This commit is contained in:
		| @@ -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<Coordinates, Coordinates>; | ||||
|  | ||||
| #[derive(Eq, PartialEq)] | ||||
| enum GameStatus { | ||||
|     Pending, | ||||
| @@ -72,9 +75,12 @@ impl GameScreen { | ||||
|  | ||||
|     pub async fn show<B: Backend>(mut self, terminal: &mut Terminal<B>) -> Res<ScreenResult> { | ||||
|         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<B: Backend>(&mut self, f: &mut Frame<B>) { | ||||
|     fn ui<B: Backend>(&mut self, f: &mut Frame<B>) -> 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 | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user