Can fire with keyboard
This commit is contained in:
		@@ -18,7 +18,7 @@ use cli_player::server::start_server_if_missing;
 | 
				
			|||||||
use cli_player::ui_screens::configure_game_rules::GameRulesConfigurationScreen;
 | 
					use cli_player::ui_screens::configure_game_rules::GameRulesConfigurationScreen;
 | 
				
			||||||
use cli_player::ui_screens::game_screen::GameScreen;
 | 
					use cli_player::ui_screens::game_screen::GameScreen;
 | 
				
			||||||
use cli_player::ui_screens::popup_screen::PopupScreen;
 | 
					use cli_player::ui_screens::popup_screen::PopupScreen;
 | 
				
			||||||
use cli_player::ui_screens::select_play_mode::{SelectPlayModeResult, SelectPlayModeScreen};
 | 
					use cli_player::ui_screens::select_play_mode_screen::{SelectPlayModeResult, SelectPlayModeScreen};
 | 
				
			||||||
use cli_player::ui_screens::*;
 | 
					use cli_player::ui_screens::*;
 | 
				
			||||||
use sea_battle_backend::data::GameRules;
 | 
					use sea_battle_backend::data::GameRules;
 | 
				
			||||||
use sea_battle_backend::human_player_ws::ServerMessage;
 | 
					use sea_battle_backend::human_player_ws::ServerMessage;
 | 
				
			||||||
@@ -37,14 +37,14 @@ async fn run_dev<B: Backend>(
 | 
				
			|||||||
            .show(terminal)?
 | 
					            .show(terminal)?
 | 
				
			||||||
            .as_string(),
 | 
					            .as_string(),
 | 
				
			||||||
        TestDevScreen::Confirm => {
 | 
					        TestDevScreen::Confirm => {
 | 
				
			||||||
            confirm_dialog::ConfirmDialogScreen::new("Do you really want to quit game?")
 | 
					            confirm_dialog_screen::ConfirmDialogScreen::new("Do you really want to quit game?")
 | 
				
			||||||
                .show(terminal)?
 | 
					                .show(terminal)?
 | 
				
			||||||
                .as_string()
 | 
					                .as_string()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        TestDevScreen::SelectBotType => select_bot_type::SelectBotTypeScreen::default()
 | 
					        TestDevScreen::SelectBotType => select_bot_type_screen::SelectBotTypeScreen::default()
 | 
				
			||||||
            .show(terminal)?
 | 
					            .show(terminal)?
 | 
				
			||||||
            .as_string(),
 | 
					            .as_string(),
 | 
				
			||||||
        TestDevScreen::SelectPlayMode => select_play_mode::SelectPlayModeScreen::default()
 | 
					        TestDevScreen::SelectPlayMode => select_play_mode_screen::SelectPlayModeScreen::default()
 | 
				
			||||||
            .show(terminal)?
 | 
					            .show(terminal)?
 | 
				
			||||||
            .as_string(),
 | 
					            .as_string(),
 | 
				
			||||||
        TestDevScreen::SetBoatsLayout => {
 | 
					        TestDevScreen::SetBoatsLayout => {
 | 
				
			||||||
@@ -53,7 +53,7 @@ async fn run_dev<B: Backend>(
 | 
				
			|||||||
                ..Default::default()
 | 
					                ..Default::default()
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            set_boats_layout::SetBoatsLayoutScreen::new(&rules)
 | 
					            set_boats_layout_screen::SetBoatsLayoutScreen::new(&rules)
 | 
				
			||||||
                .show(terminal)?
 | 
					                .show(terminal)?
 | 
				
			||||||
                .as_string()
 | 
					                .as_string()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@ use tui::{Frame, Terminal};
 | 
				
			|||||||
use sea_battle_backend::data::GameRules;
 | 
					use sea_battle_backend::data::GameRules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::constants::{HIGHLIGHT_COLOR, TICK_RATE};
 | 
					use crate::constants::{HIGHLIGHT_COLOR, TICK_RATE};
 | 
				
			||||||
use crate::ui_screens::select_bot_type::SelectBotTypeScreen;
 | 
					use crate::ui_screens::select_bot_type_screen::SelectBotTypeScreen;
 | 
				
			||||||
use crate::ui_screens::utils::centered_rect_size;
 | 
					use crate::ui_screens::utils::centered_rect_size;
 | 
				
			||||||
use crate::ui_screens::ScreenResult;
 | 
					use crate::ui_screens::ScreenResult;
 | 
				
			||||||
use crate::ui_widgets::button_widget::ButtonWidget;
 | 
					use crate::ui_widgets::button_widget::ButtonWidget;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,20 +3,21 @@ use std::time::{Duration, Instant};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use crossterm::event;
 | 
					use crossterm::event;
 | 
				
			||||||
use crossterm::event::{Event, KeyCode};
 | 
					use crossterm::event::{Event, KeyCode};
 | 
				
			||||||
use sea_battle_backend::data::{CurrentGameMapStatus, CurrentGameStatus};
 | 
					 | 
				
			||||||
use sea_battle_backend::human_player_ws::{ClientMessage, ServerMessage};
 | 
					 | 
				
			||||||
use sea_battle_backend::utils::Res;
 | 
					 | 
				
			||||||
use tui::backend::Backend;
 | 
					use tui::backend::Backend;
 | 
				
			||||||
use tui::layout::{Constraint, Direction, Layout};
 | 
					use tui::layout::{Constraint, Direction, Layout};
 | 
				
			||||||
use tui::style::Color;
 | 
					use tui::style::Color;
 | 
				
			||||||
use tui::widgets::Paragraph;
 | 
					use tui::widgets::Paragraph;
 | 
				
			||||||
use tui::{Frame, Terminal};
 | 
					use tui::{Frame, Terminal};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_battle_backend::data::{Coordinates, CurrentGameMapStatus, CurrentGameStatus};
 | 
				
			||||||
 | 
					use sea_battle_backend::human_player_ws::{ClientMessage, ServerMessage};
 | 
				
			||||||
 | 
					use sea_battle_backend::utils::Res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::client::Client;
 | 
					use crate::client::Client;
 | 
				
			||||||
use crate::constants::*;
 | 
					use crate::constants::*;
 | 
				
			||||||
use crate::ui_screens::confirm_dialog::confirm;
 | 
					use crate::ui_screens::confirm_dialog_screen::confirm;
 | 
				
			||||||
use crate::ui_screens::popup_screen::PopupScreen;
 | 
					use crate::ui_screens::popup_screen::PopupScreen;
 | 
				
			||||||
use crate::ui_screens::set_boats_layout::SetBoatsLayoutScreen;
 | 
					use crate::ui_screens::set_boats_layout_screen::SetBoatsLayoutScreen;
 | 
				
			||||||
use crate::ui_screens::utils::{centered_rect_size, centered_text};
 | 
					use crate::ui_screens::utils::{centered_rect_size, centered_text};
 | 
				
			||||||
use crate::ui_screens::ScreenResult;
 | 
					use crate::ui_screens::ScreenResult;
 | 
				
			||||||
use crate::ui_widgets::game_map_widget::{ColoredCells, GameMapWidget};
 | 
					use crate::ui_widgets::game_map_widget::{ColoredCells, GameMapWidget};
 | 
				
			||||||
@@ -54,7 +55,8 @@ pub struct GameScreen {
 | 
				
			|||||||
    client: Client,
 | 
					    client: Client,
 | 
				
			||||||
    status: GameStatus,
 | 
					    status: GameStatus,
 | 
				
			||||||
    opponent_name: Option<String>,
 | 
					    opponent_name: Option<String>,
 | 
				
			||||||
    game_status: CurrentGameStatus,
 | 
					    game: CurrentGameStatus,
 | 
				
			||||||
 | 
					    curr_shoot_position: Coordinates,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl GameScreen {
 | 
					impl GameScreen {
 | 
				
			||||||
@@ -63,7 +65,8 @@ impl GameScreen {
 | 
				
			|||||||
            client,
 | 
					            client,
 | 
				
			||||||
            status: GameStatus::Pending,
 | 
					            status: GameStatus::Pending,
 | 
				
			||||||
            opponent_name: None,
 | 
					            opponent_name: None,
 | 
				
			||||||
            game_status: Default::default(),
 | 
					            game: Default::default(),
 | 
				
			||||||
 | 
					            curr_shoot_position: Coordinates::new(0, 0),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -80,6 +83,8 @@ impl GameScreen {
 | 
				
			|||||||
            // Handle terminal events
 | 
					            // Handle terminal events
 | 
				
			||||||
            if crossterm::event::poll(timeout)? {
 | 
					            if crossterm::event::poll(timeout)? {
 | 
				
			||||||
                if let Event::Key(key) = event::read()? {
 | 
					                if let Event::Key(key) = event::read()? {
 | 
				
			||||||
 | 
					                    let mut new_shoot_pos = self.curr_shoot_position;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    match key.code {
 | 
					                    match key.code {
 | 
				
			||||||
                        // Leave game
 | 
					                        // Leave game
 | 
				
			||||||
                        KeyCode::Char('q')
 | 
					                        KeyCode::Char('q')
 | 
				
			||||||
@@ -87,8 +92,28 @@ impl GameScreen {
 | 
				
			|||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            return Ok(ScreenResult::Canceled);
 | 
					                            return Ok(ScreenResult::Canceled);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // Move  shoot cursor
 | 
				
			||||||
 | 
					                        KeyCode::Left if self.can_fire() => new_shoot_pos = new_shoot_pos.add_x(-1),
 | 
				
			||||||
 | 
					                        KeyCode::Right if self.can_fire() => new_shoot_pos = new_shoot_pos.add_x(1),
 | 
				
			||||||
 | 
					                        KeyCode::Up if self.can_fire() => new_shoot_pos = new_shoot_pos.add_y(-1),
 | 
				
			||||||
 | 
					                        KeyCode::Down if self.can_fire() => new_shoot_pos = new_shoot_pos.add_y(1),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // 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?;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        _ => {}
 | 
					                        _ => {}
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if new_shoot_pos.is_valid(&self.game.rules) {
 | 
				
			||||||
 | 
					                        self.curr_shoot_position = new_shoot_pos;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -137,12 +162,12 @@ impl GameScreen {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    ServerMessage::OpponentMustFire { status } => {
 | 
					                    ServerMessage::OpponentMustFire { status } => {
 | 
				
			||||||
                        self.status = GameStatus::OpponentMustFire;
 | 
					                        self.status = GameStatus::OpponentMustFire;
 | 
				
			||||||
                        self.game_status = status;
 | 
					                        self.game = status;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    ServerMessage::RequestFire { status } => {
 | 
					                    ServerMessage::RequestFire { status } => {
 | 
				
			||||||
                        self.status = GameStatus::MustFire;
 | 
					                        self.status = GameStatus::MustFire;
 | 
				
			||||||
                        self.game_status = status;
 | 
					                        self.game = status;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    ServerMessage::FireResult { .. } => {}
 | 
					                    ServerMessage::FireResult { .. } => {}
 | 
				
			||||||
@@ -172,7 +197,20 @@ impl GameScreen {
 | 
				
			|||||||
        self.opponent_name.as_deref().unwrap_or("opponent")
 | 
					        self.opponent_name.as_deref().unwrap_or("opponent")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn player_map(&self, map: &CurrentGameMapStatus) -> GameMapWidget {
 | 
					    fn player_map(&self, map: &CurrentGameMapStatus, opponent_map: bool) -> GameMapWidget {
 | 
				
			||||||
 | 
					        let mut map_widget = GameMapWidget::new(&self.game.rules);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Current shoot position
 | 
				
			||||||
 | 
					        if opponent_map {
 | 
				
			||||||
 | 
					            map_widget = map_widget.add_colored_cells(ColoredCells {
 | 
				
			||||||
 | 
					                color: match self.game.can_fire_at_location(self.curr_shoot_position) {
 | 
				
			||||||
 | 
					                    true => Color::Green,
 | 
				
			||||||
 | 
					                    false => Color::LightYellow,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                cells: vec![self.curr_shoot_position],
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Sunk boats
 | 
					        // Sunk boats
 | 
				
			||||||
        let sunk_boats = ColoredCells {
 | 
					        let sunk_boats = ColoredCells {
 | 
				
			||||||
            color: Color::Red,
 | 
					            color: Color::Red,
 | 
				
			||||||
@@ -206,7 +244,7 @@ impl GameScreen {
 | 
				
			|||||||
                .collect::<Vec<_>>(),
 | 
					                .collect::<Vec<_>>(),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        GameMapWidget::new(&self.game_status.rules)
 | 
					        map_widget
 | 
				
			||||||
            .add_colored_cells(sunk_boats)
 | 
					            .add_colored_cells(sunk_boats)
 | 
				
			||||||
            .add_colored_cells(touched_areas)
 | 
					            .add_colored_cells(touched_areas)
 | 
				
			||||||
            .add_colored_cells(failed_strikes)
 | 
					            .add_colored_cells(failed_strikes)
 | 
				
			||||||
@@ -227,16 +265,16 @@ impl GameScreen {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Draw main ui (default play UI)
 | 
					        // Draw main ui (default play UI)
 | 
				
			||||||
        let player_map = self
 | 
					        let player_map = self
 | 
				
			||||||
            .player_map(&self.game_status.your_map)
 | 
					            .player_map(&self.game.your_map, false)
 | 
				
			||||||
            .set_title("YOUR map");
 | 
					            .set_title("YOUR map");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut opponent_map = self
 | 
					        let mut opponent_map = self
 | 
				
			||||||
            .player_map(&self.game_status.opponent_map)
 | 
					            .player_map(&self.game.opponent_map, true)
 | 
				
			||||||
            .set_title(self.opponent_name());
 | 
					            .set_title(self.opponent_name());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.can_fire() {
 | 
					        if self.can_fire() {
 | 
				
			||||||
            opponent_map = opponent_map
 | 
					            opponent_map = opponent_map
 | 
				
			||||||
                .set_legend("Use arrows + enter\nor click on the place\nwhere you want\nto shoot");
 | 
					                .set_legend("Use arrows + Enter\nor click on the place\nwhere you want\nto shoot");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Show both maps if there is enough room on the screen
 | 
					        // Show both maps if there is enough room on the screen
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,13 @@
 | 
				
			|||||||
use std::fmt::Debug;
 | 
					use std::fmt::Debug;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod configure_game_rules;
 | 
					pub mod configure_game_rules;
 | 
				
			||||||
pub mod confirm_dialog;
 | 
					pub mod confirm_dialog_screen;
 | 
				
			||||||
pub mod game_screen;
 | 
					pub mod game_screen;
 | 
				
			||||||
pub mod input_screen;
 | 
					pub mod input_screen;
 | 
				
			||||||
pub mod popup_screen;
 | 
					pub mod popup_screen;
 | 
				
			||||||
pub mod select_bot_type;
 | 
					pub mod select_bot_type_screen;
 | 
				
			||||||
pub mod select_play_mode;
 | 
					pub mod select_play_mode_screen;
 | 
				
			||||||
pub mod set_boats_layout;
 | 
					pub mod set_boats_layout_screen;
 | 
				
			||||||
pub mod utils;
 | 
					pub mod utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ use tui::{Frame, Terminal};
 | 
				
			|||||||
use sea_battle_backend::data::*;
 | 
					use sea_battle_backend::data::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::constants::*;
 | 
					use crate::constants::*;
 | 
				
			||||||
use crate::ui_screens::confirm_dialog::confirm;
 | 
					use crate::ui_screens::confirm_dialog_screen::confirm;
 | 
				
			||||||
use crate::ui_screens::utils::{centered_rect_size, centered_text};
 | 
					use crate::ui_screens::utils::{centered_rect_size, centered_text};
 | 
				
			||||||
use crate::ui_screens::ScreenResult;
 | 
					use crate::ui_screens::ScreenResult;
 | 
				
			||||||
use crate::ui_widgets::game_map_widget::{ColoredCells, GameMapWidget};
 | 
					use crate::ui_widgets::game_map_widget::{ColoredCells, GameMapWidget};
 | 
				
			||||||
		Reference in New Issue
	
	Block a user