Trouble changing animations when entity walks

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Nazrix
Halfling
Posts: 47
Joined: Tue Oct 29, 2002 9:18 pm

Trouble changing animations when entity walks

Post by Nazrix »

I'm looking to set the AnimationState to "Walk" when the entity is walking and to "Idle" when it's not.

Here I have code from frameStarted() that turns the entity with 'U' and 'Y' and moves the entity forward with 'H'. This all works, but when I set the animation to "Walk" when you hit 'H' I don't know the proper way to set the animation to Idle when you're not hitting 'H'.

I've tried somet things but they didnt work correctly


rotx is a Real that I use to keep track of the entity's rotation angle

bool frameStarted(const FrameEvent &evt)
{

if (mInputDevice->isKeyDown( KC_U))
{
rotx+=Math::PI/180;
}


if (mInputDevice->isKeyDown( KC_Y))
{
rotx-=Math::PI/180;
}



if (mInputDevice->isKeyDown( KC_H))
{

mAnimationState = ent->getAnimationState( "Walk" );
mAnimationState->setLoop( true );
mAnimationState->setEnabled( true );

mNode->translate(Vector3( cosf(rotx+Math::PI/2), 0.0f, sinf(rotx+Math::PI/2)) * evt.timeSinceLastFrame*-60.0f);
}


// set the entity's node so that its facing the right way
Vector3 src = mNode->getOrientation( ) * Vector3::UNIT_X;

if ( (1.0f + src.dotProduct( Vector3(cosf(rotx), 0.0f, sinf(rotx)) )) < 0.0001f )
mNode->yaw( Degree(180) );
else
{
Ogre::Quaternion quat = src.getRotationTo( Vector3(cosf(rotx), 0.0f, sinf(rotx)) );
mNode->rotate( quat );
}


} //end frameStarted
User avatar
Mr_Ridd
Goblin
Posts: 297
Joined: Fri Jun 04, 2004 10:01 pm
Location: South Africa
x 1

Post by Mr_Ridd »

Hey

I found your post a bit confusing. Are you having trouble actually setting the animation or just working out the game logic to set the animation?

If you are looking for the second option I could help you out a bit. I just finished writing a system where you could walk, jump, attack, go into idle, smoothly (well without interlpolation). It also caters for things like if you jump, it first completes the jump animation before it starts a new animation.

If that is what you're looking for I could show you. I'm at work at the moment so I would have to post it tomorrow.
The ability to succeed is the ability to adapt
Nazrix
Halfling
Posts: 47
Joined: Tue Oct 29, 2002 9:18 pm

Game Logic

Post by Nazrix »

Sorry. I know it is a bit confusing.

But yes I am looking for the 2nd option of the game logic. I would love to get some help on that. That's exactly the thing that I'm looking for
User avatar
Mr_Ridd
Goblin
Posts: 297
Joined: Fri Jun 04, 2004 10:01 pm
Location: South Africa
x 1

Post by Mr_Ridd »

I forgot a have it on my flash disk. Take a look at these files:

AnimationController.h

Code: Select all

#ifndef _ANIMATION_CONTROLLER_
#define _ANIMATION_CONTROLLER_

#include "ExampleApplication.h"
#include <vector>

typedef enum
{
	IDLE_01,
	RUN_FORWARD,
	RUN_BACKWARD,
	JUMP_FORWARD,
	ATTACK_01,
	ANIM_NONE,
    NUM_BASIC_ANIMS

}BASIC_ANIMS;

typedef struct
{
	BASIC_ANIMS enAnimIndex;

	char* acName;

	bool fMustComplete;
	bool fLoop;
	bool fComplete;

	Real flAnimSpeed;
		
}ANIM_HELPER;

class AnimationController
{
	public:

		AnimationController();

		AnimationController(SceneManager* smgr, Entity* animEnt, bool setDefaultAnimation);
		
		void userAnimate(Real flFrameTime);

		void systemAnimate(Real flFrameTime);

		void setCurrentAnimation(BASIC_ANIMS enAnimIndex);

		void setUserInteracting(bool fInteract);
		
	private:

		std::vector<ANIM_HELPER> vecAnimList;	

		ANIM_HELPER* pstCurrentAnimation;

		SceneManager* mSceneMgr;

		Entity* animatedEntity;

		AnimationState* pclAnimState;

		bool fIsUserInteracting;

		Real flTimer;

		bool fEndInterpolation;

		void setAnimation(ANIM_HELPER* pstAnimType, Real flTimePosition);
};


#endif
AnimationController.cpp

Code: Select all

#include "AnimationController.h"
#include <stdio.h>
#include <time.h>

AnimationController::AnimationController()
{}

/* constructor */
AnimationController::AnimationController(SceneManager* smgr, Entity* animEnt, bool setDefaultAnimation)
{
	mSceneMgr = smgr;
	animatedEntity = animEnt;

	fIsUserInteracting = false;

	flTimer = 0.0;

	fEndInterpolation = false;

	/* animation initialisation */
	ANIM_HELPER stAnimIni;

	/* idle 01 */
	stAnimIni.enAnimIndex = IDLE_01;
	stAnimIni.acName = "Idle1";
	stAnimIni.fComplete = true;
	stAnimIni.flAnimSpeed = 1;
	stAnimIni.fLoop = true;
	stAnimIni.fMustComplete = false;

	vecAnimList.push_back(stAnimIni);

	/* run forward */
	stAnimIni.enAnimIndex = RUN_FORWARD;
	stAnimIni.acName = "Walk";
	stAnimIni.fComplete = true;
	stAnimIni.flAnimSpeed = 1;
	stAnimIni.fLoop = true;
	stAnimIni.fMustComplete = false;

	vecAnimList.push_back(stAnimIni);

	/* run backward */
	stAnimIni.enAnimIndex = RUN_BACKWARD;
	stAnimIni.acName = "Walk";
	stAnimIni.fComplete = true;
	stAnimIni.flAnimSpeed = 1;
	stAnimIni.fLoop = true;
	stAnimIni.fMustComplete = false;

	vecAnimList.push_back(stAnimIni);

	/* jump forward */
	stAnimIni.enAnimIndex = JUMP_FORWARD;
	stAnimIni.acName = "Jump";
	stAnimIni.fComplete = true;
	stAnimIni.flAnimSpeed = 1;
	stAnimIni.fLoop = false;
	stAnimIni.fMustComplete = true;

	vecAnimList.push_back(stAnimIni);

	/* jump forward */
	stAnimIni.enAnimIndex = ATTACK_01;
	stAnimIni.acName = "Attack1";
	stAnimIni.fComplete = true;
	stAnimIni.flAnimSpeed = 1;
	stAnimIni.fLoop = false;
	stAnimIni.fMustComplete = true;

	vecAnimList.push_back(stAnimIni);

	/* none */
	stAnimIni.enAnimIndex = ANIM_NONE;
	stAnimIni.acName = "";
	stAnimIni.fComplete = true;
	stAnimIni.flAnimSpeed = 0;
	stAnimIni.fLoop = false;
	stAnimIni.fMustComplete = false;

	vecAnimList.push_back(stAnimIni);

	pstCurrentAnimation = &stAnimIni;
	setCurrentAnimation(IDLE_01);

}

/* runs the animation for the current entity if there is user interaction */		
void AnimationController::userAnimate(Real flFrameTime)
{
	fIsUserInteracting = true;

	if( pclAnimState == NULL )
		return;

		pclAnimState->addTime(flFrameTime*pstCurrentAnimation->flAnimSpeed);
}

/* runs the animation for the current entity if there is no user interaction */		
void AnimationController::systemAnimate(Real flFrameTime)
{
	if( pclAnimState == NULL )
		return;

	if( pstCurrentAnimation->enAnimIndex == ANIM_NONE )
		return;

	if( fIsUserInteracting == false )
		pclAnimState->addTime(flFrameTime*pstCurrentAnimation->flAnimSpeed);

	if( pstCurrentAnimation->fMustComplete == false || pclAnimState->getTimePosition() >= pclAnimState->getLength() )
	{
		pstCurrentAnimation->fComplete = true;

		if( fIsUserInteracting == false )
		{
			setCurrentAnimation(IDLE_01);
		}
	}

}

/* sets the animation */
void AnimationController::setCurrentAnimation(BASIC_ANIMS enAnimIndex)
{
	if( pstCurrentAnimation == NULL )
		return;

	/* only perform this action if the animations differ */
	if( pstCurrentAnimation->enAnimIndex != enAnimIndex )
	{
		if( pstCurrentAnimation->fMustComplete )
		{
			if( pstCurrentAnimation->fComplete == false )
			{
				return;
			}
		}

		/* reset current animation */
		pstCurrentAnimation->fComplete = true;

		for(unsigned int i = 0; i < vecAnimList.size(); i++)
		{
			if( vecAnimList.at(i).enAnimIndex == enAnimIndex )
			{
				setAnimation(&(vecAnimList.at(i)), 0.0);
				break;
			}
		}
	}
}

/* changes the new animation to the animType */
void AnimationController::setAnimation(ANIM_HELPER* pstAnimType, Real flTimePosition)
{
	if( pclAnimState != NULL )
	{
		pclAnimState->setTimePosition(0.0);
		pclAnimState->setEnabled(false);
	}

	if( pstAnimType->enAnimIndex == ANIM_NONE )
	{
		pstCurrentAnimation = pstAnimType;
		return;
	}

	pclAnimState = animatedEntity->getAnimationState(pstAnimType->acName);

	fEndInterpolation = true;
	pclAnimState->setEnabled(true);
	pclAnimState->setTimePosition(flTimePosition);
	pclAnimState->setLoop(pstAnimType->fLoop);
	pstAnimType->fComplete = false;

	pstCurrentAnimation = pstAnimType;
}

/* whether a key is being pressed */
void AnimationController::setUserInteracting(bool fInteract)
{
	fIsUserInteracting = fInteract;
}


/* AnimationController.cpp */

ComplexCharacter.cpp

Code: Select all

#include "ComplexCharacter.h"

ComplexCharacter::ComplexCharacter()
{}

ComplexCharacter::ComplexCharacter(SceneManager* smgr, Camera* cam)
{
	mSceneMgr = smgr;
	mCamera = cam;

	charCollisionController = new CollisionController(smgr, cam);
}

/* this character's event handler */
void ComplexCharacter::processEvent(const FrameEvent& evt, InputReader* mInputDevice)
{
	Real MoveFactor = PLAYER_SPEED * evt.timeSinceLastFrame;
	
	Real mouseX = mInputDevice->getMouseRelativeX() * MOUSE_ROTATE_SPEED;
	Real mouseY = mInputDevice->getMouseRelativeY() * MOUSE_ROTATE_SPEED;

	//getAnimationController()->systemAnimate(evt.timeSinceLastFrame);
	charCollisionController->testObjectAgainstTerrain(controlNode, 5);
	/*playerCollisionController->keepCameraAboveGround(footNode);*/

	rotateCharacter(-mouseX);

	charAnimController->setUserInteracting(false);

	if(mInputDevice->isKeyDown(Ogre::KC_SPACE))
	{
		/* animation states */
		charAnimController->setCurrentAnimation(JUMP_FORWARD);
		
		animateCharacter(evt.timeSinceLastFrame);
	}
		
	if(mInputDevice->isKeyDown(MOVE_FORWARD))
	{
		/* animation states */
		charAnimController->setCurrentAnimation(RUN_FORWARD);
		
		animateCharacter(evt.timeSinceLastFrame);
		translateCharacter(0.0, 0.0, -MoveFactor);
	}
	else if(mInputDevice->isKeyDown(MOVE_BACKWARD))
	{	
		/* animation states */
		charAnimController->setCurrentAnimation(RUN_BACKWARD);

		animateCharacter(evt.timeSinceLastFrame);
		translateCharacter(0.0, 0.0, MoveFactor);
		//getAnimationController(BP_FOOT)->userAnimate(evt.timeSinceLastFrame);
	}
	
	if(mInputDevice->isKeyDown(MOVE_LEFT))
	{
		/* animation states */
		/*setAnimation(STRAFE_LEFT_RUN, true, false);
		*/

		animateCharacter(evt.timeSinceLastFrame);
		translateCharacter(-MoveFactor, 0.0, 0.0);	
		
	}
	
	if(mInputDevice->isKeyDown(MOVE_RIGHT))
	{		
		/* animation states */
		/*setAnimation(ANIMATION_STRAFE_RIGHT_RUN, true, false);
		

		animateCharacter(evt.timeSinceLastFrame);
		translateCharacter(MoveFactor, 0.0, 0.0);*/
	}

	if(mInputDevice->getMouseButton(LEFT_MOUSE_BUTTON))
	{
		charAnimController->setCurrentAnimation(ATTACK_01);	
	}
	
	if(mInputDevice->getMouseButton(RIGHT_MOUSE_BUTTON))
	{
		
	}

	charAnimController->systemAnimate(evt.timeSinceLastFrame);
}


/* sets the position of this character */
void ComplexCharacter::setCharacterPosition(Real x, Real y, Real z)
{
	controlNode->setPosition( Vector3(x, y, z) );
}

/* translates this character */
void ComplexCharacter::translateCharacter(Real x, Real y, Real z)
{
	Vector3 trans = controlNode->getOrientation() * Vector3(x, y, z);
	controlNode->translate(trans);
}

/* rotates the character */
void ComplexCharacter::rotateCharacter(Real speed)
{
	//Vector3 trans = controlNode->getOrientation() * rot;
	controlNode->yaw(Radian(speed));
}


/* animates all nodes */
void ComplexCharacter::animateCharacter(Real time)
{
	charAnimController->userAnimate(time);
}


/* creates the relevant entities and attaches them to their respective nodes */
void ComplexCharacter::createCharacter(char* name, char* characterPath)
{
	/* creating the base node */
	controlNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	
	characterEnt = mSceneMgr->createEntity(name, characterPath);
	controlNode->attachObject(characterEnt);

	/* creating the head's animation controller */
	charAnimController = new AnimationController(mSceneMgr, characterEnt, true);

	controlNode->attachObject(mCamera);
	//mCamera->setPosition(Vector3(0, CAMERA_HEIGHT, CAMERA_DISTANCE));
	mCamera->setPosition(Vector3(0, 200, 500));
	/*mCamera->setPosition(Vector3(200, 90, 100));*/
	//mCamera->setDirection( Vector3(0, 0, 100) );
	Vector3 lookAtPos = controlNode->getWorldPosition();
	lookAtPos.y += 200;
	mCamera->lookAt(lookAtPos);
	
}

/* ComplexCharacter.cpp */
It's a lot, but it's easier if you look for yourself than me explain it.

Hope this helps.
The ability to succeed is the ability to adapt
Nazrix
Halfling
Posts: 47
Joined: Tue Oct 29, 2002 9:18 pm

thanks

Post by Nazrix »

Thank you. This will help a lot.
Nazrix
Halfling
Posts: 47
Joined: Tue Oct 29, 2002 9:18 pm

ComplexCharacter.h?

Post by Nazrix »

Did you forget to post ComplexCharacter.h?

Perhaps I can figure out what ComplexCharacter.h looked like though.
User avatar
Mr_Ridd
Goblin
Posts: 297
Joined: Fri Jun 04, 2004 10:01 pm
Location: South Africa
x 1

Post by Mr_Ridd »

Hey

You shouldn't need ComplexCharactere.h. If you implement it, tell me if it worked or if you think it's a load of bullshit. :D
The ability to succeed is the ability to adapt
User avatar
bugshake
Greenskin
Posts: 111
Joined: Sat Feb 26, 2005 1:12 pm
Location: Amsterdam

Post by bugshake »

Earlier I posted a class that blends a maximum of two animations:

http://www.ogre3d.org/phpBB2/viewtopic. ... 0474#60474

It's not on the wiki because I don't think it's generic enough yet, but it might help you. You would do something like

Code: Select all

if( key[walking] && !walking )
{
  walking = true;
  mBlender->blend( "Walk", AnimationBlender::BlendWhileAnimating, 0.5 ); // 0.5 seconds
}
else if( !key[walking] && walking )
{
  walking = false;
  mBlender->blend( "Idle", AnimationBlender::BlendWhileAnimating, 0.5 ); // 0.5 seconds
}
This way when you tap the walk button, it puts one leg forward a bit then back again. And when you're walking and you release the walk button, the legs make smaller and smaller passes until you're standing again.
Nazrix
Halfling
Posts: 47
Joined: Tue Oct 29, 2002 9:18 pm

cool

Post by Nazrix »

bugshake, that sounds great. I'll check it out thanks.
Nazrix
Halfling
Posts: 47
Joined: Tue Oct 29, 2002 9:18 pm

cool

Post by Nazrix »

bugshake, that code is awesome. Thanks a lot :)