|
@@ -1,7 +1,214 @@
|
|
|
use bevy::prelude::*;
|
|
|
|
|
|
|
|
|
-pub fn create_pieces(
|
|
|
+pub struct PiecesPlugin;
|
|
|
+impl Plugin for PiecesPlugin {
|
|
|
+ fn build(&self, app: &mut AppBuilder) {
|
|
|
+ app.add_startup_system(create_pieces.system())
|
|
|
+ .add_system(move_pieces.system());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#[derive(Clone, Copy, PartialEq)]
|
|
|
+pub enum PieceColor {
|
|
|
+ White,
|
|
|
+ Black,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Clone, Copy, PartialEq)]
|
|
|
+pub enum PieceType {
|
|
|
+ King,
|
|
|
+ Queen,
|
|
|
+ Bishop,
|
|
|
+ Knight,
|
|
|
+ Rook,
|
|
|
+ Pawn,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Clone, Copy)]
|
|
|
+pub struct Piece {
|
|
|
+ pub color: PieceColor,
|
|
|
+ pub piece_type: PieceType,
|
|
|
+ // current positoin
|
|
|
+ pub x: u8,
|
|
|
+ pub y: u8,
|
|
|
+}
|
|
|
+
|
|
|
+impl Piece {
|
|
|
+ pub fn is_move_valid(&self, new_position: (u8,u8), pieces: &Vec<Piece>) -> bool {
|
|
|
+ if color_in_square(new_position, &pieces) == Some(self.color) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if self.x == new_position.0 && self.y == new_position.1 {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ match self.piece_type {
|
|
|
+ PieceType::King => {
|
|
|
+ ((self.x as i8 - new_position.0 as i8).abs() <=1
|
|
|
+ && (self.y as i8 - new_position.1 as i8).abs() <= 1)
|
|
|
+ }
|
|
|
+ PieceType::Queen => {
|
|
|
+ is_path_empty((self.x, self.y), new_position, &pieces)
|
|
|
+ && ((self.x as i8 - new_position.0 as i8).abs()
|
|
|
+ == (self.y as i8 - new_position.1 as i8).abs()
|
|
|
+ || self.x == new_position.0
|
|
|
+ || self.y == new_position.1)
|
|
|
+ }
|
|
|
+ PieceType::Bishop => {
|
|
|
+ is_path_empty((self.x, self.y), new_position, &pieces)
|
|
|
+ && (self.x as i8 - new_position.0 as i8).abs()
|
|
|
+ == (self.y as i8 - new_position.1 as i8).abs()
|
|
|
+ }
|
|
|
+ PieceType::Rook => {
|
|
|
+ is_path_empty((self.x, self.y), new_position, &pieces)
|
|
|
+ && (self.x == new_position.0
|
|
|
+ || self.y == new_position.1)
|
|
|
+ }
|
|
|
+ PieceType::Knight => {
|
|
|
+ ((self.x as i8 - new_position.0 as i8).abs() == 2
|
|
|
+ && (self.y as i8 - new_position.1 as i8).abs() == 1)
|
|
|
+ || ((self.x as i8 - new_position.0 as i8).abs() == 1
|
|
|
+ && (self.y as i8 - new_position.1 as i8).abs() == 2)
|
|
|
+ }
|
|
|
+ PieceType::Pawn => {
|
|
|
+ if self.color == PieceColor::White {
|
|
|
+ // normal move
|
|
|
+ if new_position.0 as i8 - self.x as i8 == 1
|
|
|
+ && (self.y == new_position.1)
|
|
|
+ && color_in_square(new_position, &pieces).is_none()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // initial 2 squares
|
|
|
+ if self.x == 1
|
|
|
+ && new_position.0 == 3
|
|
|
+ && self.y == new_position.1
|
|
|
+ && is_path_empty((self.x, self.y), new_position, &pieces)
|
|
|
+ && color_in_square(new_position, &pieces).is_none()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // capture
|
|
|
+ if new_position.0 as i8 - self.x as i8 == 1
|
|
|
+ && (self.y as i8 - new_position.1 as i8).abs() == 1
|
|
|
+ && color_in_square(new_position, &pieces) == Some(PieceColor::Black)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // normal move
|
|
|
+ if self.x as i8 - new_position.0 as i8 == 1
|
|
|
+ && (self.y == new_position.1)
|
|
|
+ && color_in_square(new_position, &pieces).is_none()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // initial 2 squares
|
|
|
+ if self.x == 6
|
|
|
+ && new_position.0 == 4
|
|
|
+ && self.y == new_position.1
|
|
|
+ && is_path_empty((self.x, self.y), new_position, &pieces)
|
|
|
+ && color_in_square(new_position, &pieces).is_none()
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // capture
|
|
|
+ if self.x as i8 - new_position.0 as i8 == 1
|
|
|
+ && (self.y as i8 - new_position.1 as i8).abs() == 1
|
|
|
+ && color_in_square(new_position, &pieces) == Some(PieceColor::White)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// returns the color of the piece in the square (or None if empty)
|
|
|
+fn color_in_square(pos: (u8,u8), pieces: &Vec<Piece>) -> Option<PieceColor> {
|
|
|
+ for piece in pieces {
|
|
|
+ if piece.x == pos.0 && piece.y == pos.1 {
|
|
|
+ return Some(piece.color);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ None
|
|
|
+}
|
|
|
+
|
|
|
+// checks to see if the straight line between two squares is clear of pieces
|
|
|
+fn is_path_empty(
|
|
|
+ begin: (u8,u8),
|
|
|
+ end: (u8,u8),
|
|
|
+ pieces: &Vec<Piece>)
|
|
|
+ -> bool
|
|
|
+{
|
|
|
+ // same column
|
|
|
+ if begin.0 == end.0 {
|
|
|
+ for piece in pieces {
|
|
|
+ if piece.x == begin.0
|
|
|
+ && ((piece.y > begin.1 && piece.y < end.1)
|
|
|
+ || (piece.y > end.1 && piece.y < begin.1))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // same row
|
|
|
+ if begin.1 == end.1 {
|
|
|
+ for piece in pieces {
|
|
|
+ if piece.y == begin.1
|
|
|
+ && ((piece.x > begin.0 && piece.x < end.0)
|
|
|
+ || (piece.x > end.0 && piece.x < begin.0))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // diagonals
|
|
|
+ let x_diff = (begin.0 as i8 - end.0 as i8).abs();
|
|
|
+ let y_diff = (begin.1 as i8 - end.1 as i8).abs();
|
|
|
+ if x_diff == y_diff {
|
|
|
+ for i in 1..x_diff {
|
|
|
+ let pos = if begin.0 < end.0 && begin.1 < end.1 {
|
|
|
+ // left bottom -> right top
|
|
|
+ (begin.0 + i as u8, begin.1 + i as u8)
|
|
|
+ } else if begin.0 < end.0 && begin.1 > end.1 {
|
|
|
+ // left top -> right bottom
|
|
|
+ (begin.0 + i as u8, begin.1 - i as u8)
|
|
|
+ } else if begin.0 > end.0 && begin.1 < end.1 {
|
|
|
+ // right bottom -> left top
|
|
|
+ (begin.0 - i as u8, begin.1 + i as u8)
|
|
|
+ } else {
|
|
|
+ // right top -> left bottom
|
|
|
+ (begin.0 - i as u8, begin.1 - i as u8)
|
|
|
+ };
|
|
|
+
|
|
|
+ if color_in_square(pos, pieces).is_some() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ true
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+fn create_pieces(
|
|
|
mut commands: Commands,
|
|
|
asset_server: Res<AssetServer>,
|
|
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
@@ -23,61 +230,70 @@ pub fn create_pieces(
|
|
|
spawn_rook(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
rook_handle.clone(),
|
|
|
- Vec3::new(0.0, 0.0, 0.0),
|
|
|
+ (0,0),
|
|
|
);
|
|
|
spawn_knight(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
knight_1_handle.clone(),
|
|
|
knight_2_handle.clone(),
|
|
|
- Vec3::new(0.0, 0.0, 1.0),
|
|
|
+ (0,1),
|
|
|
);
|
|
|
spawn_bishop(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
bishop_handle.clone(),
|
|
|
- Vec3::new(0.0, 0.0, 2.0),
|
|
|
+ (0,2),
|
|
|
);
|
|
|
spawn_queen(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
queen_handle.clone(),
|
|
|
- Vec3::new(0.0, 0.0, 3.0),
|
|
|
+ (0,3),
|
|
|
);
|
|
|
spawn_king(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
king_handle.clone(),
|
|
|
king_cross_handle.clone(),
|
|
|
- Vec3::new(0.0, 0.0, 4.0),
|
|
|
+ (0,4),
|
|
|
);
|
|
|
spawn_bishop(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
bishop_handle.clone(),
|
|
|
- Vec3::new(0.0, 0.0, 5.0),
|
|
|
+ (0,5),
|
|
|
);
|
|
|
spawn_knight(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
knight_1_handle.clone(),
|
|
|
knight_2_handle.clone(),
|
|
|
- Vec3::new(0.0, 0.0, 6.0),
|
|
|
+ (0,6),
|
|
|
);
|
|
|
spawn_rook(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
rook_handle.clone(),
|
|
|
- Vec3::new(0.0, 0.0, 7.0),
|
|
|
+ (0,7),
|
|
|
);
|
|
|
|
|
|
for i in 0..8 {
|
|
|
spawn_pawn(
|
|
|
&mut commands,
|
|
|
white_material.clone(),
|
|
|
+ PieceColor::White,
|
|
|
pawn_handle.clone(),
|
|
|
- Vec3::new(1.0, 0.0, i as f32),
|
|
|
+ (1, i),
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -85,61 +301,70 @@ pub fn create_pieces(
|
|
|
spawn_rook(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
rook_handle.clone(),
|
|
|
- Vec3::new(7.0, 0.0, 0.0),
|
|
|
+ (7,0),
|
|
|
);
|
|
|
spawn_knight(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
knight_1_handle.clone(),
|
|
|
knight_2_handle.clone(),
|
|
|
- Vec3::new(7.0, 0.0, 1.0),
|
|
|
+ (7,1),
|
|
|
);
|
|
|
spawn_bishop(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
bishop_handle.clone(),
|
|
|
- Vec3::new(7.0, 0.0, 2.0),
|
|
|
+ (7,2),
|
|
|
);
|
|
|
spawn_queen(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
queen_handle.clone(),
|
|
|
- Vec3::new(7.0, 0.0, 3.0),
|
|
|
+ (7,3),
|
|
|
);
|
|
|
spawn_king(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
king_handle.clone(),
|
|
|
king_cross_handle.clone(),
|
|
|
- Vec3::new(7.0, 0.0, 4.0),
|
|
|
+ (7,4),
|
|
|
);
|
|
|
spawn_bishop(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
bishop_handle.clone(),
|
|
|
- Vec3::new(7.0, 0.0, 5.0),
|
|
|
+ (7,5),
|
|
|
);
|
|
|
spawn_knight(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
knight_1_handle.clone(),
|
|
|
knight_2_handle.clone(),
|
|
|
- Vec3::new(7.0, 0.0, 6.0),
|
|
|
+ (7,6),
|
|
|
);
|
|
|
spawn_rook(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
rook_handle.clone(),
|
|
|
- Vec3::new(7.0, 0.0, 7.0),
|
|
|
+ (7,7),
|
|
|
);
|
|
|
|
|
|
for i in 0..8 {
|
|
|
spawn_pawn(
|
|
|
&mut commands,
|
|
|
black_material.clone(),
|
|
|
+ PieceColor::Black,
|
|
|
pawn_handle.clone(),
|
|
|
- Vec3::new(6.0, 0.0, i as f32),
|
|
|
+ (6, i),
|
|
|
);
|
|
|
}
|
|
|
}
|
|
@@ -149,16 +374,27 @@ pub fn create_pieces(
|
|
|
fn spawn_king(
|
|
|
commands: &mut Commands,
|
|
|
material: Handle<StandardMaterial>,
|
|
|
+ piece_color: PieceColor,
|
|
|
mesh: Handle<Mesh>,
|
|
|
mesh_cross: Handle<Mesh>,
|
|
|
- position: Vec3,
|
|
|
+ position: (u8, u8),
|
|
|
) {
|
|
|
// spawn parent
|
|
|
commands
|
|
|
.spawn_bundle(PbrBundle {
|
|
|
- transform: Transform::from_translation(position),
|
|
|
+ transform: Transform::from_translation(Vec3::new(
|
|
|
+ position.0 as f32,
|
|
|
+ 0.0,
|
|
|
+ position.1 as f32,
|
|
|
+ )),
|
|
|
..Default::default()
|
|
|
})
|
|
|
+ .insert(Piece {
|
|
|
+ color: piece_color,
|
|
|
+ piece_type: PieceType::King,
|
|
|
+ x: position.0,
|
|
|
+ y: position.1,
|
|
|
+ })
|
|
|
.with_children(|parent| {
|
|
|
parent.spawn_bundle(PbrBundle {
|
|
|
mesh,
|
|
@@ -187,16 +423,27 @@ fn spawn_king(
|
|
|
fn spawn_knight(
|
|
|
commands: &mut Commands,
|
|
|
material: Handle<StandardMaterial>,
|
|
|
+ piece_color: PieceColor,
|
|
|
mesh_1: Handle<Mesh>,
|
|
|
mesh_2: Handle<Mesh>,
|
|
|
- position: Vec3,
|
|
|
+ position: (u8, u8),
|
|
|
) {
|
|
|
// spawn parent
|
|
|
commands
|
|
|
.spawn_bundle(PbrBundle {
|
|
|
- transform: Transform::from_translation(position),
|
|
|
+ transform: Transform::from_translation(Vec3::new(
|
|
|
+ position.0 as f32,
|
|
|
+ 0.0,
|
|
|
+ position.1 as f32,
|
|
|
+ )),
|
|
|
..Default::default()
|
|
|
})
|
|
|
+ .insert(Piece {
|
|
|
+ color: piece_color,
|
|
|
+ piece_type: PieceType::Knight,
|
|
|
+ x: position.0,
|
|
|
+ y: position.1,
|
|
|
+ })
|
|
|
.with_children(|parent| {
|
|
|
parent.spawn_bundle(PbrBundle {
|
|
|
mesh: mesh_1,
|
|
@@ -225,15 +472,26 @@ fn spawn_knight(
|
|
|
fn spawn_queen(
|
|
|
commands: &mut Commands,
|
|
|
material: Handle<StandardMaterial>,
|
|
|
+ piece_color: PieceColor,
|
|
|
mesh: Handle<Mesh>,
|
|
|
- position: Vec3,
|
|
|
+ position: (u8, u8),
|
|
|
) {
|
|
|
// spawn parent
|
|
|
commands
|
|
|
.spawn_bundle(PbrBundle {
|
|
|
- transform: Transform::from_translation(position),
|
|
|
+ transform: Transform::from_translation(Vec3::new(
|
|
|
+ position.0 as f32,
|
|
|
+ 0.0,
|
|
|
+ position.1 as f32,
|
|
|
+ )),
|
|
|
..Default::default()
|
|
|
})
|
|
|
+ .insert(Piece {
|
|
|
+ color: piece_color,
|
|
|
+ piece_type: PieceType::Queen,
|
|
|
+ x: position.0,
|
|
|
+ y: position.1,
|
|
|
+ })
|
|
|
.with_children(|parent| {
|
|
|
parent.spawn_bundle(PbrBundle {
|
|
|
mesh,
|
|
@@ -252,15 +510,26 @@ fn spawn_queen(
|
|
|
fn spawn_bishop(
|
|
|
commands: &mut Commands,
|
|
|
material: Handle<StandardMaterial>,
|
|
|
+ piece_color: PieceColor,
|
|
|
mesh: Handle<Mesh>,
|
|
|
- position: Vec3,
|
|
|
+ position: (u8, u8),
|
|
|
) {
|
|
|
// spawn parent
|
|
|
commands
|
|
|
.spawn_bundle(PbrBundle {
|
|
|
- transform: Transform::from_translation(position),
|
|
|
+ transform: Transform::from_translation(Vec3::new(
|
|
|
+ position.0 as f32,
|
|
|
+ 0.0,
|
|
|
+ position.1 as f32,
|
|
|
+ )),
|
|
|
..Default::default()
|
|
|
})
|
|
|
+ .insert(Piece {
|
|
|
+ color: piece_color,
|
|
|
+ piece_type: PieceType::Bishop,
|
|
|
+ x: position.0,
|
|
|
+ y: position.1,
|
|
|
+ })
|
|
|
.with_children(|parent| {
|
|
|
parent.spawn_bundle(PbrBundle {
|
|
|
mesh,
|
|
@@ -279,15 +548,26 @@ fn spawn_bishop(
|
|
|
fn spawn_rook(
|
|
|
commands: &mut Commands,
|
|
|
material: Handle<StandardMaterial>,
|
|
|
+ piece_color: PieceColor,
|
|
|
mesh: Handle<Mesh>,
|
|
|
- position: Vec3,
|
|
|
+ position: (u8, u8),
|
|
|
) {
|
|
|
// spawn parent
|
|
|
commands
|
|
|
.spawn_bundle(PbrBundle {
|
|
|
- transform: Transform::from_translation(position),
|
|
|
+ transform: Transform::from_translation(Vec3::new(
|
|
|
+ position.0 as f32,
|
|
|
+ 0.0,
|
|
|
+ position.1 as f32,
|
|
|
+ )),
|
|
|
..Default::default()
|
|
|
})
|
|
|
+ .insert(Piece {
|
|
|
+ color: piece_color,
|
|
|
+ piece_type: PieceType::Rook,
|
|
|
+ x: position.0,
|
|
|
+ y: position.1,
|
|
|
+ })
|
|
|
.with_children(|parent| {
|
|
|
parent.spawn_bundle(PbrBundle {
|
|
|
mesh,
|
|
@@ -306,15 +586,26 @@ fn spawn_rook(
|
|
|
fn spawn_pawn(
|
|
|
commands: &mut Commands,
|
|
|
material: Handle<StandardMaterial>,
|
|
|
+ piece_color: PieceColor,
|
|
|
mesh: Handle<Mesh>,
|
|
|
- position: Vec3,
|
|
|
+ position: (u8, u8),
|
|
|
) {
|
|
|
// spawn parent
|
|
|
commands
|
|
|
.spawn_bundle(PbrBundle {
|
|
|
- transform: Transform::from_translation(position),
|
|
|
+ transform: Transform::from_translation(Vec3::new(
|
|
|
+ position.0 as f32,
|
|
|
+ 0.0,
|
|
|
+ position.1 as f32,
|
|
|
+ )),
|
|
|
..Default::default()
|
|
|
})
|
|
|
+ .insert(Piece {
|
|
|
+ color: piece_color,
|
|
|
+ piece_type: PieceType::Pawn,
|
|
|
+ x: position.0,
|
|
|
+ y: position.1,
|
|
|
+ })
|
|
|
.with_children(|parent| {
|
|
|
parent.spawn_bundle(PbrBundle {
|
|
|
mesh,
|
|
@@ -330,6 +621,21 @@ fn spawn_pawn(
|
|
|
}
|
|
|
|
|
|
|
|
|
+fn move_pieces(
|
|
|
+ time: Res<Time>,
|
|
|
+ mut query: Query<(&mut Transform, &Piece)>,
|
|
|
+) {
|
|
|
+ for (mut transform, piece) in query.iter_mut() {
|
|
|
+ // get the direction to move in
|
|
|
+ let direction = Vec3::new(piece.x as f32, 0.0, piece.y as f32) - transform.translation;
|
|
|
+
|
|
|
+ // only move it if it isn't already there
|
|
|
+ if direction.length() > 0.1 {
|
|
|
+ transform.translation += direction.normalize() * time.delta_seconds();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
|