animation walking

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
Guest

animation walking

Post by Guest »

hi,
how do you keep a model to keep walking (with walking cycle frame) while a key is held down(key repeat)?
i've done something like this..and after you hold it for some time, it goes really funny.

Code: Select all

bool pressed=false;
core::vector3df v;
 
class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent (SEvent event)
	{
		if (moveNode!=0 && event.EventType==irr::EET_KEY_INPUT_EVENT)
		{
			if (!pressed)
			{
				if (event.KeyInput.Key==KEY_KEY_W)
				{
					//move
					walk_left=true;
					v = moveNode->getPosition();
					moveNode->setFrameLoop(2,5);
					moveNode->setAnimationSpeed(10);
					moveNode->setLoopMode(false);
					v.Z += 1.0f;
					moveNode->setPosition(v);
					return true;	
			}
			else
			{
					//idle 
					moveNode->setFrameLoop(90,110); 
					moveNode->setLoopMode(true);
					moveNode->setAnimationSpeed(10);
					pressed=false;
					anim_cycle = false;
					return true;
			}
		}
	return false;
	}
};
also, how do i restrict the animation so that no matter what key you press, it will wait until the animation to finish before the next action.

thanks for your time
Kayl
Posts: 14
Joined: Wed Jun 08, 2005 7:17 am

Post by Kayl »

use a bool to keep track of "walking".

in your event method :

if (event.KeyInput.Key==KEY_KEY_W)
{

if (event.KeyInput.PressedDown)&&(!walking) //this will be done once
{
walking = true;
set the waling animations details
}
else if (!event.KeyInput.PressedDown)&&(walking) //this will be done on key up
{
walking = false;
set the idle animations details
}


}


For your second question :
When you start an animation put a bool finished to false.
With an IAnimationEndCallback set the bool to true when the animation is finished.
Then allow Animations to start only if finished is "true"
Guest

Post by Guest »

hi, thanks for the solution. the first one works perfectly.
however, i still didn't get it for the second one.

so you mean something like this?

//global
bool finished;

//then...in event
if ((event.KeyInput.PressedDown)&&(!walking))
{
finished=false;
set animation frame loop, etc
moveNode->setAnimationEndCallBack();
finished = true;
return true;
}
Kayl
Posts: 14
Joined: Wed Jun 08, 2005 7:17 am

Post by Kayl »

If what you want to do is : when the guy stops walking, wait until the end of the walking animation before setting it to idle animation.

Then you can TRY (not sure about interrupting the loop part, don't your animations have names ?)

global :
MyCallBack mycallback;

MyCallback being a class specialising IAnimationEndCallBack


if ((event.KeyInput.PressedDown)&&(!walking))
{
//because now I assume it was looping when walking
moveNode->setLoopMode(false);
moveNode->setAnimationEndCallBack(&mycallback);
}

thus when the animation will stop (at frame 5 i guess in your case)
i hope mycallback::OnAnimationEnd will be called and there (in the method of your own class MyCallback) you can do :
node->setFrameLoop(90,110);
node->setLoopMode(true);
node->setAnimationSpeed(10);

This will only work if the callback is indeed called, which i'm not sure because irrlicht doc is fuzzy about it.
It will allow the walk animation to finish before using idle animation.
Guest

Post by Guest »

hum..i've tried many ways, still didn't work.
well..how does setAnimationEndCallBack work?
i read the description in IAnimatedMeshSceneNode.h, and it just says that IAnimationEndCallBack::OnAnimationEnd will be called.
so i figured, maybe do something like :

//global
scene::IAnimationEndCallBack* endNode;

//then after animation..
endNode->OnAnimation(moveNode);

but then i'm not sure how to make use of this information.
//to test it, i did something stupid like...
if (endNode)
{different animation state}
:cry:

i think once i know how this animationEndCallBack thing work, it's good to go. but again i've been searching all over the place (this forum, google) for example how to use it, no luck.
if anyone could tell me, pls let me know.

thanks again
Guest

Post by Guest »

oh hi kayl, i didn't see your post just now. :o

sorry it's not what i meant. what i meant was : if you press the key and hold, the character will just keep walking (which is good), but then if you press the key rapidly, the character will try to do the animation rapidly (sorta just shaking there...if you know what i mean) before even the animation done.
so ideally, i want: once the key is pressed, and no matter how many times i press the same key, it will just finish the animation first.

sorry, does that clear up the misunderstanding?
Kayl
Posts: 14
Joined: Wed Jun 08, 2005 7:17 am

Post by Kayl »

First when you release the key : you should launch the idle animation as mentionned in my previous post with the callback system.

But if you press the key, BEFORE the end of the animation, (before the call of the callback), then just remove the animation callback (call it with NULL) and set the loop mode to true.

To know when you press the key if you're still in walking animation, check the getFrame().
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

animation walking

Post by trivtn »

First you should declare a bool keys array.
bool keys[irr::KEY_KEY_CODES_COUNT];//bool keyboard buffer
EMD2_ANIMATION_TYPE model_style=EMAT_STAND;
...
See :"http://www.irrforge.org/index.php/Keyboard_Input"
then after that, in the game loop you can process that by the way:
...
if ((keys[irr::KEY_KEY_W])||(keys[irr::KEY_KEY_S])
||(keys[irr::KEY_KEY_A])||(keys[irr::KEY_KEY_D]))
{
if (model_style!=EMAT_RUN)
{
model_style =EMAT_RUN;
node->setMD2Animation(model_style);
}
if(keys[irr::KEY_KEY_W])
{
p.X = p.X + ( cos(r.Y * core::GRAD_PI2)*speed);
p.Z = p.Z - ( sin(r.Y * core::GRAD_PI2)*speed);
node->setPosition(p);
}
if(keys[irr::KEY_KEY_S])
{
p.X = p.X - ( cos(r.Y * core::GRAD_PI2)*speed );
p.Z = p.Z + ( sin(r.Y * core::GRAD_PI2)*speed );
node->setPosition(p);
}
if(keys[irr::KEY_KEY_A])
{
p.X = p.X + ( cos((r.Y-90) * GRAD_PI2)*speed );
p.Z = p.Z - ( sin((r.Y-90) * GRAD_PI2)*speed );
node->setPosition(p);
}
if(keys[irr::KEY_KEY_D])
{
p.X = p.X + ( cos((r.Y+90) * GRAD_PI2)*speed );
p.Z = p.Z - ( sin((r.Y+90) * GRAD_PI2)*speed );
node->setPosition(p);
}
}
else
{
if (model_style!=EMAT_STAND)
{
model_style =EMAT_STAND;
node->setMD2Animation(model_style);
}
}
Guest

Post by Guest »

Kayl wrote:First when you release the key : you should launch the idle animation as mentionned in my previous post with the callback system.

But if you press the key, BEFORE the end of the animation, (before the call of the callback), then just remove the animation callback (call it with NULL) and set the loop mode to true.

To know when you press the key if you're still in walking animation, check the getFrame().

Code: Select all

scene::IAnimationEndCallBack* endNode;
if (event.KeyInput.Key==KEY_KEY_W)
			{
				//press key
				if ((event.KeyInput.PressedDown)&&(!animation))
				{
					//if pressed down and there's no animation then
					//run animation..
					v = moveNode->getPosition();
					finished=false;
					moveNode->setFrameLoop(2,14);
					moveNode->setAnimationSpeed(10);
					moveNode->setAnimationEndCallback(NULL);
					moveNode->setLoopMode(true);
					moveNode->setAnimationEndCallback(endNode); //the end of animation
				
					v.Z = v.Z + 3.0f; 
					moveNode->setPosition(v);
					animation=true;
					//finished=true;
					return true;
				}
				//release key
				else if ((!event.KeyInput.PressedDown)&&(animation))
				{
					animation=false;
					//idle animation
					moveNode->setFrameLoop(75,88); 
					moveNode->setLoopMode(true);
					moveNode->setAnimationSpeed(10);
					return true;
				}
the animationEndCallBack thing still didn't have any effects.
i think what i need is something like buffered key input, so then it won't allow me to run n number of animation when i press n number of the same key, it'll just queue all the key inputs.
i tried to do what trivtn suggested, but i still don't understand some of the stuff.
like "EMD2_ANIMATION_TYPE model_style=EMAT_STAND; " (is this declaration?)
also, isn't md2animation is for md2 models? cause i'm using *.x for the model.
shadowrider
Posts: 5
Joined: Tue Jan 31, 2006 5:18 pm

Post by shadowrider »

putting this problem aside for a min, how do i update the position of the character when the key is held down?
right now, it gets the current position when key is "pressed", update position, and it'll not be updated until the next event.
how to make it so that it'll update the position while in this event without having to exit the event?
thanks
Guest

Post by Guest »

Use an animator that is called at each frame.
In this animator if the boolean saying "i am moving" is set, then move, else don't do anything.

In the event just change the animation and set this boolean.
Kayl
Posts: 14
Joined: Wed Jun 08, 2005 7:17 am

Post by Kayl »

That was me above.
Post Reply