Start to build game grid
This commit is contained in:
		@@ -18,7 +18,8 @@ use sea_battle_backend::data::GameRules;
 | 
			
		||||
 | 
			
		||||
async fn run_app<B: Backend>(terminal: &mut Terminal<B>) -> Result<(), Box<dyn Error>> {
 | 
			
		||||
    // Temporary code
 | 
			
		||||
    let res = configure_game_rules::configure_play_rules(GameRules::default(), terminal)?; // select_bot_type::select_bot_type(terminal)?;
 | 
			
		||||
    // let res = configure_game_rules::configure_play_rules(GameRules::default(), terminal)?; // select_bot_type::select_bot_type(terminal)?;
 | 
			
		||||
    let res = set_boats_layout::set_boat_layout(&GameRules::default(), terminal)?; // select_bot_type::select_bot_type(terminal)?;
 | 
			
		||||
    Err(io::Error::new(
 | 
			
		||||
        ErrorKind::Other,
 | 
			
		||||
        format!("result: {:?}", res),
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
pub mod configure_game_rules;
 | 
			
		||||
pub mod select_bot_type;
 | 
			
		||||
pub mod select_play_mode;
 | 
			
		||||
pub mod set_boats_layout;
 | 
			
		||||
pub mod utils;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										75
									
								
								rust/cli_player/src/ui_screens/set_boats_layout.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								rust/cli_player/src/ui_screens/set_boats_layout.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
use std::io;
 | 
			
		||||
use std::time::{Duration, Instant};
 | 
			
		||||
 | 
			
		||||
use crossterm::event;
 | 
			
		||||
use crossterm::event::{Event, KeyCode};
 | 
			
		||||
use tui::backend::Backend;
 | 
			
		||||
use tui::style::*;
 | 
			
		||||
use tui::text::*;
 | 
			
		||||
use tui::widgets::*;
 | 
			
		||||
use tui::{Frame, Terminal};
 | 
			
		||||
 | 
			
		||||
use sea_battle_backend::data::*;
 | 
			
		||||
 | 
			
		||||
use crate::constants::*;
 | 
			
		||||
use crate::ui_screens::utils::centered_rect_size;
 | 
			
		||||
use crate::ui_screens::ScreenResult;
 | 
			
		||||
use crate::ui_widgets::game_map_widget::GameMapWidget;
 | 
			
		||||
 | 
			
		||||
struct SetBotsLayoutScreen {
 | 
			
		||||
    curr_boat: usize,
 | 
			
		||||
    layout: BoatsLayout,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn set_boat_layout<B: Backend>(
 | 
			
		||||
    rules: &GameRules,
 | 
			
		||||
    terminal: &mut Terminal<B>,
 | 
			
		||||
) -> io::Result<ScreenResult<BoatsLayout>> {
 | 
			
		||||
    let mut model = SetBotsLayoutScreen {
 | 
			
		||||
        curr_boat: 0,
 | 
			
		||||
        layout: BoatsLayout::gen_random_for_rules(rules)
 | 
			
		||||
            .expect("Failed to generate initial boats layout"),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let mut last_tick = Instant::now();
 | 
			
		||||
    loop {
 | 
			
		||||
        terminal.draw(|f| ui(f, &mut model, rules))?;
 | 
			
		||||
 | 
			
		||||
        let timeout = TICK_RATE
 | 
			
		||||
            .checked_sub(last_tick.elapsed())
 | 
			
		||||
            .unwrap_or_else(|| Duration::from_secs(0));
 | 
			
		||||
 | 
			
		||||
        if event::poll(timeout)? {
 | 
			
		||||
            if let Event::Key(key) = event::read()? {
 | 
			
		||||
                match key.code {
 | 
			
		||||
                    KeyCode::Char('q') => return Ok(ScreenResult::Canceled),
 | 
			
		||||
                    KeyCode::Enter => {
 | 
			
		||||
                        if model.layout.is_valid(rules) {
 | 
			
		||||
                            return Ok(ScreenResult::Ok(model.layout));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    KeyCode::Down => model.curr_boat -= 1,
 | 
			
		||||
                    KeyCode::Up => model.curr_boat += model.layout.number_of_boats() - 1,
 | 
			
		||||
                    _ => {}
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                model.curr_boat %= model.layout.number_of_boats();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if last_tick.elapsed() >= TICK_RATE {
 | 
			
		||||
            last_tick = Instant::now();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn ui<B: Backend>(f: &mut Frame<B>, model: &mut SetBotsLayoutScreen, rules: &GameRules) {
 | 
			
		||||
    let area = centered_rect_size(
 | 
			
		||||
        rules.map_width as u16 + 10,
 | 
			
		||||
        rules.map_height as u16 + 10,
 | 
			
		||||
        f.size(),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let game_map_widget = GameMapWidget::new(rules);
 | 
			
		||||
 | 
			
		||||
    f.render_widget(game_map_widget, area);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								rust/cli_player/src/ui_widgets/game_map_widget.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								rust/cli_player/src/ui_widgets/game_map_widget.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
use sea_battle_backend::data::{GameRules, PlayConfiguration};
 | 
			
		||||
use tui::buffer::Buffer;
 | 
			
		||||
use tui::layout::Rect;
 | 
			
		||||
use tui::widgets::{BorderType, Widget};
 | 
			
		||||
 | 
			
		||||
pub struct GameMapWidget<'a> {
 | 
			
		||||
    rules: &'a GameRules,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> GameMapWidget<'a> {
 | 
			
		||||
    pub fn new(rules: &'a GameRules) -> Self {
 | 
			
		||||
        Self { rules }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'a> Widget for GameMapWidget<'a> {
 | 
			
		||||
    fn render(self, area: Rect, buf: &mut Buffer) {
 | 
			
		||||
        let alphabet = PlayConfiguration::default().ordinate_alphabet;
 | 
			
		||||
 | 
			
		||||
        let symbols = BorderType::line_symbols(BorderType::Plain);
 | 
			
		||||
 | 
			
		||||
        // Paint game grid
 | 
			
		||||
        for y in 0..(self.rules.map_height + 1) {
 | 
			
		||||
            for x in 0..(self.rules.map_width + 1) {
 | 
			
		||||
                let o_x = x as u16 * 2;
 | 
			
		||||
                let o_y = y as u16 * 2;
 | 
			
		||||
                buf.get_mut(o_x, o_y).set_symbol(symbols.cross);
 | 
			
		||||
                buf.get_mut(o_x + 1, o_y).set_symbol(symbols.horizontal);
 | 
			
		||||
                buf.get_mut(o_x, o_y + 1).set_symbol(symbols.vertical);
 | 
			
		||||
                buf.get_mut(o_x + 1, o_y + 1).set_char('.');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
pub mod button_widget;
 | 
			
		||||
pub mod checkbox_widget;
 | 
			
		||||
pub mod game_map_widget;
 | 
			
		||||
pub mod text_editor_widget;
 | 
			
		||||
 
 | 
			
		||||
@@ -172,7 +172,7 @@ impl BoatPosition {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Default)]
 | 
			
		||||
pub struct BoatsLayout(Vec<BoatPosition>);
 | 
			
		||||
pub struct BoatsLayout(pub Vec<BoatPosition>);
 | 
			
		||||
 | 
			
		||||
impl BoatsLayout {
 | 
			
		||||
    /// Generate a new invalid (empty) boats layout
 | 
			
		||||
@@ -331,6 +331,10 @@ impl BoatsLayout {
 | 
			
		||||
        errors
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn is_valid(&self, rules: &GameRules) -> bool {
 | 
			
		||||
        self.errors(rules).is_empty()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn find_boat_at_position(&self, pos: Coordinates) -> Option<&BoatPosition> {
 | 
			
		||||
        self.0.iter().find(|f| f.all_coordinates().contains(&pos))
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user