diff --git a/src/display2d.rs b/src/display2d.rs index 92a2f50..833878b 100644 --- a/src/display2d.rs +++ b/src/display2d.rs @@ -197,16 +197,7 @@ fn initialize_board(sprite_sheet: Option>, mut commands: Comman } } -/// TODO: YOU DUMB IDIOT -/// JUST RE-DRAW ANY ENTITY WITH A CHANGED BoardIndex!! -/// INITIALIZE THE STARTING BOARD, THEN JUST UPDATE CHANGED BOARDINDEX!!! -/// GOD YOU ARE SO DUMB. -/// -/// OK so that won't quite work because we want the 2d/3d states to stay in sync. -/// We can figure some way of diffing the board though. -/// -/// I mean we can still have a system that sets the location based on index changes. -/// But the index changes can be the _only_ change we make in the update_board method. +/// Update the location of pieces on the board fn draw_board( board: Option>, sprite_sheet: Option>, diff --git a/src/display3d.rs b/src/display3d.rs index 3f88fd1..754c7da 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -13,14 +13,20 @@ impl Plugin for Display3dPlugin { ) .add_systems( Update, - gizmo_system - .run_if(in_state(GameState::Display3d)) - .run_if(resource_exists::()), + update_board + // .run_if(in_state(GameState::Display3d)) + .run_if(resource_changed::()), ) .add_systems( Update, set_piece_position.run_if(in_state(GameState::Display3d)), ) + .add_systems( + Update, + gizmo_system + .run_if(in_state(GameState::Display3d)) + .run_if(resource_exists::()), + ) .add_systems(OnEnter(GameState::Display3d), activate) .add_systems(OnExit(GameState::Display3d), deactivate); } @@ -124,11 +130,13 @@ fn initialize_board( }, )) .with_children(|parent| { + // TODO: Add this to a reactive system when board is added board .unwrap() .pieces() .into_iter() .for_each(|(index, piece)| { + // TODO: Move this to a reactive system like index -> Transform let scene = match piece { game::Piece::Pawn => gltf.named_scenes.get("Pawn"), game::Piece::Drone => gltf.named_scenes.get("Drone"), @@ -137,13 +145,98 @@ fn initialize_board( .expect("Game board model") .clone(); - parent.spawn((Piece3d, index, SceneBundle { scene, ..default() })); + parent.spawn(( + Piece3d, + piece, + index, + SceneBundle { scene, ..default() }, + )); }); }); }); } } +/// Update the location of pieces on the 3d board +fn update_board( + board: Option>, + mut pieces: Query<(Entity, &mut BoardIndex, &game::Piece), With>, + mut commands: Commands, +) { + if let Some(board) = board { + let board_pieces = board.pieces(); + + { + // Get a list of all Queen piece entities + let mut queen_entities = pieces + .iter_mut() + .filter_map(|(entity, idx, p)| (*p == game::Piece::Queen).then_some((entity, idx))); + + // Compare each board piece with an entity piece + // Set the board index for this particular queen + board_pieces + .iter() + .filter_map(|(index, p)| (*p == game::Piece::Queen).then_some(index)) + .for_each(|index| { + if let Some((_, mut idx)) = queen_entities.next() { + *idx = index.clone(); + } + }); + // If we have one left that means this queen has been "destroyed" so we remove the + // BoardIndex component from the entitiy, removing it from play. + if let Some((entity, _)) = queen_entities.next() { + commands.entity(entity).remove::(); + } + } + + { + // Get a list of all drone piece entities + let mut drone_entities = pieces + .iter_mut() + .filter_map(|(entity, idx, p)| (*p == game::Piece::Drone).then_some((entity, idx))); + + // Compare each board piece with an entity piece + // Set the board index for this particular drone + board_pieces + .iter() + .filter_map(|(index, p)| (*p == game::Piece::Drone).then_some(index)) + .for_each(|index| { + if let Some((_, mut idx)) = drone_entities.next() { + *idx = index.clone(); + } + }); + // If we have one left that means this drone has been "destroyed" so we remove the + // BoardIndex component from the entitiy, removing it from play. + if let Some((entity, _)) = drone_entities.next() { + commands.entity(entity).remove::(); + } + } + + { + // Get a list of all pawn piece entities + let mut pawn_entities = pieces + .iter_mut() + .filter_map(|(entity, idx, p)| (*p == game::Piece::Pawn).then_some((entity, idx))); + + // Compare each board piece with an entity piece + // Set the board index for this particular pawn + board_pieces + .iter() + .filter_map(|(index, p)| (*p == game::Piece::Pawn).then_some(index)) + .for_each(|index| { + if let Some((_, mut idx)) = pawn_entities.next() { + *idx = index.clone(); + } + }); + // If we have one left that means this pawn has been "destroyed" so we remove the + // BoardIndex component from the entitiy, removing it from play. + if let Some((entity, _)) = pawn_entities.next() { + commands.entity(entity).remove::(); + } + } + } +} + /// Sets a piece location given it's board index fn set_piece_position( mut events: Query<(&mut Transform, &BoardIndex), (With, Changed)>, diff --git a/src/game.rs b/src/game.rs index 371c7be..c88591f 100644 --- a/src/game.rs +++ b/src/game.rs @@ -19,7 +19,7 @@ impl Plugin for GamePlugin { } } -#[derive(Debug, Component, Clone)] +#[derive(Debug, Component, Clone, PartialEq)] pub(crate) enum Piece { Pawn, Drone,