Can fire with mouse

This commit is contained in:
Pierre HUBERT 2022-10-15 16:06:47 +02:00
parent acd13af227
commit 3455559d33

View File

@ -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
}
}