bevy_sprite_animation
A simple 2d sprite animation plugin for the Bevy game engine.
Anyone is welcome to make suggestion and corrections to this repository, typographic and otherwise!
This is more or less a copy of Aarthificial's Reanimator for Unity but for Bevy of course.
Here is a video explaining how the example works.
Here is a video going over what is new in 0.4
subject to change with feedback
Version
0.3 = Bevy 0.7 avalable as 0.7 branch
0.3.1 = Bevy 0.8 avalable as 0.8 branch
0.3.1 = Bevy 0.10 avalable as 0.10 branch
0.3.2 = Bevy 0.11 avalable as master branch
0.4 = Bevy 0.11 avalable as v0.4 branch
Usage
Add AnimationPlugin::<usize> and other systems to app
the usize is the max nodes a single path can take
this is to stop loops from locking up frames indefinitly
fn main() {
App::build()
.add_plugin(AnimationPlugin::<10>)
.add_startup_system(add_nodes.system())
.add_startup_system(add_animator.system())
.add_system(update_animator)
.add_system(read_animator)
.register_type::<MatchNode<ZState>>()
.run()
}
Add nodes to Assets<AnimationNode> resurce
fn add_nodes(
asset_server : Res<AssetServer>,
mut nodes : ResMut<Assets<AnimationNode>>,
) {
let mut handles = Vec::new();
for i in 0..10 {
handles.push(asset_server.load(format!("SomeSprite_{}", i));
}
let node = Box::new(IndexNode::new("New Node", &handles));
let node_handle = nodes.add_node(node);
let node_id = NodeId::from_handle(node_handle);
nodes.set(NodeId::from_name("Node Name"), node);
nodes.set(NodeId::from_u64("Node Name"), node);
let from_file = asset_server.load("example.node");
node_tree.load("example.nodetree");
}
Create an entity with an AnimationState and StartNode
the start node it used to pick the entry point each frame
fn add_animator(
mut commands: Commands,
) {
let mut state = AnimationState::default();
start.set_attribute(Attribute::FlipX, true);
start.set_attribute(Attribute::new_attribute("custom_attribute"), "cat");
start.set_attribute(Attribute::new_attribute_id("specil_attribute"), 5);
state.set_temporary(Attribute::new_index("Idel"));
state.set_persistent(Attribute::new_index_id("Idel"));
commands.spwan((
SpriteBundle::default(),
state,
StartNode::from_u64(0),
))
}
Change the state of the AnimationState to control what frame is picked next update
fn update_animation_state(
mut animatiors : Query<&mut AnimationState>,
input : Res<Input<KeyCode>>,
) {
if input.just_pressed(KeyCode::Space){
for mut animatior in animatiors.iter(){
start.set_attribute(Attributes::new_attribute("custom_attribute"), "dog");
}}
}
Get an attribute from an AnimationState to create logic that happens only on special frames
fn read_animation_state(
animatiors : Query<(Entity, &AnimationState)>,
) {
for (entity, animatior) in animatiors.iter(){
if let Ok(ground_type) = animatior.get_attribute::<GroundType>(Attributes::new_attribute("step")) {
println!("{} is on a frame where you should play the sound of someone stepping on {}", entity, ground_type);
}
}
}
Check if an attribute from AnimationState changed this frame
fn read_animation_change(
animatiors : Query<(Entity, &AnimationState)>,
dogs: Query<&mut Dogs>,
) {
for (entity, animatior) in animatiors.iter(){
if animatior.changed(Attributes::new_attribute("barke")) {
println!("{} is on a frame where you should play a barke sound effect", entity);
}
}
for (entity, animatior) in animatiors.iter(){
if animatior.changed(Attributes::new_attribute("dog_breed")) {
let dog = dogs.get(animatior.get_attribute::<Entity>(Attributes::new_attribute("dog_breed")));
println!("{} is on a frame where you should play a barke sound effect", entity);
}
}
}