use bevy::{ app::AppExit, prelude::*, }; use bevy_mod_picking::*; use crate::pieces::*; pub struct Square { pub x: u8, pub y: u8, } impl Square { fn is_white(&self) -> bool { (self.x + self.y + 1) % 2 == 0 } } struct PlayerTurn(PieceColor); impl Default for PlayerTurn { fn default() -> Self { Self(PieceColor::White) } } #[derive(Default)] struct SelectedSquare { entity: Option, } #[derive(Default)] struct SelectedPiece { entity: Option, } pub struct BoardPlugin; impl Plugin for BoardPlugin { fn build(&self, app: &mut AppBuilder) { app.init_resource::() .init_resource::() .init_resource::() .add_startup_system(create_board.system()) .add_system(select_square.system()); } } fn create_board( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, mut highlight_colors: ResMut, ) { // add meshes and materials let mesh = meshes.add(Mesh::from(shape::Plane {size: 1.0})); for i in 0..8 { for j in 0..8 { commands .spawn_bundle(PbrBundle { mesh: mesh.clone(), material: if (i + j + 1) % 2 == 0 { materials.add(Color::rgb(1.0, 0.9, 0.9).into()) } else { materials.add(Color::rgb(0.0, 0.1, 0.1).into()) }, transform: Transform::from_translation(Vec3::new(i as f32, 0.0, j as f32)), ..Default::default() }) .insert_bundle(PickableBundle::default()) .insert(Square { x: i, y: j, }); } } highlight_colors.hovered = materials.add(Color::rgb(0.8, 0.3, 0.3).into()); highlight_colors.pressed = materials.add(Color::rgb(0.9, 0.5, 0.5).into()); highlight_colors.selected = materials.add(Color::rgb(0.9, 0.1, 0.1).into()); } fn select_square( mut commands: Commands, mouse_button_inputs: Res>, mut selected_square: ResMut, mut selected_piece: ResMut, mut turn: ResMut, mut app_exit_events: EventWriter, camera_query: Query<&PickingCamera>, squares_query: Query<&Square>, mut pieces_query: Query<(Entity, &mut Piece, &Children)>, ) { if !mouse_button_inputs.just_pressed(MouseButton::Left) { return; } for camera in camera_query.iter() { if let Some((square_entity, _intersection)) = camera.intersect_top() { let pieces_entity_vec: Vec<(Entity, Piece, Vec)> = pieces_query .iter_mut() .map(|(entity, piece, children)| { ( entity, *piece, children.iter().map(|entity| *entity).collect() ) }) .collect(); let pieces_vec = pieces_query .iter_mut() .map(|(_, piece, _)| *piece) .collect(); if let Ok(square) = squares_query.get(square_entity) { selected_square.entity = Some(square_entity); // if a piece is already selected, set it to move if let Some(selected_piece_entity) = selected_piece.entity { if let Ok((_piece_entity, mut piece, _)) = pieces_query.get_mut(selected_piece_entity) { if piece.is_move_valid((square.x, square.y), &pieces_vec) { // check to see if we're capturing for (other_entity, other_piece, other_children) in pieces_entity_vec { if other_piece.x == square.x && other_piece.y == square.y && other_piece.color != piece.color { // if the king is taken, exit if other_piece.piece_type == PieceType::King { println!( "{} won! Thanks for playing!", match turn.0 { PieceColor::White => "White", PieceColor::Black => "Black", } ); app_exit_events.send(AppExit); } // despawn the piece and its children commands.entity(other_entity).despawn(); for child in other_children { commands.entity(child).despawn(); } } } // and set it to move piece.x = square.x; piece.y = square.y; turn.0 = match turn.0 { PieceColor::White => PieceColor::Black, PieceColor::Black => PieceColor::White, } } } selected_square.entity = None; selected_piece.entity = None; } else { // otherwise, select the piece (if one) in the selected square for (piece_entity, piece, _) in pieces_query.iter_mut() { if piece.x == square.x && piece.y == square.y && piece.color == turn.0 { selected_piece.entity = Some(piece_entity); break; } } } } } else { // clicked on nothing, deselect selected_square.entity = None; selected_piece.entity = None; } } }