board.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. use bevy::{
  2. app::AppExit,
  3. prelude::*,
  4. };
  5. use bevy_mod_picking::*;
  6. use crate::pieces::*;
  7. pub struct Square {
  8. pub x: u8,
  9. pub y: u8,
  10. }
  11. impl Square {
  12. fn is_white(&self) -> bool {
  13. (self.x + self.y + 1) % 2 == 0
  14. }
  15. }
  16. struct PlayerTurn(PieceColor);
  17. impl Default for PlayerTurn {
  18. fn default() -> Self {
  19. Self(PieceColor::White)
  20. }
  21. }
  22. #[derive(Default)]
  23. struct SelectedSquare {
  24. entity: Option<Entity>,
  25. }
  26. #[derive(Default)]
  27. struct SelectedPiece {
  28. entity: Option<Entity>,
  29. }
  30. pub struct BoardPlugin;
  31. impl Plugin for BoardPlugin {
  32. fn build(&self, app: &mut AppBuilder) {
  33. app.init_resource::<SelectedSquare>()
  34. .init_resource::<SelectedPiece>()
  35. .init_resource::<PlayerTurn>()
  36. .add_startup_system(create_board.system())
  37. .add_system(select_square.system());
  38. }
  39. }
  40. fn create_board(
  41. mut commands: Commands,
  42. mut meshes: ResMut<Assets<Mesh>>,
  43. mut materials: ResMut<Assets<StandardMaterial>>,
  44. mut highlight_colors: ResMut<MeshButtonMaterials>,
  45. ) {
  46. // add meshes and materials
  47. let mesh = meshes.add(Mesh::from(shape::Plane {size: 1.0}));
  48. for i in 0..8 {
  49. for j in 0..8 {
  50. commands
  51. .spawn_bundle(PbrBundle {
  52. mesh: mesh.clone(),
  53. material: if (i + j + 1) % 2 == 0 {
  54. materials.add(Color::rgb(1.0, 0.9, 0.9).into())
  55. } else {
  56. materials.add(Color::rgb(0.0, 0.1, 0.1).into())
  57. },
  58. transform: Transform::from_translation(Vec3::new(i as f32, 0.0, j as f32)),
  59. ..Default::default()
  60. })
  61. .insert_bundle(PickableBundle::default())
  62. .insert(Square {
  63. x: i,
  64. y: j,
  65. });
  66. }
  67. }
  68. highlight_colors.hovered = materials.add(Color::rgb(0.8, 0.3, 0.3).into());
  69. highlight_colors.pressed = materials.add(Color::rgb(0.9, 0.5, 0.5).into());
  70. highlight_colors.selected = materials.add(Color::rgb(0.9, 0.1, 0.1).into());
  71. }
  72. fn select_square(
  73. mut commands: Commands,
  74. mouse_button_inputs: Res<Input<MouseButton>>,
  75. mut selected_square: ResMut<SelectedSquare>,
  76. mut selected_piece: ResMut<SelectedPiece>,
  77. mut turn: ResMut<PlayerTurn>,
  78. mut app_exit_events: EventWriter<AppExit>,
  79. camera_query: Query<&PickingCamera>,
  80. squares_query: Query<&Square>,
  81. mut pieces_query: Query<(Entity, &mut Piece, &Children)>,
  82. ) {
  83. if !mouse_button_inputs.just_pressed(MouseButton::Left) {
  84. return;
  85. }
  86. for camera in camera_query.iter() {
  87. if let Some((square_entity, _intersection)) = camera.intersect_top() {
  88. let pieces_entity_vec: Vec<(Entity, Piece, Vec<Entity>)> = pieces_query
  89. .iter_mut()
  90. .map(|(entity, piece, children)| {
  91. (
  92. entity,
  93. *piece,
  94. children.iter().map(|entity| *entity).collect()
  95. )
  96. })
  97. .collect();
  98. let pieces_vec = pieces_query
  99. .iter_mut()
  100. .map(|(_, piece, _)| *piece)
  101. .collect();
  102. if let Ok(square) = squares_query.get(square_entity) {
  103. selected_square.entity = Some(square_entity);
  104. // if a piece is already selected, set it to move
  105. if let Some(selected_piece_entity) = selected_piece.entity {
  106. if let Ok((_piece_entity, mut piece, _)) = pieces_query.get_mut(selected_piece_entity) {
  107. if piece.is_move_valid((square.x, square.y), &pieces_vec) {
  108. // check to see if we're capturing
  109. for (other_entity, other_piece, other_children) in pieces_entity_vec {
  110. if other_piece.x == square.x
  111. && other_piece.y == square.y
  112. && other_piece.color != piece.color
  113. {
  114. // if the king is taken, exit
  115. if other_piece.piece_type == PieceType::King {
  116. println!(
  117. "{} won! Thanks for playing!",
  118. match turn.0 {
  119. PieceColor::White => "White",
  120. PieceColor::Black => "Black",
  121. }
  122. );
  123. app_exit_events.send(AppExit);
  124. }
  125. // despawn the piece and its children
  126. commands.entity(other_entity).despawn();
  127. for child in other_children {
  128. commands.entity(child).despawn();
  129. }
  130. }
  131. }
  132. // and set it to move
  133. piece.x = square.x;
  134. piece.y = square.y;
  135. turn.0 = match turn.0 {
  136. PieceColor::White => PieceColor::Black,
  137. PieceColor::Black => PieceColor::White,
  138. }
  139. }
  140. }
  141. selected_square.entity = None;
  142. selected_piece.entity = None;
  143. } else {
  144. // otherwise, select the piece (if one) in the selected square
  145. for (piece_entity, piece, _) in pieces_query.iter_mut() {
  146. if piece.x == square.x
  147. && piece.y == square.y
  148. && piece.color == turn.0
  149. {
  150. selected_piece.entity = Some(piece_entity);
  151. break;
  152. }
  153. }
  154. }
  155. }
  156. } else {
  157. // clicked on nothing, deselect
  158. selected_square.entity = None;
  159. selected_piece.entity = None;
  160. }
  161. }
  162. }