Implement board display
This commit is contained in:
		
							parent
							
								
									7e397c3c56
								
							
						
					
					
						commit
						15f4124855
					
				
					 3 changed files with 270 additions and 3 deletions
				
			
		|  | @ -97,7 +97,7 @@ impl Board { | ||||||
|         for (i, p) in ps[0..18].iter().enumerate() { |         for (i, p) in ps[0..18].iter().enumerate() { | ||||||
|             if i % 2 == 0 { |             if i % 2 == 0 { | ||||||
|                 //is a port
 |                 //is a port
 | ||||||
|                 if i % 3 != 2 { |                 if i % 3 != 1 { | ||||||
|                     orientation.rotate(); |                     orientation.rotate(); | ||||||
|                 } |                 } | ||||||
|                 hexes.push(Hex { |                 hexes.push(Hex { | ||||||
|  |  | ||||||
							
								
								
									
										234
									
								
								src/display.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								src/display.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,234 @@ | ||||||
|  | use crate::logic::{Board, Position}; | ||||||
|  | use ratatui::buffer::Buffer; | ||||||
|  | use ratatui::prelude::*; | ||||||
|  | 
 | ||||||
|  | pub struct BoardView { | ||||||
|  |     buffer: Box<Buffer>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl BoardView { | ||||||
|  |     pub fn new(board: Box<Board>) -> BoardView { | ||||||
|  |         let buffer = Box::new(board.draw()); | ||||||
|  |         BoardView { buffer } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ratatui::widgets::Widget for BoardView { | ||||||
|  |     fn render(self, area: ratatui::layout::Rect, buf: &mut Buffer) { | ||||||
|  |         buf.merge(&self.buffer); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Board { | ||||||
|  |     fn draw(&self) -> Buffer { | ||||||
|  |         let mut b = Buffer::empty(Rect { | ||||||
|  |             x: 0, | ||||||
|  |             y: 0, | ||||||
|  |             width: 49, | ||||||
|  |             height: 28, | ||||||
|  |         }); | ||||||
|  |         for i in 0..self.hexes.len() { | ||||||
|  |             for j in 0..self.hexes[i].len() { | ||||||
|  |                 if i + j < 3 || i + j > 9 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 b.merge(&self.draw_hex(&Position(i as i32, j as i32))); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         b | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn draw_hex(&self, p: &Position) -> Buffer { | ||||||
|  |         let mut b = Buffer::empty(Rect { | ||||||
|  |             x: 0, | ||||||
|  |             y: 0, | ||||||
|  |             width: 7, | ||||||
|  |             height: 5, | ||||||
|  |         }); | ||||||
|  |         let get_edge = |x, y| { | ||||||
|  |             let p = p.edge(&Position(x, y)); | ||||||
|  |             self.edges[p.0 as usize][p.1 as usize] | ||||||
|  |         }; | ||||||
|  |         let get_vertex = |x, y| { | ||||||
|  |             let p = p.vertex(&Position(x, y)); | ||||||
|  |             self.vertices[p.0 as usize][p.1 as usize] | ||||||
|  |         }; | ||||||
|  |         let hex = self.hexes[p.0 as usize][p.1 as usize]; | ||||||
|  |         let edge_NW = get_edge(0, -1); | ||||||
|  |         let edge_SW = get_edge(1, -1); | ||||||
|  |         let edge_S = get_edge(1, 0); | ||||||
|  |         let vertex_SW = get_vertex(1, -1); | ||||||
|  |         let vertex_SE = get_vertex(1, 0); | ||||||
|  |         b.get_mut(0, 0).set_symbol(" "); | ||||||
|  |         draw_edge(&mut b, edge_NW, "⧸", &[(1, 0), (0, 1)]); | ||||||
|  |         draw_edge(&mut b, edge_SW, "⧹", &[(0, 2), (1, 3)]); | ||||||
|  |         draw_edge( | ||||||
|  |             &mut b, | ||||||
|  |             edge_S, | ||||||
|  |             "_", | ||||||
|  |             &[(2, 3), (3, 3), (4, 3), (5, 3), (6, 3)], | ||||||
|  |         ); | ||||||
|  |         draw_vertex(&mut b, vertex_SW, (2, 3)); | ||||||
|  |         draw_vertex(&mut b, vertex_SE, (6, 3)); | ||||||
|  |         match hex { | ||||||
|  |             None => (), | ||||||
|  |             Some(h) => { | ||||||
|  |                 if self.robber.0 == p.0 && self.robber.1 == p.1 { | ||||||
|  |                     b.get_mut(4, 3).set_symbol(""); | ||||||
|  |                 } | ||||||
|  |                 match h.hextype { | ||||||
|  |                     crate::logic::HexType::Desert => (), | ||||||
|  |                     crate::logic::HexType::Port => { | ||||||
|  |                         if h.resource.is_some() { | ||||||
|  |                             draw_resource(&mut b, h.resource.unwrap(), (4, 1)); | ||||||
|  |                         } else { | ||||||
|  |                             b.get_mut(4, 1).set_symbol("?"); | ||||||
|  |                         } | ||||||
|  |                         draw_ports(&mut b, h.orientation.unwrap()); | ||||||
|  |                     } | ||||||
|  |                     crate::logic::HexType::Ocean => (), | ||||||
|  |                     crate::logic::HexType::Resource => { | ||||||
|  |                         draw_resource(&mut b, h.resource.unwrap(), (4, 0)); | ||||||
|  |                         match h.number { | ||||||
|  |                             None => (), | ||||||
|  |                             Some(n) => { | ||||||
|  |                                 draw_number(&mut b, n as u8); | ||||||
|  |                             } | ||||||
|  |                         }; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         b.resize(Rect { | ||||||
|  |             x: (p.1 * 7) as u16, | ||||||
|  |             y: (p.0 * 4 + p.1 * 2) as u16, | ||||||
|  |             width: 7, | ||||||
|  |             height: 5, | ||||||
|  |         }); | ||||||
|  |         b | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn draw_edge(b: &mut Buffer, edge: Option<crate::logic::Edge>, symbol: &str, ps: &[(u16, u16)]) { | ||||||
|  |     match edge { | ||||||
|  |         None => (), | ||||||
|  |         Some(edge) => { | ||||||
|  |             for &(x, y) in ps { | ||||||
|  |                 b.get_mut(x, y) | ||||||
|  |                     .set_symbol(symbol) | ||||||
|  |                     .set_style(Style::default().bold()); | ||||||
|  |             } | ||||||
|  |             match edge.road { | ||||||
|  |                 None => (), | ||||||
|  |                 Some(road) => { | ||||||
|  |                     for &(x, y) in ps { | ||||||
|  |                         b.get_mut(x, y).set_fg(color_convert(road.0)); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn draw_vertex(b: &mut Buffer, vertex: Option<crate::logic::Vertex>, p: (u16, u16)) { | ||||||
|  |     match vertex { | ||||||
|  |         None => (), | ||||||
|  |         Some(vertex) => { | ||||||
|  |             if vertex.settlement.is_some() { | ||||||
|  |                 b.get_mut(p.0, p.1) | ||||||
|  |                     .set_symbol("") | ||||||
|  |                     .set_fg(color_convert(vertex.settlement.unwrap().0)); | ||||||
|  |             } else if vertex.city.is_some() { | ||||||
|  |                 b.get_mut(p.0, p.1) | ||||||
|  |                     .set_symbol("") | ||||||
|  |                     .set_fg(color_convert(vertex.city.unwrap().0)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn draw_resource(b: &mut Buffer, resource: crate::logic::Resource, p: (u16, u16)) { | ||||||
|  |     let (bg, fg, symbol) = match resource { | ||||||
|  |         crate::logic::Resource::Brick => (Color::Red, Color::Black, ""), | ||||||
|  |         crate::logic::Resource::Ore => (Color::Blue, Color::Black, ""), | ||||||
|  |         crate::logic::Resource::Sheep => (Color::Gray, Color::Black, ""), | ||||||
|  |         crate::logic::Resource::Wheat => (Color::Yellow, Color::Black, ""), | ||||||
|  |         crate::logic::Resource::Wood => (Color::Green, Color::Black, ""), | ||||||
|  |     }; | ||||||
|  |     b.get_mut(p.0, p.1).set_bg(bg).set_fg(fg).set_symbol(symbol); | ||||||
|  |     // .set_style(Style::default().bold());
 | ||||||
|  |     b.get_mut(p.0 - 1, p.1).set_bg(bg); | ||||||
|  |     b.get_mut(p.0 + 1, p.1).set_bg(bg); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn draw_ports(b: &mut Buffer, orientation: Position) { | ||||||
|  |     match orientation { | ||||||
|  |         Position(1, 0) => { | ||||||
|  |             b.get_mut(3, 2).set_symbol(""); | ||||||
|  |             b.get_mut(5, 2).set_symbol(""); | ||||||
|  |         } | ||||||
|  |         Position(0, 1) => { | ||||||
|  |             b.get_mut(5, 2).set_symbol(""); | ||||||
|  |             b.get_mut(6, 1).set_symbol(""); | ||||||
|  |         } | ||||||
|  |         Position(-1, 1) => { | ||||||
|  |             b.get_mut(6, 1).set_symbol(""); | ||||||
|  |             b.get_mut(5, 0).set_symbol(""); | ||||||
|  |         } | ||||||
|  |         Position(-1, 0) => { | ||||||
|  |             b.get_mut(5, 0).set_symbol(""); | ||||||
|  |             b.get_mut(3, 0).set_symbol(""); | ||||||
|  |         } | ||||||
|  |         Position(0, -1) => { | ||||||
|  |             b.get_mut(3, 0).set_symbol(""); | ||||||
|  |             b.get_mut(2, 1).set_symbol(""); | ||||||
|  |         } | ||||||
|  |         Position(1, -1) => { | ||||||
|  |             b.get_mut(2, 1).set_symbol(""); | ||||||
|  |             b.get_mut(3, 2).set_symbol(""); | ||||||
|  |         } | ||||||
|  |         _ => (), | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn draw_number(b: &mut Buffer, number: u8) { | ||||||
|  |     let style = if number == 6 || number == 8 { | ||||||
|  |         Style::default().fg(Color::Red) | ||||||
|  |     } else { | ||||||
|  |         Style::default() | ||||||
|  |     }; | ||||||
|  |     b.set_string(3, 1, &format!("{number:>2}"), style); | ||||||
|  | 
 | ||||||
|  |     match number { | ||||||
|  |         2 | 12 => { | ||||||
|  |             b.get_mut(4, 2).set_symbol("⠈").set_style(style); | ||||||
|  |         } | ||||||
|  |         3 | 11 => { | ||||||
|  |             b.get_mut(4, 2).set_symbol("⠉").set_style(style); | ||||||
|  |         } | ||||||
|  |         4 | 10 => { | ||||||
|  |             b.get_mut(3, 2).set_symbol("⠈").set_style(style); | ||||||
|  |             b.get_mut(4, 2).set_symbol("⠉").set_style(style); | ||||||
|  |         } | ||||||
|  |         5 | 9 => { | ||||||
|  |             b.get_mut(3, 2).set_symbol("⠈").set_style(style); | ||||||
|  |             b.get_mut(4, 2).set_symbol("⠉").set_style(style); | ||||||
|  |             b.get_mut(5, 2).set_symbol("⠁").set_style(style); | ||||||
|  |         } | ||||||
|  |         6 | 8 => { | ||||||
|  |             b.get_mut(3, 2).set_symbol("⠉").set_style(style); | ||||||
|  |             b.get_mut(4, 2).set_symbol("⠉").set_style(style); | ||||||
|  |             b.get_mut(5, 2).set_symbol("⠁").set_style(style); | ||||||
|  |         } | ||||||
|  |         _ => (), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn color_convert(c: crate::logic::Color) -> Color { | ||||||
|  |     match c { | ||||||
|  |         crate::logic::Color::Red => Color::LightRed, | ||||||
|  |         crate::logic::Color::Green => Color::LightGreen, | ||||||
|  |         crate::logic::Color::Yellow => Color::LightYellow, | ||||||
|  |         crate::logic::Color::Blue => Color::LightBlue, | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										37
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -1,10 +1,43 @@ | ||||||
| mod board; | mod board; | ||||||
|  | mod display; | ||||||
| mod logic; | mod logic; | ||||||
|  | use crossterm::{ | ||||||
|  |     event::{self, KeyCode, KeyEventKind}, | ||||||
|  |     terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, | ||||||
|  |     ExecutableCommand, | ||||||
|  | }; | ||||||
|  | use logic::Board; | ||||||
|  | use ratatui::prelude::{CrosstermBackend, Terminal}; | ||||||
|  | use std::io::{stdout, Result}; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| * Three Ore Two Wheat | * Three Ore Two Wheat | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| fn main() { | fn main() -> Result<()> { | ||||||
|     println!("Hello, world!"); |     stdout().execute(EnterAlternateScreen)?; | ||||||
|  |     enable_raw_mode()?; | ||||||
|  |     let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; | ||||||
|  |     terminal.clear()?; | ||||||
|  | 
 | ||||||
|  |     let board = Box::new(Board::new("example_seed")); | ||||||
|  |     let hex = display::BoardView::new(board); | ||||||
|  | 
 | ||||||
|  |     terminal.draw(|frame| { | ||||||
|  |         frame.render_widget(hex, frame.size()); | ||||||
|  |     })?; | ||||||
|  | 
 | ||||||
|  |     loop { | ||||||
|  |         if event::poll(std::time::Duration::from_millis(16))? { | ||||||
|  |             if let event::Event::Key(key) = event::read()? { | ||||||
|  |                 if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     stdout().execute(LeaveAlternateScreen)?; | ||||||
|  |     disable_raw_mode()?; | ||||||
|  |     Ok(()) | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 danial23
						danial23