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 {
 | 
			
		||||
                                self.client
 | 
			
		||||
                                    .send_message(&ClientMessage::Fire {
 | 
			
		||||
                                        location: self.curr_shoot_position,
 | 
			
		||||
                                }).await?;
 | 
			
		||||
                                    })
 | 
			
		||||
                                    .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