Chaining Animations?

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Re: Chaining Animations?

Post by serengeor »

Seriously just put some effort in it yourself and write what you need. Sudi gave you some code that is close to your problem you just need to modify it a bit to get what you want.
Working on game: Marrbles (Currently stopped).
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Re: Chaining Animations?

Post by sudi »

thoma91 wrote:Thank you Sudi for your example, but it's still not, what I'm looking for.
This changes animations by pressing keys.
I need automatic change, after one animation is finished/played.
The problem is, when I set up a second animation, the first one gets ignored.
Even if there's an if condition before it, like this:

Code: Select all

 
...
 
So the first animation has to be played, before the second could start, but only the second one is played.
Sudi, and others: could you help me solving this?
Did you even read the code at all i posted?
Just as an example you could add a next field to each animation and when set it plays this next animation when the animation finishes.....
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
shadowslair
Posts: 758
Joined: Mon Mar 31, 2008 3:32 pm
Location: Bulgaria

Re: Chaining Animations?

Post by shadowslair »

thoma91 wrote:So the first animation has to be played, before the second could start, but only the second one is played.
Sudi, and others: could you help me solving this?
This is a disrespect for the helpers. Sudi has spent probably about half an hour or more to create a simplified and easy to understand working example especially for you and you seem not to have spent even 15 minutes testing it. From your explanations the code does exactly what you`re trying to do. Please, soon or later you`ll need to put some time and efforts on your side, and there`s just no way around that. Of course it`s ok to ask for help, but if you wanna your project to keep going, you`ll need to slowly start learning.
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
thoma91
Posts: 28
Joined: Tue Aug 09, 2011 10:00 am

Re: Chaining Animations?

Post by thoma91 »

Sorry guys, it was my fault. I'm not an expert, so I just took a short look over the code, then I quickly tried it.
I thought that it's certainly good, so I have time to understand it later. Then I saw that the animation-changes triggered by pressing keys, and I thought that Sudi may have misunderstood my problem.
Now I see that was my mistake, sorry for that, and thanks again for your spent time and efforts! Image
Sudi wrote: Just as an example you could add a next field to each animation and when set it plays this next animation when the animation finishes.....
Yes, it works of course.

Now I'm trying to simplify your code for at least one and a half hour, but I can achieve only, what I've done before..
You may ask why am I doing this, but my program structure is much more simplier than yours (only one file, main.cpp and only the main function,the shooting function and the eventreceiver so far), and I want to keep that form to be easily overviewed by beginners like me.
Here's what I tried:
In Shooting function, after checking if the enemy takes hit, I want to call the new functions like this:

Code: Select all

 
playanimation(1);  // takes hit
onanimationend();  // I want to end that animation
playanimation(2);  // walks
 
playanimation:

Code: Select all

 
void playanimation(int n)
{
        if(n==1)
        {
                if(!animationrunning)   // animationrunning is a global variable, starting value is false
                {
                setanimation(1);
                }
                else
                {
                //hasnext=true;         // hasnext is a global variable, starting value is false
                //setanimation(2);      
                }
        }
        else if(n==2)
        {
                if(!animationrunning)
                {
                setanimation(2);
                }
                else
                {
                //
                }
        }
}
 
setanimation:

Code: Select all

 
void setanimation(int n)
{
        if(n==1)
        {
        node->setFrameLoop(272,288);
        node->setLoopMode(false);
        animationrunning=true;
        }
        else if(n==2)
        {
        node->setFrameLoop(0,24);
        node->setLoopMode(true);
        animationrunning=true;
        }
}
 
onanimationend:

Code: Select all

 
void onanimationend()
{
        if(animationrunning)
        {
        node->setAnimationEndCallback(0);       // I want to end that animation
        animationrunning=false;
        }
        else
        {
        
        }
 
}
 
I know this code misses a lot from yours, but I tried a lot of things, but I REALLY can't get this to work in this way :cry:
I'm completely confused, embittered, I can't proceed in my work for days now because of this!
It could be so easy if these frameloops could go into a queue: if one finished, the others start, why can't be like this?
I think you're already tired of me, but if someone have pity on me, please help. Thank you..
shadowslair
Posts: 758
Joined: Mon Mar 31, 2008 3:32 pm
Location: Bulgaria

Re: Chaining Animations?

Post by shadowslair »

See, the heart of the code is the animation end callback you add to the node, which, when added, Irrlicht calls it internally when an animation has ended. The main class is derived from it:

Code: Select all

 class CAnimationController : public irr::scene::IAnimationEndCallBack
it overwrites its only method:

Code: Select all

void OnAnimationEnd(irr::scene::IAnimatedMeshSceneNode* node);
which gets called as I said, when an animation has ended. So, basically whatever you do, make sure you have this in your code, although I recommend you to not change the classes and file structures, just slightly modify them. As I already said, try to get used to the "good programming" style, which Sudi was very polite to give. Coding in one big main.cpp is definitely a bad practice for anything that`s not a short example or tutorial as in the Irrlicht case.

PS: Try to follow the irrlicht coding style as you learn, or you`ll get some bad habits, which will be more difficult to work with in the future.

Code: Select all

void onanimationend()
{
        if(animationrunning)
        {
        node->setAnimationEndCallback(0);       // I want to end that animation
        animationrunning=false;
        }
        else
        {
       
        }
 
}
will be better

Code: Select all

void OnAnimationEnd() // you cannot simply change this name, because Irrlicht calls this function by exactly this name
{
        if (animationRunning) // or animation_running, I myself would call it maybe IsAnimRunning or sth alike
        {
            node->setAnimationEndCallback(0); // the callback won`t be used for a while, nullify it
            animationRunning = false;
        }
        else
        {
        }
}
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Re: Chaining Animations?

Post by sudi »

@thoma91
I think the big problem here is that you don't understand at all what my code was doing and when it was doing it and thats bc you know to little about programming structures and even the language. You should really get some good tutorial about classes and certain structures.Bc for example the OnAnimationEnd is called from inside irrlicht not from myself. its an interface callback which is triggered when the last frame of animation is reached. The example code you showed assumes that code is not running in a straight line of time and that irrlicht is rendering in a different thread maybe?
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Re: Chaining Animations?

Post by serengeor »

Sudi wrote:@thoma91
I think the big problem here is that you don't understand at all what my code was doing and when it was doing it and thats bc you know to little about programming structures and even the language. You should really get some good tutorial about classes and certain structures.Bc for example the OnAnimationEnd is called from inside irrlicht not from myself. its an interface callback which is triggered when the last frame of animation is reached. The example code you showed assumes that code is not running in a straight line of time and that irrlicht is rendering in a different thread maybe?
oh really?? :shock:
I thought it just updates the animations in the smgr->drawAll() (not exactly in it but rather w/e it calls to do so).
Working on game: Marrbles (Currently stopped).
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Re: Chaining Animations?

Post by sudi »

serengeor wrote:
Sudi wrote:@thoma91
I think the big problem here is that you don't understand at all what my code was doing and when it was doing it and thats bc you know to little about programming structures and even the language. You should really get some good tutorial about classes and certain structures.Bc for example the OnAnimationEnd is called from inside irrlicht not from myself. its an interface callback which is triggered when the last frame of animation is reached. The example code you showed assumes that code is not running in a straight line of time and that irrlicht is rendering in a different thread maybe?
oh really?? :shock:
I thought it just updates the animations in the smgr->drawAll() (not exactly in it but rather w/e it calls to do so).
What?

anyways

@thoma91
I just improved the animationController a bit more.

PS: make sure to check out key 'R'

CAnimationController.h

Code: Select all

 
#ifndef CANIMATIONCONTROLLER_H
#define CANIMATIONCONTROLLER_H
 
#include <IAnimatedMeshSceneNode.h>
#include <irrMap.h>
 
class CAnimationController : public irr::scene::IAnimationEndCallBack
{
public:
    struct Animation
    {
        Animation()
        {
            name = "";
            start = 0;
            end = 1;
            looping = false;
        }
        Animation(const irr::c8* n, const irr::u32& s, const irr::u32& e, const bool& loop)
        {
            name = n;
            start = s;
            end = e;
            looping = loop;
        }
        Animation(const Animation& other)
        {
            name = other.name;
            start = other.start;
            end = other.end;
            looping = other.looping;
        }
 
        irr::core::stringc name;
        irr::u32 start;
        irr::u32 end;
        bool looping;
    };
 
    CAnimationController();
    virtual ~CAnimationController();
 
    //!Set the node that should be controlled
    void setAnimatedMeshNode(irr::scene::IAnimatedMeshSceneNode* node);
 
    //!Add an animation to the controller
    void addAnimation(const irr::c8* name, const irr::u32& start, const irr::u32& end, const bool& loop = false);
 
    //!Plays an animation when the previous ones finished. Animations chain up
    void playAnimation(const irr::c8* name);
    //!Plays this animation directly after the last one and clears the animation chain
    void playAnimationNext(const irr::c8* name);
    //!Plays this animation directly and clears the animation chain
    void playAnimationNow(const irr::c8* name);
 
    void OnAnimationEnd(irr::scene::IAnimatedMeshSceneNode* node);
protected:
    void setAnimation(const Animation& anim);
 
    irr::core::map<irr::core::stringc, Animation> animations;
    Animation currentAnimation;
    irr::core::array<Animation> nextAnimation;
    irr::scene::IAnimatedMeshSceneNode*animatedNnode;
    bool animationRunning;
};
 
#endif // CANIMATIONCONTROLLER_H
 
CAnimationController.cpp

Code: Select all

 
/*
  Copyright (C) 2011 Daniel Sudmann
 
  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.
 
  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:
 
  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
 
  Daniel Sudmann suddani@googlemail.com
*/
#include "CAnimationController.h"
 
CAnimationController::CAnimationController()
{
    animatedNnode = 0;
    animationRunning = false;
}
 
CAnimationController::~CAnimationController()
{
    if (animatedNnode)
    {
        animatedNnode->setAnimationEndCallback(0);
        animatedNnode->drop();
    }
    animatedNnode = 0;
}
 
void CAnimationController::OnAnimationEnd(irr::scene::IAnimatedMeshSceneNode *node)
{
    animationRunning = false;
    if ((nextAnimation.size() > 0 || currentAnimation.looping) && animatedNnode)
    {
        if (nextAnimation.size() > 0 )
        {
            setAnimation(nextAnimation[0]);
            nextAnimation.erase(0);
        }
        else
            setAnimation(currentAnimation);
    }
}
 
void CAnimationController::addAnimation(const irr::c8 *name, const irr::u32 &start, const irr::u32 &end, const bool& loop)
{
    animations[name] = Animation(name, start, end, loop);
}
 
void CAnimationController::setAnimatedMeshNode(irr::scene::IAnimatedMeshSceneNode *node)
{
    if (animatedNnode == node)
        return;
 
    nextAnimation.clear();
    animationRunning = false;
 
    if (animatedNnode)
    {
        animatedNnode->setAnimationEndCallback(0);
        animatedNnode->drop();
    }
 
    animatedNnode = node;
 
    if (animatedNnode)
    {
        animatedNnode->grab();
 
        currentAnimation.start = 0;
        currentAnimation.end = animatedNnode->getEndFrame(); //There is no way to get the actual frame count...
 
        animatedNnode->setAnimationEndCallback(this);
    }
}
 
void CAnimationController::playAnimation(const irr::c8 *name)
{
    if (animations.find(name) == 0)
        return;
 
    if (animationRunning)
    {
        nextAnimation.push_back(animations[name]);
    }
    else
        setAnimation(animations[name]);
}
 
void CAnimationController::playAnimationNext(const irr::c8* name)
{
    if (animations.find(name) == 0)
        return;
 
    nextAnimation.clear();
 
    if (animationRunning)
    {
        nextAnimation.push_back(animations[name]);
    }
    else
        setAnimation(animations[name]);
}
 
void CAnimationController::playAnimationNow(const irr::c8* name)
{
    if (animations.find(name) == 0)
        return;
 
    nextAnimation.clear();
 
    setAnimation(animations[name]);
}
 
 
void CAnimationController::setAnimation(const Animation& anim)
{
 
    printf("change Animation to %s\n", anim.name.c_str());
    currentAnimation = anim;
    animatedNnode->setFrameLoop(currentAnimation.start, currentAnimation.end);
    animatedNnode->setCurrentFrame(currentAnimation.start);
    animatedNnode->setLoopMode(false);
    animationRunning = true;
}
main.cpp

Code: Select all

 
/*
  Copyright (C) 2011 Daniel Sudmann
 
  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.
 
  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:
 
  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
 
  Daniel Sudmann suddani@googlemail.com
*/
#include "CAnimationController.h"
#include <irrlicht.h>
 
struct events : irr::IEventReceiver
{
    bool OnEvent(const irr::SEvent& event)
    {
        if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
        {
            if (event.KeyInput.Key == irr::KEY_KEY_Q)
            {
                controller.playAnimation("idle");
            }
            else if (event.KeyInput.Key == irr::KEY_KEY_W)
            {
                controller.playAnimation("crouch");
            }
            else if (event.KeyInput.Key == irr::KEY_KEY_E)
            {
                controller.playAnimation("stand");
            }
            else if (event.KeyInput.Key == irr::KEY_KEY_R)
            {
                controller.playAnimation("idle");
                controller.playAnimation("crouch");
                controller.playAnimation("stand");
                controller.playAnimation("idle");
            }
            else if (event.KeyInput.Key == irr::KEY_ESCAPE)
            {
                device->closeDevice();
            }
        }
        return false;
    }
    CAnimationController controller;
    irr::IrrlichtDevice* device;
};
 
int main()
{
    irr::IrrlichtDevice* device = irr::createDevice(irr::video::EDT_OPENGL);
 
    irr::scene::IAnimatedMeshSceneNode* dwarf = device->getSceneManager()->addAnimatedMeshSceneNode(device->getSceneManager()->getMesh("dwarf.x")); //change to fit your media path
    dwarf->setMaterialFlag(irr::video::EMF_LIGHTING, false);
    dwarf->setLoopMode(false);
 
    printf("Total frames: %i\n", dwarf->getEndFrame());
 
    device->getSceneManager()->addCameraSceneNodeFPS();
 
    events event;
 
    event.device = device;
 
    event.controller.setAnimatedMeshNode(dwarf);
 
    printf("!!!Total frames: %i\n", dwarf->getEndFrame());
 
    event.controller.addAnimation("crouch", 0, 20);
    event.controller.addAnimation("idle", 21, 30, true);
    event.controller.addAnimation("stand", 31, 54);
 
    device->setEventReceiver(&event);
 
    while (device->run())
    {
        device->getVideoDriver()->beginScene();
        device->getSceneManager()->drawAll();
        device->getVideoDriver()->endScene();
    }
 
    device->drop();
 
    return 0;
}
 
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Re: Chaining Animations?

Post by serengeor »

Sudi wrote: What?
Never mind I read it the wrong way around.
Working on game: Marrbles (Currently stopped).
thoma91
Posts: 28
Joined: Tue Aug 09, 2011 10:00 am

Re: Chaining Animations?

Post by thoma91 »

Thank you Sudi, this works like a dream! This time I didn't waste my time to simplify it, I have to move on..
By the way, is there a way to interrupt an animation?
For example:
The enemy should die after the 4th shot.
If I shoot slowly, that looks good: enemy walks,the player shoots,hit taking animation,then it starts walking again,etc.
But if I shoot fast, the enemy doesn't die after 4th shot, it dies after the 4th "hurt-walk" animation combination, which looks pretty weird.
So I want to get that "hurt" animation immediately.
Here's what I tried (it did not work at all, I get the same result as before):

Code: Select all

 
void CAnimationController::playAnimation(const irr::c8 *name)
{
    if (animations.find(name) == 0)
        return;
 
    if (animationRunning && name != "hurt")
    {
        nextAnimation.push_back(animations[name]);
    }
    else if (animationRunning && name == "hurt")
    {
         setAnimation(animations[name]);
    }
    else if (!animationRunning)
    {
        setAnimation(animations[name]);
    }
}
 
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Re: Chaining Animations?

Post by sudi »

Really? Are you even reading the code i posted?

I already implemented that for you and even documented it for you!!!!

Code: Select all

CAnimationController::playAnimationNow
is doing what you want.
Please read the CAnimationController.h

PS: from the h file

Code: Select all

 
//!Plays an animation when the previous ones finished. Animations chain up
void playAnimation(const irr::c8* name);
//!Plays this animation directly after the last one and clears the animation chain
void playAnimationNext(const irr::c8* name);
//!Plays this animation directly and clears the animation chain
void playAnimationNow(const irr::c8* name);
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
thoma91
Posts: 28
Joined: Tue Aug 09, 2011 10:00 am

Re: Chaining Animations?

Post by thoma91 »

Ahh, thank you, it's my fault again :( Sorry for being foolish for asking first before looking.
Thank you Sudi for your help and patience, it was very important to me!
Greetings Image
Post Reply