Animation example
parent
28890a870b
commit
be7627e9c0
Binary file not shown.
Binary file not shown.
@ -0,0 +1,163 @@
|
||||
use bevy::{
|
||||
animation::{animated_field, AnimationTarget, AnimationTargetId},
|
||||
input::{keyboard::KeyboardInput, ButtonState},
|
||||
prelude::*,
|
||||
utils::HashMap,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_systems(Startup, init)
|
||||
.add_systems(Update, switch)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
struct AnimationStore(HashMap<String, (AnimationGraphHandle, AnimationNodeIndex)>);
|
||||
|
||||
fn init(
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
mut animations: ResMut<Assets<AnimationClip>>,
|
||||
mut graphs: ResMut<Assets<AnimationGraph>>,
|
||||
) {
|
||||
commands.spawn(Camera2d);
|
||||
|
||||
commands.spawn((
|
||||
Text2d("Press 1/2/3 to trigger animation".into()),
|
||||
Node {
|
||||
top: Val::Px(-50.0),
|
||||
height: Val::Percent(100.0),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
|
||||
let mut hash_map = HashMap::new();
|
||||
{
|
||||
let mut a = AnimationClip::default();
|
||||
let animatable_curve = AnimatableCurve::new(
|
||||
animated_field!(Transform::translation),
|
||||
UnevenSampleAutoCurve::new([0.0, 1.0, 2.0, 3.0, 4.0].into_iter().zip([
|
||||
Vec3::new(200.0, 200.0, 0.0),
|
||||
Vec3::new(-200.0, 200.0, 0.0),
|
||||
Vec3::new(-200.0, -200.0, 0.0),
|
||||
Vec3::new(200.0, -200.0, 0.0),
|
||||
// in case seamless looping is wanted, the last keyframe should
|
||||
// be the same as the first one
|
||||
Vec3::new(200.0, 200.0, 0.0),
|
||||
]))
|
||||
.expect("should be able to build translation curve because we pass in valid samples"),
|
||||
);
|
||||
a.add_curve_to_target(
|
||||
AnimationTargetId::from_name(&Name::new("Circle")),
|
||||
animatable_curve,
|
||||
);
|
||||
let (graph, animation_index) = AnimationGraph::from_clip(animations.add(a));
|
||||
let graph_handle = AnimationGraphHandle(graphs.add(graph));
|
||||
hash_map.insert("Box".into(), (graph_handle, animation_index));
|
||||
};
|
||||
{
|
||||
let mut a = AnimationClip::default();
|
||||
let animatable_curve = AnimatableCurve::new(
|
||||
animated_field!(Transform::translation),
|
||||
UnevenSampleAutoCurve::new([0.0, 1.0, 2.0].into_iter().zip([
|
||||
Vec3::new(200.0, 200.0, 0.0),
|
||||
Vec3::new(-200.0, -200.0, 0.0),
|
||||
Vec3::new(200.0, 200.0, 0.0),
|
||||
]))
|
||||
.expect("should be able to build translation curve because we pass in valid samples"),
|
||||
);
|
||||
a.add_curve_to_target(
|
||||
AnimationTargetId::from_name(&Name::new("Circle")),
|
||||
animatable_curve,
|
||||
);
|
||||
let (graph, animation_index) = AnimationGraph::from_clip(animations.add(a));
|
||||
let graph_handle = AnimationGraphHandle(graphs.add(graph));
|
||||
hash_map.insert("Diag1".into(), (graph_handle, animation_index));
|
||||
};
|
||||
{
|
||||
let mut a = AnimationClip::default();
|
||||
let animatable_curve = AnimatableCurve::new(
|
||||
animated_field!(Transform::translation),
|
||||
UnevenSampleAutoCurve::new([0.0, 1.0, 2.0].into_iter().zip([
|
||||
Vec3::new(-200.0, 200.0, 0.0),
|
||||
Vec3::new(200.0, -200.0, 0.0),
|
||||
// in case seamless looping is wanted, the last keyframe should
|
||||
// be the same as the first one
|
||||
Vec3::new(-200.0, 200.0, 0.0),
|
||||
]))
|
||||
.expect("should be able to build translation curve because we pass in valid samples"),
|
||||
);
|
||||
a.add_curve_to_target(
|
||||
AnimationTargetId::from_name(&Name::new("Circle")),
|
||||
animatable_curve,
|
||||
);
|
||||
let (graph, animation_index) = AnimationGraph::from_clip(animations.add(a));
|
||||
let graph_handle = AnimationGraphHandle(graphs.add(graph));
|
||||
hash_map.insert("Diag2".into(), (graph_handle, animation_index));
|
||||
};
|
||||
|
||||
let store = AnimationStore(hash_map);
|
||||
commands.insert_resource(store);
|
||||
|
||||
let shape = meshes.add(Circle::new(50.0));
|
||||
let material = materials.add(Color::WHITE);
|
||||
commands.spawn((
|
||||
Mesh2d(shape),
|
||||
MeshMaterial2d(material),
|
||||
Name::new("Circle"),
|
||||
AnimationPlayer::default(),
|
||||
));
|
||||
}
|
||||
|
||||
fn switch(
|
||||
mut commands: Commands,
|
||||
mut evr_kbd: EventReader<KeyboardInput>,
|
||||
mut query: Query<(Entity, &Name, &mut AnimationPlayer)>,
|
||||
store: Res<AnimationStore>,
|
||||
) {
|
||||
evr_kbd
|
||||
.read()
|
||||
.filter(|ev| ev.state == ButtonState::Pressed)
|
||||
.for_each(|ev| match ev.key_code {
|
||||
KeyCode::Digit1 => {
|
||||
let (g, ai) = store.0.get("Box".into()).unwrap();
|
||||
let (e, n, mut ap) = query.single_mut();
|
||||
ap.stop_all().play(ai.clone());
|
||||
commands.entity(e).insert((
|
||||
g.clone(),
|
||||
AnimationTarget {
|
||||
id: AnimationTargetId::from_name(n),
|
||||
player: e,
|
||||
},
|
||||
));
|
||||
}
|
||||
KeyCode::Digit2 => {
|
||||
let (g, ai) = store.0.get("Diag1".into()).unwrap();
|
||||
let (e, n, mut ap) = query.single_mut();
|
||||
ap.stop_all().play(ai.clone());
|
||||
commands.entity(e).insert((
|
||||
g.clone(),
|
||||
AnimationTarget {
|
||||
id: AnimationTargetId::from_name(n),
|
||||
player: e,
|
||||
},
|
||||
));
|
||||
}
|
||||
KeyCode::Digit3 => {
|
||||
let (g, ai) = store.0.get("Diag2".into()).unwrap();
|
||||
let (e, n, mut ap) = query.single_mut();
|
||||
ap.stop_all().play(ai.clone());
|
||||
commands.entity(e).insert((
|
||||
g.clone(),
|
||||
AnimationTarget {
|
||||
id: AnimationTargetId::from_name(n),
|
||||
player: e,
|
||||
},
|
||||
));
|
||||
}
|
||||
_ => (),
|
||||
});
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
TODO:
|
||||
* "New Game" button
|
||||
* Print "no set"/"too many cards" alert
|
||||
* Guarentee there is always a set
|
||||
* Better shuffling
|
||||
* Make "set" button visually interesting when 3 cards selected
|
||||
* Use Animation for rotating cards
|
||||
* Animate cards deck -> board
|
||||
* Animate cards deck -> set-pile
|
||||
|
||||
Later:
|
||||
* View all cards with some indication of in-set
|
||||
* Music!
|
||||
* Music! (w/ sam)
|
||||
* Make button(s) look pretty
|
||||
|
||||
Loading…
Reference in New Issue