Giter VIP home page Giter VIP logo

Comments (7)

bmanturner avatar bmanturner commented on June 29, 2024 1

I've chosen to use benimator (at the very least in it's current form) in a game I'm working on. I would be glad to give feedback on any design ideas you come up with regarding switching between animations. Thanks Jonathan

from benimator.

bmanturner avatar bmanturner commented on June 29, 2024 1

Yeah I dig. Aside from those systems the rest of the code in the repo is agnostic. Worth a look!

I put my code here because I’ve seen this issue linked to in bevy discords more than once so I think it might help people that come here and are wondering about implementing that functionality.

from benimator.

jcornaz avatar jcornaz commented on June 29, 2024

Yeah, definitely, that sounds like a good idea.

Maybe can you share more details about your current use-case? So that I can try thinking about an API.

from benimator.

bmanturner avatar bmanturner commented on June 29, 2024

So imagine you're making a tile-based game. You're gonna be swapping the animations a lot.

  1. standing still, idle_down on repeat
  2. walking left, swap idle_down for walk_left on repeat
  3. reach destination tile, swap walk_left for idle_left on repeat, etc

In some cases, like an attack, you'll play the attack animation once and then return to the animation you were playing before you attacked.

Here's some musing:

An AnimationChain and AnimationChainBuilder

let animation_chain = AnimationChainBuilder::new()
                                        .begins_with(attack_animation)
                                        .then(stow_weapon_animation)
                                        .then(idle_animation);

And then that allows you to expand the AnimationChainBuilder to support options other than begins_with and then,
and have maybe play_n_times(3, animation), then_in_reverse(animation_to_play_backwards) or more.

Or maybe something like iyes_loopless where you specify the animation to run given a particular animation state enum value.

let animation_states = AnimationStatesBuilder::new()
                                        .run_in_state(EntityAnimState::IdleDown, idle_down_animation)
                                        .run_in_state(EntityAnimState::WalkLeft, walk_left_animation)
                                        .run_in_state(EntityAnimState::AttackLeft, attack_left_animation);

let animation_state = State::new(EntityAnimState::IdleDown, animation_chain);

animation_state.now(EntityAnimState::WalkLeft); // change animation

animation_state.now(EntityAnimState::AttackLeft).next(EntityAnimState::IdleLeft);

I hope this helps! Let me know if you want to chat about it

from benimator.

jcornaz avatar jcornaz commented on June 29, 2024

Yes, it helps, thanks. I will think more about it and try to come up with an initial design.

from benimator.

bmanturner avatar bmanturner commented on June 29, 2024

Using bevy-simple-state-machine as a reference I was able to implement something that works for benimator over the weekend

Here's the crux of the code. Also, state_machine.animation_finished() checks benimator to see if a Once animation has finished

pub fn check_animation_transitions(
    mut state_machines_query: Query<(Entity, &mut AnimationStateMachine)>,
    mut event_writer: EventWriter<TransitionEndedEvent>,
    animations: Res<Assets<Animation>>,
) {
    for (entity, mut state_machine) in &mut state_machines_query {
        if let Some(current_state) = state_machine.current_state() {
            if current_state.interruptible || state_machine.animation_finished() {
                for transition in state_machine.transitions_from_current_state() {
                    if transition.trigger.evaluate(&state_machine.variables) {
                        if let Some(next_state) =
                            state_machine.get_state(transition.end_state.unwrap())
                        {
                            println!("triggering {}", transition);
                            state_machine.current_state = next_state.name;

                            // Get new animation and restart benimator with it
                            let animation = match animations.get(&next_state.base_animation) {
                                Some(anim) => anim,
                                None => continue,
                            };
                            state_machine.base_frame.reset();
                            state_machine
                                .base_frame
                                .update(animation, Duration::from_millis(0));

                            // emit event that the transition has completed
                            event_writer.send(TransitionEndedEvent {
                                entity,
                                origin: current_state.state_ref(),
                                end: transition.end_state,
                            });
                        }
                    }
                }
            }
        }
    }
}

pub fn update_animations(
    time: Res<Time>,
    mut state_machines_query: Query<(&mut AnimationStateMachine, &mut TextureAtlasSprite)>,
    animations: Res<Assets<Animation>>,
) {
    for (mut state_machine, mut sprite_texture) in &mut state_machines_query {
        if let Some(current_state) = state_machine.current_state() {
            // Get animation and update it
            let animation = match animations.get(&current_state.base_animation) {
                Some(anim) => anim,
                None => continue,
            };

            state_machine.base_frame.update(animation, time.delta());

            sprite_texture.index = state_machine.base_frame.frame_index();
        }
    }
}

from benimator.

jcornaz avatar jcornaz commented on June 29, 2024

Thanks @bmanturner, I'll have to look into this.

Right of the bat, I would like to make sure you're aware that benimator is no longer a bevy plugin. The bevy systems you just shared are still interesting to look at, and it is indeed worthwhile to think about how usage from bevy would look like. I will definitely study what you shared. I just want to make sure you're aware I am looking for an API that is agnostic of bevy.

from benimator.

Related Issues (18)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.