bug infestation. selecting/capturing/etc in 2d works worse than in 3d

bevy0.12
Elijah C. Voigt 2 years ago
parent 8e0254c7e8
commit 38b796ad31

@ -33,7 +33,7 @@ impl Plugin for Display2dPlugin {
}), }),
update_background.run_if(on_event::<WindowResized>()), update_background.run_if(on_event::<WindowResized>()),
set_transform set_transform
.after(game::update_board::<Display2d>) .after(game::update_board)
.run_if(any_component_changed::<BoardIndex>), .run_if(any_component_changed::<BoardIndex>),
set_piece_sprite.run_if(any_component_changed::<Side>), set_piece_sprite.run_if(any_component_changed::<Side>),
set_tile_sprite.run_if(any_component_added::<game::Tile>), set_tile_sprite.run_if(any_component_added::<game::Tile>),

@ -11,8 +11,7 @@ impl Plugin for GamePlugin {
Update, Update,
( (
menu::exit_to_menu.run_if(in_state(GameState::Play)), menu::exit_to_menu.run_if(in_state(GameState::Play)),
update_board::<display2d::Display2d>.run_if(on_event::<Move>()), update_board.run_if(on_event::<Move>()),
update_board::<display3d::Display3d>.run_if(on_event::<Move>()),
set_side.run_if(on_event::<Move>()), // TODO: correct run_if? set_side.run_if(on_event::<Move>()), // TODO: correct run_if?
cancel_place.run_if(|buttons: Res<Input<MouseButton>>| -> bool { cancel_place.run_if(|buttons: Res<Input<MouseButton>>| -> bool {
buttons.just_pressed(MouseButton::Right) buttons.just_pressed(MouseButton::Right)
@ -20,10 +19,7 @@ impl Plugin for GamePlugin {
select_sync.run_if(any_component_added::<Selected>), select_sync.run_if(any_component_added::<Selected>),
deselect_sync.run_if(any_component_removed::<Selected>()), deselect_sync.run_if(any_component_removed::<Selected>()),
move_piece.run_if(any_component_added::<Selected>), move_piece.run_if(any_component_added::<Selected>),
exclusive_select::<display2d::Display2d> capture_piece.run_if(any_component_added::<Captured>),
.run_if(any_component_added::<Selected>),
exclusive_select::<display2d::Display2d>
.run_if(any_component_added::<Selected>),
), ),
) )
.add_systems( .add_systems(
@ -62,6 +58,9 @@ pub(crate) fn tiles() -> impl Iterator<Item = (BoardIndex, Tile)> {
#[derive(Debug, Component)] #[derive(Debug, Component)]
pub(crate) struct BoardComponent; pub(crate) struct BoardComponent;
#[derive(Debug, Component)]
pub(crate) struct Captured;
// manually for the type. // manually for the type.
impl std::fmt::Display for Piece { impl std::fmt::Display for Piece {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
@ -76,7 +75,6 @@ impl std::fmt::Display for Piece {
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum GameError { pub(crate) enum GameError {
NullMove, NullMove,
InvalidMove,
InvalidIndex, InvalidIndex,
} }
@ -150,12 +148,14 @@ impl Board {
) -> Result<Vec<Move>, GameError> { ) -> Result<Vec<Move>, GameError> {
if from == to { if from == to {
Err(GameError::NullMove) Err(GameError::NullMove)
} else if self.at(to).is_none() { } else {
self.at(from).map_or(Err(GameError::NullMove), |from_val| { self.at(from).map_or(Err(GameError::NullMove), |from_val| {
// The current epoch is the last epoch + 1 // The current epoch is the last epoch + 1
let epoch = self.moves.last().unwrap_or(&Move { ..default() }).epoch + 1; let epoch = self.moves.last().unwrap_or(&Move { ..default() }).epoch + 1;
// Local moves vec we can return // Local moves vec we can return
let mut moves = vec![]; let mut moves = vec![];
// If the position we are moving to is occupied, capture the removal in the ledger // If the position we are moving to is occupied, capture the removal in the ledger
if self.inner[to.y][to.x].is_some() { if self.inner[to.y][to.x].is_some() {
moves.push(Move { moves.push(Move {
@ -164,21 +164,21 @@ impl Board {
to: None, to: None,
}); });
} }
// Capture the intened move in the moves ledger // Capture the intened move in the moves ledger
moves.push(Move { moves.push(Move {
epoch, epoch,
from: from.clone(), from: from.clone(),
to: Some(to.clone()), to: Some(to.clone()),
}); });
self.moves.extend(moves.clone()); self.moves.extend(moves.clone());
// TODO: We can self.inner.swap(to, from) if board is single vec
// Update board to reflect move
self.inner[to.y][to.x] = Some(from_val); self.inner[to.y][to.x] = Some(from_val);
self.inner[from.y][from.x] = None; self.inner[from.y][from.x] = None;
Ok(moves) Ok(moves)
}) })
} else {
Err(GameError::InvalidMove)
} }
} }
@ -272,9 +272,10 @@ fn debug_board(board: Res<Board>, mut debug_info: ResMut<debug::DebugInfo>) {
/// Update this method to use a diff between the board and the state of the 2d/3d worlds /// Update this method to use a diff between the board and the state of the 2d/3d worlds
/// Only update the tiles without a corresponding board piece /// Only update the tiles without a corresponding board piece
pub(crate) fn update_board<T: Component>( pub(crate) fn update_board(
mut events: EventReader<Move>, mut events: EventReader<Move>,
mut pieces: Query<(Entity, &mut BoardIndex), (With<Piece>, With<T>)>, mut pieces: Query<(Entity, &mut BoardIndex), (With<Piece>, Without<Tile>)>,
tiles: Query<(Entity, &BoardIndex), (With<Tile>, Without<Piece>)>,
mut commands: Commands, mut commands: Commands,
) { ) {
events.iter().for_each(|Move { from, to, .. }| { events.iter().for_each(|Move { from, to, .. }| {
@ -282,12 +283,25 @@ pub(crate) fn update_board<T: Component>(
.iter_mut() .iter_mut()
.filter(|(_, index)| **index == *from) .filter(|(_, index)| **index == *from)
.for_each(|(entity, mut index)| { .for_each(|(entity, mut index)| {
if let Some(idx) = to { match to {
*index = idx.clone(); Some(to_idx) => {
} else { *index = to_idx.clone();
commands.entity(entity).remove::<BoardIndex>(); }
None => {
commands
.entity(entity)
.remove::<BoardIndex>()
.insert(Captured);
}
} }
}) commands.entity(entity).remove::<Selected>();
});
tiles
.iter()
.filter_map(|(entity, idx)| (Some(idx) == to.as_ref() || idx == from).then_some(entity))
.for_each(|entity| {
commands.entity(entity).remove::<Selected>();
});
}) })
} }
@ -349,44 +363,32 @@ fn cancel_place(current: Query<Entity, (With<Selected>, With<Piece>)>, mut comma
/// When a tile is selected, move all selected pieces to that index /// When a tile is selected, move all selected pieces to that index
fn move_piece( fn move_piece(
events: Query<(Entity, &BoardIndex), (With<Tile>, Added<Selected>)>, events: Query<(Entity, &BoardIndex), (With<BoardIndex>, Added<Selected>)>,
selected_pieces: Query<(Entity, &BoardIndex), (With<Selected>, With<Piece>)>, selected_pieces: Query<&BoardIndex, (With<Selected>, With<Piece>)>,
mut board: ResMut<Board>, mut board: ResMut<Board>,
mut commands: Commands, mut commands: Commands,
mut move_events: EventWriter<Move>, mut move_events: EventWriter<Move>,
) { ) {
events.iter().for_each(|(tile, to)| { events.iter().for_each(|(tile, to)| {
selected_pieces.iter().for_each(|(piece, from)| { selected_pieces.iter().for_each(|from| {
// Move piece // Move piece
match board.move_piece(from, to) { match board.move_piece(from, to) {
Ok(moves) => { Ok(moves) => {
// De-select the piece // De-select the piece
commands.entity(piece).remove::<Selected>(); info!("Applying moves {:?}", moves);
moves.iter().for_each(|m| move_events.send(m.clone())); moves.iter().for_each(|m| move_events.send(m.clone()));
} }
Err(GameError::NullMove) => warn!("Null move!"), Err(GameError::NullMove) => warn!("Null move!"),
Err(GameError::InvalidMove) => warn!("Invalid move!"),
Err(GameError::InvalidIndex) => warn!("Invalid index!"), Err(GameError::InvalidIndex) => warn!("Invalid index!"),
} }
}); });
// De-select the tile
commands.entity(tile).remove::<Selected>();
}); });
} }
/// TEMPORARY: Exclusive selection; only select one piece at a time /// When a piece's _BoardIndex_ is removed, we hide that entity from the viewer
fn exclusive_select<T: Component>( fn capture_piece(mut events: Query<&mut Visibility, Added<Captured>>) {
events: Query<Entity, (Added<Selected>, With<Piece>, With<T>)>, events.iter_mut().for_each(|mut vis| {
selected: Query<Entity, (With<Selected>, With<Piece>, With<T>)>, info!("Hiding captured piece");
mut commands: Commands, *vis = Visibility::Hidden
) {
// Iterate over selected component markers on pieces
events.iter().for_each(|entity| {
// Selected > 2 (one for each display2d/3d)
selected.iter().filter(|&e| e != entity).for_each(|e| {
// Remove the previously added selected marker
commands.entity(e).remove::<Selected>();
});
}); });
} }

@ -143,7 +143,7 @@ fn toggle_display_mode(
fn activate<Marker: Component>( fn activate<Marker: Component>(
mut cameras: Query<&mut Camera, With<Marker>>, mut cameras: Query<&mut Camera, With<Marker>>,
mut entities: Query<&mut Visibility, With<Marker>>, mut entities: Query<&mut Visibility, (With<Marker>, Without<game::Captured>)>,
) { ) {
cameras.iter_mut().for_each(|mut camera| { cameras.iter_mut().for_each(|mut camera| {
camera.is_active = true; camera.is_active = true;
@ -155,7 +155,7 @@ fn activate<Marker: Component>(
fn deactivate<Marker: Component>( fn deactivate<Marker: Component>(
mut cameras: Query<&mut Camera, With<Marker>>, mut cameras: Query<&mut Camera, With<Marker>>,
mut entities: Query<&mut Visibility, With<Marker>>, mut entities: Query<&mut Visibility, (With<Marker>, Without<game::Captured>)>,
) { ) {
cameras.iter_mut().for_each(|mut camera| { cameras.iter_mut().for_each(|mut camera| {
camera.is_active = false; camera.is_active = false;

Loading…
Cancel
Save