Using animations for card rotation!

Now to add deal and discard animations...
main
Elijah Voigt 1 year ago
parent d7fc9a12bf
commit 41bbca55cc

@ -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; pub struct PlayPlugin;
@ -36,21 +39,27 @@ pub(crate) struct SetNumber(pub u8);
pub(crate) fn toggle_selected( pub(crate) fn toggle_selected(
trigger: Trigger<Pointer<Click>>, trigger: Trigger<Pointer<Click>>,
mut commands: Commands, mut commands: Commands,
query: Query<&Selected>, selections: Query<&Selected>,
mut players: Query<(&mut AnimationPlayer, &CardAnimations)>, mut query: Query<(&Name, &mut AnimationPlayer)>,
store: Res<AnimationStore>,
) { ) {
commands.trigger(UiMessage("".into())); commands.trigger(UiMessage("".into()));
let e = trigger.entity(); 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::<Selected>(); commands.entity(e).remove::<Selected>();
info!("stopping animation");
let (mut player, anims) = players.get_mut(e).unwrap();
player.stop(anims.rotate);
} else { } else {
commands.entity(e).insert(Selected); ap.play(ai.clone()).repeat();
info!("starting animation"); commands.entity(e).insert((
let (mut player, anims) = players.get_mut(e).unwrap(); Selected,
player.play(anims.rotate); g.clone(),
AnimationTarget {
id: AnimationTargetId::from_name(n),
player: e,
},
));
} }
} }

@ -2,8 +2,9 @@ use std::f32::consts::PI;
use crate::{deck::*, *}; use crate::{deck::*, *};
use bevy::{ use bevy::{
animation::{animated_field, AnimationTarget, AnimationTargetId}, animation::{animated_field, AnimationTargetId},
prelude::*, prelude::*,
utils::HashMap,
}; };
use view::ViewState; use view::ViewState;
@ -13,23 +14,25 @@ impl Plugin for SetupPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems( app.add_systems(
OnEnter(GameState::Setup), 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)] #[derive(Resource, Default)]
pub(crate) struct CardAnimations { pub(crate) struct AnimationStore {
pub rotate: AnimationNodeIndex, pub store: HashMap<String, (AnimationGraphHandle, AnimationNodeIndex)>,
} }
/// Setup drawing our cards on the screen /// Setup drawing our cards on the screen
pub(crate) fn setup_cards( pub(crate) fn setup_cards(mut commands: Commands, deck: Res<Deck>) {
mut commands: Commands,
deck: Res<Deck>,
mut clips: ResMut<Assets<AnimationClip>>,
mut graphs: ResMut<Assets<AnimationGraph>>,
) {
let animation_player = AnimationPlayer::default(); let animation_player = AnimationPlayer::default();
commands commands
.spawn(( .spawn((
@ -53,40 +56,9 @@ pub(crate) fn setup_cards(
}; };
let order = play::DeckOrder(i as u8); let order = play::DeckOrder(i as u8);
let animation_player = AnimationPlayer::default();
let name = Name::new(format!("{}", this_card)); 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 parent
.spawn(( .spawn((
this_sprite, this_sprite,
@ -94,7 +66,7 @@ pub(crate) fn setup_cards(
order, order,
Visibility::Hidden, Visibility::Hidden,
name, name,
animation_components, animation_player,
)) ))
.observe(play::place_card) .observe(play::place_card)
.observe(debug::set_debug_card) .observe(debug::set_debug_card)
@ -105,6 +77,60 @@ pub(crate) fn setup_cards(
}); });
} }
fn setup_animations(
mut clips: ResMut<Assets<AnimationClip>>,
mut graphs: ResMut<Assets<AnimationGraph>>,
mut commands: Commands,
) {
let mut animation_store = AnimationStore::default();
let targets: Vec<AnimationTargetId> = 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 /// Setup our camera to view cardson the screen
pub(crate) fn setup_camera(mut commands: Commands) { pub(crate) fn setup_camera(mut commands: Commands) {
commands.spawn(( commands.spawn((
@ -140,9 +166,3 @@ pub(crate) fn start_play(
game_state.set(GameState::Main); game_state.set(GameState::Main);
view_state.set(ViewState::Menu); 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
}

Loading…
Cancel
Save