From 41bbca55ccce8831ddd3592a54b5f56f0ea9b260 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Tue, 24 Dec 2024 21:38:07 -0800 Subject: [PATCH] Using animations for card rotation! Now to add deal and discard animations... --- src/play.rs | 33 +++++++++----- src/setup.rs | 122 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 92 insertions(+), 63 deletions(-) diff --git a/src/play.rs b/src/play.rs index 2e2f2d3..088cbe6 100644 --- a/src/play.rs +++ b/src/play.rs @@ -1,6 +1,9 @@ -use bevy::prelude::*; +use bevy::{ + animation::{AnimationTarget, AnimationTargetId}, + prelude::*, +}; -use crate::{deck::Card, menu::UiMessage, setup::CardAnimations, GameState}; +use crate::{deck::Card, menu::UiMessage, setup::AnimationStore, GameState}; pub struct PlayPlugin; @@ -36,21 +39,27 @@ pub(crate) struct SetNumber(pub u8); pub(crate) fn toggle_selected( trigger: Trigger>, mut commands: Commands, - query: Query<&Selected>, - mut players: Query<(&mut AnimationPlayer, &CardAnimations)>, + selections: Query<&Selected>, + mut query: Query<(&Name, &mut AnimationPlayer)>, + store: Res, ) { commands.trigger(UiMessage("".into())); let e = trigger.entity(); - if query.contains(e) { + let (g, ai) = store.store.get("rotate".into()).unwrap(); + let (n, mut ap) = query.get_mut(e).unwrap(); + ap.stop_all(); + if selections.contains(e) { commands.entity(e).remove::(); - info!("stopping animation"); - let (mut player, anims) = players.get_mut(e).unwrap(); - player.stop(anims.rotate); } else { - commands.entity(e).insert(Selected); - info!("starting animation"); - let (mut player, anims) = players.get_mut(e).unwrap(); - player.play(anims.rotate); + ap.play(ai.clone()).repeat(); + commands.entity(e).insert(( + Selected, + g.clone(), + AnimationTarget { + id: AnimationTargetId::from_name(n), + player: e, + }, + )); } } diff --git a/src/setup.rs b/src/setup.rs index 2517578..4b675fd 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -2,8 +2,9 @@ use std::f32::consts::PI; use crate::{deck::*, *}; use bevy::{ - animation::{animated_field, AnimationTarget, AnimationTargetId}, + animation::{animated_field, AnimationTargetId}, prelude::*, + utils::HashMap, }; use view::ViewState; @@ -13,23 +14,25 @@ impl Plugin for SetupPlugin { fn build(&self, app: &mut App) { app.add_systems( OnEnter(GameState::Setup), - (setup_background, setup_cards, setup_camera, start_play).chain(), + ( + setup_background, + setup_cards, + setup_camera, + start_play, + setup_animations, + ) + .chain(), ); } } -#[derive(Component)] -pub(crate) struct CardAnimations { - pub rotate: AnimationNodeIndex, +#[derive(Resource, Default)] +pub(crate) struct AnimationStore { + pub store: HashMap, } /// Setup drawing our cards on the screen -pub(crate) fn setup_cards( - mut commands: Commands, - deck: Res, - mut clips: ResMut>, - mut graphs: ResMut>, -) { +pub(crate) fn setup_cards(mut commands: Commands, deck: Res) { let animation_player = AnimationPlayer::default(); commands .spawn(( @@ -53,40 +56,9 @@ pub(crate) fn setup_cards( }; let order = play::DeckOrder(i as u8); + let animation_player = AnimationPlayer::default(); + let name = Name::new(format!("{}", this_card)); - let animation_components = { - let mut animation = AnimationClip::default(); - let target = AnimationTargetId::from_name(&name); - let curve = AnimatableCurve::new( - animated_field!(Transform::rotation), - AnimatableKeyframeCurve::new( - [0.0, 1.0, 2.0, 3.0, 4.0].into_iter().zip([ - Quat::IDENTITY, - Quat::from_axis_angle(Vec3::Y, PI / 2.), - Quat::from_axis_angle(Vec3::Y, PI / 2. * 2.), - Quat::from_axis_angle(Vec3::Y, PI / 2. * 3.), - Quat::IDENTITY, - ]), - ) - .expect("Rotation animation"), - ); - animation.add_curve_to_target(target, curve); - let animation_handle = clips.add(animation); - let (graph, rotate) = AnimationGraph::from_clip(animation_handle); - let animation_graph_handle = AnimationGraphHandle(graphs.add(graph)); - let indexes = CardAnimations { rotate }; - let target = AnimationTarget { - id: target, - player: parent.parent_entity(), - }; - (animation_graph_handle, indexes, target) - }; - // Card Animations: - // active_card_animation = AnimationClip::default() // simple rotation - // for each (X, Y) in board: - // deck_to_X_Y = AnimationClip::default() // Move from deck to X Y position - // X_Y_to_sets = AnimationClip::default() // Move from X Y position to sets pile - // All need AnimationTarget, AnimationGraphHandle, and AnimationPlayer parent .spawn(( this_sprite, @@ -94,7 +66,7 @@ pub(crate) fn setup_cards( order, Visibility::Hidden, name, - animation_components, + animation_player, )) .observe(play::place_card) .observe(debug::set_debug_card) @@ -105,6 +77,60 @@ pub(crate) fn setup_cards( }); } +fn setup_animations( + mut clips: ResMut>, + mut graphs: ResMut>, + mut commands: Commands, +) { + let mut animation_store = AnimationStore::default(); + + let targets: Vec = Deck::iter_cards() + .map(|c| Name::new(format!("{}", c))) + .map(|n| AnimationTargetId::from_name(&n)) + .collect(); + + // Rotation Animation + { + let mut animation = AnimationClip::default(); + targets.iter().for_each(|target| { + let curve = AnimatableCurve::new( + animated_field!(Transform::rotation), + AnimatableKeyframeCurve::new( + [0.0, 1.0, 2.0, 3.0, 4.0] + .map(|i| i * 5.0) // TODO: Make this tuneable + .into_iter() + .zip([ + Quat::IDENTITY, + Quat::from_axis_angle(Vec3::Z, PI / 2.), + Quat::from_axis_angle(Vec3::Z, PI / 2. * 2.), + Quat::from_axis_angle(Vec3::Z, PI / 2. * 3.), + Quat::IDENTITY, + ]), + ) + .expect("Rotation animation"), + ); + animation.add_curve_to_target(*target, curve); + }); + let animation_handle = clips.add(animation); + let (graph, animation_index) = AnimationGraph::from_clip(animation_handle); + let graph_handle = AnimationGraphHandle(graphs.add(graph)); + animation_store + .store + .insert("rotate".into(), (graph_handle, animation_index)); + } + + commands.insert_resource(animation_store); + // Card Animations: + // active_card_animation = AnimationClip::default() // simple rotation + // for each (X, Y) in board: + // deck_to_X_Y = AnimationClip::default() // Move from deck to X Y position + // X_Y_to_sets = AnimationClip::default() // Move from X Y position to sets pile + // All need AnimationTarget, AnimationGraphHandle, and AnimationPlayer + // TODO: (example: https://bevyengine.org/examples/animation/animated-transform/) + // Button Animations: + // active_button_animation = AnimationClip::default() // color and size +} + /// Setup our camera to view cardson the screen pub(crate) fn setup_camera(mut commands: Commands) { commands.spawn(( @@ -140,9 +166,3 @@ pub(crate) fn start_play( game_state.set(GameState::Main); view_state.set(ViewState::Menu); } - -fn setup_animations(mut commands: Commands) { - // TODO: (example: https://bevyengine.org/examples/animation/animated-transform/) - // Button Animations: - // active_button_animation = AnimationClip::default() // color and size -}