Executing a list of animations

I’m trying to get my feet wet with jME3-based animation. I have a specific list of animations I want a ninja (the NInja.mesh.xml that ships with the test-data jar) to execute. When I run:

public class Simulator extends SimpleApplication implements AnimEventListener {
    private AnimChannel animationChannel;
    private AnimControl animationController;
    private Node avatar;

    // Constructor, getters/setters, etc.

    @Override
    public void simpleInitApp() {
        viewPort.setBackgroundColor(ColorRGBA.LightGray);
        DirectionalLight directionalLight = new DirectionalLight();
        rootNode.addLight(directionalLight);

        avatar = (Node)assetManager.loadModel("models/Ninja.mesh.xml");
        avatar.localScale = 0.025f;
        rootNode.attachChild(avatar);
        animationController = avatar.getControl(AnimControl);
        animationController.addListener(this);
        animationChannel = animationController.createChannel();

        flyCam.setDragToRotate(true);

        setDisplayFps(false);
        setDisplayStatView(false);

        // Start the animation...
        animationChannel.setAnim("Walk", 0.5f);
        animationChannel.setAnim("Backflip", 0.5f);
        animationChannel.setAnim("Walk", 0.5f);
        animationChannel.setAnim("Crouch", 0.5f);
        animationChannel.setAnim("Attack2", 0.5f);
        animationChannel.setAnim("Walk", 0.5f);
    }

    @Override
    public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
        channel.setAnim('Idle1');
        channel.setLoopMode(LoopMode.DontLoop);
        channel.setSpeed(1f);
    }

    @Override
    public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
        // No-op for now
    }
}

I get the ninja rendering to the screen, but the screen freaks out for a second and then the ninja starts idling (assuming the Idle1 position). I think what is happening is that the list of animations are all basically happening at the same time (which explains the screen freaking out for a split second) and then the onAnimCycleDone method takes over and places the ninja in an idle animation.

How can I get my ninja to smoothly, slowly, execute my list of animations?

Well, you easily get access to all names of the model with the method: getAnimationNames() from the AnimControl class. Store this list and go through it, step by step, everytime a animation is finished. You might define a counter globally.

I highly recommend to have a look at the tutorials (wiki) again ! Also have a look at certain javadocs like this one: AnimControl doc

Thanks @Domenic, however I don’t think you undertand what I’m trying to do here!

I already have the specific list of animations I want the avatar to do/execute. Specifically, from the code above, I want the ninja to:

  1. Walk for, say, 3 seconds
  2. Do a backflip over the course of, say, 1 second
  3. Walk for another 3 seconds
  4. Crouch down for 5 seconds
  5. Do whatever “Attack2” is for 2 seconds
  6. Walk again for another 3 seconds
  7. Remain in Idle1 position until I terminate the program (this isn’t an actual game, I’m just playing around with animation and the jME3 framework)

How can I accomplish all that?!? Thanks again!

Your current code says “run all of these animations NOW”. You need to wait three seconds then execute the next one… then 1 second and execute the next… basically exactly as your post says. Not do this, do this, do this… all instantly.

Thanks @pspeed, so do you mean actually placing Thread.sleep(...) calls in between the animations? Something like:

animationChannel.setAnim("Walk", 0.5f);
Thread.sleep(3 * 1000);
animationChannel.setAnim("Backflip", 0.5f);
Thread.sleep(2 * 1000);
// etc.

Or something else? A code example, even pseudo-code example, would be very helpful here! Thanks again!

No. You will block the whole render thread that way.

Your code is called many times per second to update things. Count time. Do things at specific times.

DO ALL THE TUTORIALS.

Thanks again @pspeed, however I am quite sure that simpleInitApp is only called once at app startup. Is this not true? If so, how is simpleInitApp different than the game loop?

Also I have searched the tutorials high and low for any kind of reference to “time counting” and can’t find any. Is there a magical tutorial that you know of that I have somehow missed?!?

It sounds like you are advocating something along the lines of:

private static int GLOBAL_TIME = 0;

public void gameLoop() {
    GLOBAL_TIME++;

    if(GLOBAL_TIME == MAGICAL_TIME_TO_START_WALKING) {
        animationController.setAnim("Walk", 0.5f);
    } else if(GLOBAL_TIME == MAGICAL_TIME_TO_BACKFLIP) {
        animationController.setAnim("Backflip", 0.5f);
    } // etc.
}

But again, I see no such reference to either time counting in the tutorials, nor to orchestrating multiple animations one after the other. I am more than happy to read the docs, but can’t read what I can’t find!!! Thanks again!

As pspeed said, this would block all. You could set a timer variable (ie: float time) and increment it by the tpf (time += tpf) on every game loop (with this you can track the elapsed time in seconds). To know how, just follow the given suggestions of doing the beginners tutorials. They are quite easy and well explained.

Thanks @NemesisMate but like I stated above, I can find no reference to time counting or animation orchestration in those tutorials. Can you please kindly provide a link to the tutorial that covers these topics? Thanks again!

Do tutorial 1.
Then do tutorial 2… and so on until you get to tutorial 4:
https://wiki.jmonkeyengine.org/doku.php/jme3:beginner:hello_main_event_loop

Hm… I think you are blinding yourself. You don’t need to see an exact tutorial but use the knowledge given there and use it to your purposes. In the loop tutorial: https://wiki.jmonkeyengine.org/doku.php/jme3:beginner:hello_main_event_loop you can see how the loop is used and how the tpf is used.

A fast example on how to use in this case:

    float time;

    @Override
    public void simpleUpdate(float tpf) {
        // Increment timer
        time += tpf;

        // Check time
        if(time > 3) {
            // Set your animation
        }
    }

Normally, a tutorial is more than simple references. If you do them you’ll learn things that you wont if you just read them. Again, give them a try ;).

My advice would be to do the tutorials

And after doing the tutorials, you could but your code to start the next animation in an AnimEventListener that is attached to your AnimControl. By that, you do not have to worry about the exact durations of the animations.