From eea2f879d0647b7b519cc49ed62d434e533a09e0 Mon Sep 17 00:00:00 2001 From: "Elijah C. Voigt" Date: Sun, 21 Jan 2024 22:31:04 -0800 Subject: [PATCH] skeleton for capture animation flow --- .gitignore | 4 + assets/examples/shaders/dissolve.wgsl | 2 +- src/display2d.rs | 13 ++++ src/display3d.rs | 102 ++++++++++++++++++++++++-- src/game.rs | 32 +++++--- 5 files changed, 138 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 37ffd44..0389a60 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,7 @@ trace-*.json *.blend *.blend1 + + +# Don't need this +.vscode/ \ No newline at end of file diff --git a/assets/examples/shaders/dissolve.wgsl b/assets/examples/shaders/dissolve.wgsl index da4e520..63ef228 100644 --- a/assets/examples/shaders/dissolve.wgsl +++ b/assets/examples/shaders/dissolve.wgsl @@ -67,7 +67,7 @@ fn fragment( var n = fbm(pos); - var cutoff = mat_ext.cutoff; // abs(sin(globals.time)); + var cutoff = mat_ext.cutoff; if n > cutoff { discard; diff --git a/src/display2d.rs b/src/display2d.rs index 67e2cd8..f79dbad 100644 --- a/src/display2d.rs +++ b/src/display2d.rs @@ -41,6 +41,7 @@ impl Plugin for Display2dPlugin { set_sprite.run_if(any_component_changed::), // When tweakfile is updated set_sprite.run_if(resource_exists_and_changed::()), + capture_piece.run_if(any_component_added::), ), ) .add_systems(OnEnter(DisplayState::Display2d), activate::) @@ -389,3 +390,15 @@ fn move_piece( } }) } + +/// When a piece is captured, we make it invisible in 2D +fn capture_piece( + mut events: Query<(Entity, &mut Visibility), (With, Added)>, + mut commands: Commands, +) { + events.iter_mut().for_each(|(entity, mut vis)| { + info!("Hiding captured piece"); + *vis = Visibility::Hidden; + commands.entity(entity).remove::(); + }); +} \ No newline at end of file diff --git a/src/display3d.rs b/src/display3d.rs index f5468a7..6135f54 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -61,8 +61,9 @@ impl Plugin for Display3dPlugin { any_component_added:: .or_else(any_component_added::) .or_else(any_component_added::) - .or_else(on_event::>()) + .or_else(on_event::>()), ), + capture_piece.run_if(any_with_component::()), ), ) .add_systems( @@ -473,6 +474,26 @@ fn board_translation(&BoardIndex { x, y }: &BoardIndex) -> Vec3 { Vec3::new(x, 0.0, y) } +fn capture_translation(side: &Side, num: usize) -> Vec3 { + info!("Side: {:?} Num: {:?}", side, num); + match side { + Side::B => { + let x = -((num % 4) as f32 * 1.3 + 4.0); // mod(num, 4) + let z = (num / 4) as f32 * 1.3 + 4.0; // floor(div(num, 4)) + let y = -1.3; + info!("Vec3({}, {}, {})", x, y, z); + Vec3::new(x, y, z) + }, + Side::A => { + let x = (num % 4) as f32 * 1.3 + 4.0; // mod(num, 4) + let z = -((num / 4) as f32 * 1.3 + 4.0); // floor(div(num, 4)) + let y = -1.3; + info!("Vec3({}, {}, {})", x, y, z); + Vec3::new(x, y, z) + } + } +} + fn gizmo_system(mut gizmos: Gizmos) { for y in 0..4 { for x in 0..8 { @@ -786,6 +807,7 @@ fn moves_gizmo( /// Spawn 3d "Valid move" indicators when a piece is selected /// Another system registers these new entities and associates the correct models and plays animations. +/// TODO: Do not create/delete entities at runtime fn create_valid_move_entity( events: Query<&BoardIndex, (With, Added, With)>, board: Res, @@ -841,7 +863,7 @@ fn _play_valid_move_animation(_players: Query<&AnimationPlayer>) { todo!(); } -// TODO: Move this to game.rs +// TODO: Do not create/delete entities at runtime /// Remove "Valid Move" indicators when a piece is de-selected fn remove_valid_move_entity( mut events: RemovedComponents, @@ -1025,7 +1047,7 @@ fn scale_lighting( let directional_tweak = tweak.get::("display3d_lights_scaling_directional").expect("Directional lighting scalar"); directional.iter_mut().for_each(|(entity, mut val, original)| { - info!("Scaling directional light {:?}", entity); + debug!("Scaling directional light {:?}", entity); if let Some(Original(v)) = original { val.illuminance = v.illuminance * directional_tweak; } else { @@ -1036,7 +1058,7 @@ fn scale_lighting( let spot_tweak = tweak.get::("display3d_lights_scaling_spot").expect("Spot lighting scalar"); spot.iter_mut().for_each(|(entity, mut val, original)| { - info!("Scaling spot light {:?}", entity); + debug!("Scaling spot light {:?}", entity); if let Some(Original(v)) = original { val.intensity = v.intensity * spot_tweak; } else { @@ -1047,7 +1069,7 @@ fn scale_lighting( let point_tweak = tweak.get::("display3d_lights_scaling_point").expect("Point lighting scalar"); point.iter_mut().for_each(|(entity, mut val, original)| { - info!("Scaling point light {:?}", entity); + debug!("Scaling point light {:?}", entity); if let Some(Original(v)) = original { val.intensity = v.intensity * point_tweak; } else { @@ -1223,3 +1245,73 @@ pub(super) mod tweaks { } } } + +/// When a piece is captured... +/// 1. Play a cool "captured" animation and a neat sound +/// 2. Move the piece to the side of the board +/// 3. Play the same "captured" animation in reverse +/// The animation is like a 'beam me up scotty' sorta thing. +fn capture_piece( + mut events: Query, Added)>, + mut query: Query<(&mut Visibility, &mut Transform, &Side), (With, With)>, + mut state: Local>, + mut commands: Commands, +) { + match *state { + Some(s) => { + match s { + game::CaptureFlow::FadeOut(entity) => { + let (mut v, _, _) = query + .get_mut(entity) + .expect("Visibility and Transform of captured piece"); + + // Play fade-out animation + { + error!("Run fade-out animation"); + + // Move to next state now that animation is done + *state = s.next(); + + // Hide piece now that animation is done + *v = Visibility::Hidden; + } + }, + game::CaptureFlow::Store(entity) => { + let (_, mut t, side) = query + .get_mut(entity) + .expect("Visibility and Transform of captured piece"); + + // Move piece to next spot at side of table + error!("Move piece to side of table"); + // TODO: Dynamic number based on side's score + t.translation = capture_translation(side, 1); + + *state = s.next(); + }, + game::CaptureFlow::FadeIn(entity) => { + let (mut v, _, _) = query + .get_mut(entity) + .expect("Visibility and Transform of captured piece"); + + // Show piece now that it is moved + *v = Visibility::Inherited; + + // Play fade-in animation + { + error!("Run fade-in animation"); + // When animation is done, move to next phase of flow + *state = s.next(); + } + + // Remove the captured component for bookkeeping + commands.entity(entity).remove::(); + } + } + }, + None => { + *state = events.iter().next().map(|entity| { + game::CaptureFlow::FadeOut(entity) + }); + } + } +} \ No newline at end of file diff --git a/src/game.rs b/src/game.rs index 7d4cf99..618d45e 100644 --- a/src/game.rs +++ b/src/game.rs @@ -23,7 +23,6 @@ impl Plugin for GamePlugin { buttons.just_pressed(MouseButton::Right) }), handle_selection.run_if(on_event::()), - capture_piece.run_if(any_component_added::), switch_sides.run_if(|input: Res>| -> bool { input.just_pressed(KeyCode::N) }), @@ -130,6 +129,29 @@ pub(crate) struct Move { pub to: Option, } +/// Enum for the Capture event flow +#[derive(Debug, Clone, Copy, Resource)] +pub(crate) enum CaptureFlow { + // Run the "fade out" animation + FadeOut(Entity), + // Put the captured piece next to the board + Store(Entity), + // Run the "fade in" animation + FadeIn(Entity), +} + +impl CaptureFlow { + /// The capture flow so we can move from one "capture flow state" to the next + /// Fade out, then store, then fade in + pub(crate) fn next(&self) -> Option { + match self { + Self::FadeOut(e) => Some(Self::Store(e.clone())), + Self::Store(e) => Some(Self::FadeIn(e.clone())), + Self::FadeIn(_) => None, + } + } +} + #[derive(Debug, Component, PartialEq, Clone, Default, Copy, Eq, Hash)] pub(crate) struct BoardIndex { pub x: usize, @@ -553,14 +575,6 @@ fn cancel_place(current: Query<&BoardIndex, With>, mut events: EventWr }); } -/// When a piece's _BoardIndex_ is removed, we hide that entity from the viewer -fn capture_piece(mut events: Query<&mut Visibility, Added>) { - events.iter_mut().for_each(|mut vis| { - info!("Hiding captured piece"); - *vis = Visibility::Hidden - }); -} - /// Panics if more than two pieces are selected at a time fn asserts( selected_pieces: Query, With, With)>,