Game Development Community

8 Directional Movement

by Kevin Mitchell · in Torque 3D Professional · 01/18/2010 (11:38 pm) · 29 replies

Source Code

This code resource is a guide for implementing my version, of a 8 Directional movement system in T3D.

There are always multiple ways to skin a cat so here's my way.

Step 1 Grab the tail....



player.h

enum {
      // *** WARNING ***
      // These enum values are used to index the ActionAnimationList
      // array instantiated in player.cc
      // The first several are selected in the move state based on velocity

   // *** WARNING ***
   // This array is indexed using the enum values defined in player.h

   // Root is the default animation
   // These are selected in the move state based on velocity
   Root_0,
   Root_45,
   Root_90,
   Root_135,
   Root_180,
   Root_225,
   Root_270,
   Root_315,
   // These are selected in the move state based on velocity
   Run_0,
   Run_45,
   Run_90,
   Run_135,
   Run_180,
   Run_225,
   Run_270,
   Run_315,
   //swim
   SwimRoot_0,
   SwimRoot_45,
   SwimRoot_90,
   SwimRoot_135,
   SwimRoot_180,
   SwimRoot_225,
   SwimRoot_270,
   SwimRoot_315,
   //swim
   Swim_0,
   Swim_45,
   Swim_90,
   Swim_135,
   Swim_180,
   Swim_225,
   Swim_270,
   Swim_315,
   //Crouch
   Crouch_0,
   Crouch_45,
   Crouch_90,
   Crouch_135,
   Crouch_180,
   Crouch_225,
   Crouch_270,
   Crouch_315,
   //Crouch
   CrouchWalk_0,
   CrouchWalk_45,
   CrouchWalk_90,
   CrouchWalk_135,
   CrouchWalk_180,
   CrouchWalk_225,
   CrouchWalk_270,
   CrouchWalk_315,
   //Jump
   Jump_0,
   Jump_45,
   Jump_90,
   Jump_135,
   Jump_180,
   Jump_225,
   Jump_270,
   Jump_315,
   //Fall
   Fall_0,
   Fall_45,
   Fall_90,
   Fall_135,
   Fall_180,
   Fall_225,
   Fall_270,
   Fall_315,
   //Land
   Land_0,
   Land_45,
   Land_90,
   Land_135,
   Land_180,
   Land_225,
   Land_270,
   Land_315,
   //StandJump
   StandJump_0,
   StandJump_45,
   StandJump_90,
   StandJump_135,
   StandJump_180,
   StandJump_225,
   StandJump_270,
   StandJump_315,
   //ProneRoot
   ProneRoot_0,
   ProneRoot_45,
   ProneRoot_90,
   ProneRoot_135,
   ProneRoot_180,
   ProneRoot_225,
   ProneRoot_270,
   ProneRoot_315,
   //ProneWalk
   ProneWalk_0,
   ProneWalk_45,
   ProneWalk_90,
   ProneWalk_135,
   ProneWalk_180,
   ProneWalk_225,
   ProneWalk_270,
   ProneWalk_315,
   //Jet
   Jet_0,
   Jet_45,
   Jet_90,
   Jet_135,
   Jet_180,
   Jet_225,
   Jet_270,
   Jet_315,
      
      // 
      NumMoveActionAnims = Run_315 + 1,
      NumTableActionAnims = Jet_315 + 1,

      NumExtraActionAnims = 512 - NumTableActionAnims,
      NumActionAnims = NumTableActionAnims + NumExtraActionAnims,
      ActionAnimBits = Jet_315,
      NullAnimation = (1 << ActionAnimBits) - 1
   };



player.cpp



...
static F32 sTractionDistance = 0.04f;
static F32 sNormalElasticity = 0.01f;
static U32 sMoveRetryCount = 5;
[b]
//8 DIRECTION ----
F32 YDIR;
F32 XDIR;

F32 PRE_YDIR;
F32 PRE_XDIR;
//8 DIRECTION ----
[/b]
...



// Root is the default animation

//8 DIRECTION ----
	{ "Root_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "Root_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "Root_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "Root_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "Root_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "Root_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "Root_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "Root_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	// These are selected in the move state based on velocity
	{ "Run_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "Run_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "Run_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "Run_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "Run_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "Run_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "Run_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "Run_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//swimRoot
	{ "SwimRoot_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "SwimRoot_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "SwimRoot_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "SwimRoot_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "SwimRoot_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "SwimRoot_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "SwimRoot_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "SwimRoot_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//swim
	{ "Swim_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "Swim_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "Swim_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "Swim_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "Swim_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "Swim_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "Swim_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "Swim_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//Crouch
	{ "Crouch_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "Crouch_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "Crouch_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "Crouch_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "Crouch_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "Crouch_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "Crouch_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "Crouch_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//Crouch
	{ "CrouchWalk_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "CrouchWalk_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "CrouchWalk_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "CrouchWalk_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "CrouchWalk_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "CrouchWalk_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "CrouchWalk_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "CrouchWalk_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//Jump
	{ "Jump_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "Jump_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "Jump_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "Jump_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "Jump_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "Jump_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "Jump_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "Jump_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//Fall
	{ "Fall_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "Fall_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "Fall_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "Fall_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "Fall_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "Fall_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "Fall_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "Fall_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//Land
	{ "Land_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "Land_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "Land_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "Land_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "Land_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "Land_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "Land_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "Land_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//StandJump
	{ "StandJump_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "StandJump_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "StandJump_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "StandJump_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "StandJump_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "StandJump_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "StandJump_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "StandJump_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//ProneRoot
	{ "ProneRoot_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "ProneRoot_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "ProneRoot_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "ProneRoot_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "ProneRoot_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "ProneRoot_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "ProneRoot_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "ProneRoot_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//ProneWalk
	{ "ProneWalk_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "ProneWalk_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "ProneWalk_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "ProneWalk_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "ProneWalk_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "ProneWalk_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "ProneWalk_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "ProneWalk_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
	//ProneWalk
	{ "Jet_0",	{ 1.0f, 0.0f, 0.0f } },       // RunForwardAnim,
	{ "Jet_45",	{ 0.707f, 0.707F, 0.0f } },       // BackBackwardAnim
	{ "Jet_90",	{ 0.0f, 1.0f, 0.0f } },       // SideLeftAnim,
	{ "Jet_135",  { -0.707f, 0.707F, 0.0f } },       // RunForwardAnim,
	{ "Jet_180",	{ -1.0f, 0.0f, 0.0f } },       // BackBackwardAnim
	{ "Jet_225",	{ -0.707f, -0.707F, 0.0f } },       // SideLeftAnim,
	{ "Jet_270",  { 0.0f, -1.0f, 0.0f } },       // RunForwardAnim,
	{ "Jet_315",  { 0.707f, -0.707F, 0.0f } },       // RunForwardAnim,
};


Line 578
bool PlayerData::isJumpAction(U32 action)
{
	return ((action >= Jump_0 && action <= Jump_315) || (action >= StandJump_0 && action <= StandJump_315));
}


void Player::setState(ActionState state, U32 recoverTicks)
{
	if (state != mState) {
		// Skip initialization if there is no manager, the state
		// will get reset when the object is added to a manager.
		if (isProperlyAdded()) {
			switch (state) {
			case RecoverState: {
				mRecoverTicks = recoverTicks;
				mReversePending = U32(F32(mRecoverTicks) / sLandReverseScale); 
				// Our feet are on something
				// Pick animation that is the best fit for our current velocity.
				// Assumes that root is the first animation in the list.
				VectorF vel;
				mWorldToObj.mulV(mVelocity,&vel);
				for (U32 i = PlayerData::Land_0; i < PlayerData::Land_315+1; i++)
				{
					PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
					if (anim.sequence != -1 && anim.speed) 
					{
						if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
							setActionThread(i, true, false, true, true);
							break;
						}
					}
				}


				break;
				}

			default:
				break;
			}
		}

		mState = state;
	}
}


Add any where above "void Player::updateMove(const Move* move)"


float CalcTheta( const Point3F Point1, const Point3F Point2 )
{
	float Theta;
	if ( Point2.x - Point1.x == 0 ){
		if ( Point2.y > Point1.y ){
			Theta = 0;
		}else{
			Theta = static_cast<float>( M_PI_F );
		}
	}else{
		Theta = std::atan( (Point2.y - Point1.y) / (Point2.x - Point1.x) );
		if ( Point2.x > Point1.x ){
			Theta = static_cast<float>( M_PI_F ) / 2.0f - Theta;
		}else{
			Theta = static_cast<float>( M_PI_F ) * 1.5f - Theta;
		}
	}
	return Theta;
}

Inside "void Player::updateMove(const Move* move)"
if (mState == MoveState && mDamageState == Enabled)
	{
		zRot.getColumn(0,&moveVec);
		moveVec *= move->x;
		VectorF tv;
		zRot.getColumn(1,&tv);
		moveVec += tv * move->y;

		//Con::printf("movex: %g  movey: %g movez: %g",move->x,move->y,move->z);
		//if(move->y!=0||move->x!=0){
		Point3F Point1;
		Point3F Point2;
		F32 DIR_ANGLE;
		Point1.x=10;
		Point1.y=10;
		Point1.z=0;
		Point2.x=10+(move->y);
		Point2.y=10+move->x;
		Point2.z=0;
		DIR_ANGLE = (CalcTheta(Point1,Point2)*180)/M_PI_F;
		//Con::printf("degree: %g rad: %g",(CalcTheta(Point1,Point2)*180)/M_PI_F,CalcTheta(Point1,Point2));
		YDIR=move->y;
		XDIR=move->x;
		if(move->y!=0||move->x!=0){
			if(DIR_ANGLE<22.5 || DIR_ANGLE>=337.5){//0
				YDIR=0;
				XDIR=1;
			}else if(DIR_ANGLE<67.5 && DIR_ANGLE>=22.5){//45
				YDIR=0.707f;
				XDIR=0.707f;
			}else if(DIR_ANGLE<112.5 && DIR_ANGLE>=67.5){//90
				YDIR=1;
				XDIR=0;
			}else if(DIR_ANGLE<157.5 && DIR_ANGLE>=112.5){//135
				YDIR=0.707f;
				XDIR=-0.707f;
			}else if(DIR_ANGLE<202.5 && DIR_ANGLE>=157.5){//180
				YDIR=0;
				XDIR=-1;
			}else if(DIR_ANGLE<247.5 && DIR_ANGLE>=202.5){//225
				YDIR=-0.707f;
				XDIR=-0.707f;
			}else if(DIR_ANGLE<292.5 && DIR_ANGLE>=247.5){//270
				YDIR=-0;
				XDIR=0;
			}else if(DIR_ANGLE<337.5 && DIR_ANGLE>=292.5){//315
				YDIR=-0.707f;
				XDIR=0.707f;
			}
		}


		//}
		// Clamp water movement


// Cancel any script driven animations if we are going to move.
		if (moveVec.x + moveVec.y + moveVec.z != 0.0f &&
			(mActionAnimation.action >= PlayerData::NumTableActionAnims
			|| (mActionAnimation.action >= PlayerData::Land_0&&mActionAnimation.action <= PlayerData::Land_315)))
			mActionAnimation.action = PlayerData::NullAnimation;
	}


// If we don't have a StandJumpAnim, just play the JumpAnim...
		S32 seq = (mVelocity.len() < 0.5) ? PlayerData::StandJump_0: PlayerData::Jump_0; 
		//if ( mDataBlock->actionList[seq].sequence != -1 ){			
			// Our feet are on something
			// Pick animation that is the best fit for our current velocity.
			// Assumes that root is the first animation in the list.
			VectorF vel;
			F32 dirBased=false;
			if(seq==PlayerData::Jump_0) dirBased=true;
			mWorldToObj.mulV(mVelocity,&vel);
			for (U32 i = seq; i < seq+9; i++)
			{
				PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
				if (anim.sequence != -1 && anim.speed) 
				{
					if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
						seq=i;
						break;
					}
				}
			}
		//}
		setActionThread( seq, true, false, true );


// Can't crouch if no crouch animation!
	if ( mDataBlock->actionList[PlayerData::Crouch_0].sequence == -1 )
		return false;

// Can't go prone if no prone animation!
	if ( mDataBlock->actionList[PlayerData::ProneRoot_0].sequence == -1 )
		return false;

if ( ((mActionAnimation.action >= PlayerData::Land_0)&&(mActionAnimation.action <= PlayerData::Land_315)) &&
		(mActionAnimation.action != PlayerData::NullAnimation) )
	{


void Player::pickActionAnimation()
{
	// Only select animations in our normal move state.
	if (mState != MoveState || mDamageState != Enabled)
		return;

	if (isMounted())
	{
		// Go into root position unless something was set explicitly
		// from a script.
		if (((mActionAnimation.action >= PlayerData::Root_0)&&(mActionAnimation.action <= PlayerData::Root_315)) &&
			mActionAnimation.action < PlayerData::NumTableActionAnims){
				// Our feet are on something
				// Pick animation that is the best fit for our current velocity.
				// Assumes that root is the first animation in the list.
				VectorF vel;
				mWorldToObj.mulV(mVelocity,&vel);
				for (U32 i = PlayerData::Root_0; i < PlayerData::Root_315+1; i++)
				{
					PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
					if (anim.sequence != -1 && anim.speed) 
					{
						if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
							setActionThread(i, true, false, false);
							break;
						}
					}
				}
		}
		return;
	}

	bool forward = true;
	U32 action = PlayerData::Root_90;
	bool fsp = false;

	// Jetting overrides the fall animation condition
	if (mJetting)
	{
		// Play the jetting animation
		// Our feet are on something
		// Pick animation that is the best fit for our current velocity.
		// Assumes that root is the first animation in the list.
		VectorF vel;
		mWorldToObj.mulV(mVelocity,&vel);
		for (U32 i = PlayerData::Swim_90; i <= PlayerData::Swim_315+1; i++)
		{
			PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
			if (anim.sequence != -1 && anim.speed) 
			{
				if(XDIR!=0||YDIR!=0){
					if(anim.dir.x==XDIR && anim.dir.y==YDIR){
						PRE_XDIR=XDIR;
						PRE_YDIR=YDIR;
						action = i;
						forward = true;
						break;
					}
				}else if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
					action = i;
					forward = true;
					break;
				}
			}
		}
	}
	else if (mFalling)
	{
		// Not in contact with any surface and falling		// Our feet are on something
		// Pick animation that is the best fit for our current velocity.
		// Assumes that root is the first animation in the list.
		VectorF vel;
		mWorldToObj.mulV(mVelocity,&vel);
		for (U32 i = PlayerData::Fall_90; i <= PlayerData::Fall_315+1; i++)
		{
			PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
			if (anim.sequence != -1 && anim.speed) 
			{
				if(XDIR!=0||YDIR!=0){
					if(anim.dir.x==XDIR && anim.dir.y==YDIR){
						PRE_XDIR=XDIR;
						PRE_YDIR=YDIR;
						action = i;
						forward = true;
						break;
					}
				}else if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
					action = i;
					forward = true;
					break;
				}
			}
		}
	}
	else if ( mSwimming )
	{
		action = PlayerData::SwimRoot_90;

		VectorF vel;

		for (U32 i = PlayerData::SwimRoot_0; i < PlayerData::SwimRoot_315+1; i++)
		{
			PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
			if (anim.sequence != -1 && anim.speed) 
			{
				// We bias towards picking the forward/backward anims over
				// the side to prevent oscillation between anims.  This seems 
				// to work ok but the real fix is to have 8 way directional 
				// animations.
				/*VectorF biasedDir = anim.dir * VectorF(0.5f,1.0f,0.5f);*/

				if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
					action = i;
					forward = true;
					break;
				}
			}
		}



		mWorldToObj.mulV(mVelocity,&vel);
		for (U32 i = PlayerData::Swim_90; i <= PlayerData::Swim_315+1; i++)
		{
			PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
			if (anim.sequence != -1 && anim.speed) 
			{
				if(anim.dir.x==XDIR && anim.dir.y==YDIR){
					if(XDIR!=0||YDIR!=0){
						PRE_XDIR=XDIR;
						PRE_YDIR=YDIR;
					}
					action = i;
					forward = true;
					break;
				}
			}
		}
	}
	else if ( mPose == StandPose )
	{
		if (mContactTimer >= sContactTickTime) {
			// Nothing under our feet
			action = PlayerData::Root_90;

			// Our feet are on something
			// Pick animation that is the best fit for our current velocity.
			// Assumes that root is the first animation in the list.
			VectorF vel;
			mWorldToObj.mulV(mVelocity,&vel);
			for (U32 i = PlayerData::Root_0; i < PlayerData::Root_315+1; i++)
			{
				PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
				if (anim.sequence != -1 && anim.speed) 
				{
					if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
						action = i;
						forward = true;
						break;
					}
				}
			}
		}
		else
		{

			action = PlayerData::Root_90;

			// Our feet are on something
			// Pick animation that is the best fit for our current velocity.
			// Assumes that root is the first animation in the list.
			VectorF vel;
			mWorldToObj.mulV(mVelocity,&vel);
			for (U32 i = PlayerData::Root_0; i < PlayerData::Root_315+1; i++)
			{
				PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
				if (anim.sequence != -1 && anim.speed) 
				{
					if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
						action = i;
						forward = true;
						break;
					}
				}
			}
			// Our feet are on something
			// Pick animation that is the best fit for our current velocity.
			// Assumes that root is the first animation in the list.
			mWorldToObj.mulV(mVelocity,&vel);
			for (U32 i = PlayerData::Run_0; i < PlayerData::Run_315+1; i++)
			{
				PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
				if (anim.sequence != -1 && anim.speed) 
				{
					if(anim.dir.x==XDIR && anim.dir.y==YDIR){
						if(XDIR!=0||YDIR!=0){
							PRE_XDIR=XDIR;
							PRE_YDIR=YDIR;
						}
						action = i;
						forward = true;
						break;
					}
				}
			}
		}
	}
	else if ( mPose == CrouchPose )
	{
		VectorF vel;
		mWorldToObj.mulV(mVelocity,&vel);

		// Our feet are on something
		// Pick animation that is the best fit for our current velocity.
		// Assumes that root is the first animation in the list.
		mWorldToObj.mulV(mVelocity,&vel);
		for (U32 i = PlayerData::Crouch_0; i < PlayerData::Crouch_315+1; i++)
		{
			PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
			if (anim.sequence != -1 && anim.speed) 
			{
				if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
					action = i;
					forward = true;
					break;
				}
			}
		}


		fsp = true;

		// Our feet are on something
		// Pick animation that is the best fit for our current velocity.
		// Assumes that root is the first animation in the list.
		mWorldToObj.mulV(mVelocity,&vel);
		for (U32 i = PlayerData::CrouchWalk_0; i < PlayerData::CrouchWalk_315+1; i++)
		{
			PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
			if (anim.sequence != -1 && anim.speed) 
			{
				if(anim.dir.x==XDIR && anim.dir.y==YDIR){
					if(XDIR!=0||YDIR!=0){
						PRE_XDIR=XDIR;
						PRE_YDIR=YDIR;
					}
					action = i;
					forward = true;
					break;
				}
			}
		}
	}
	else if ( mPose == PronePose )
	{
		VectorF vel;
		mWorldToObj.mulV(mVelocity,&vel);

		// Our feet are on something
		// Pick animation that is the best fit for our current velocity.
		// Assumes that root is the first animation in the list.
		mWorldToObj.mulV(mVelocity,&vel);
		for (U32 i = PlayerData::ProneRoot_0; i < PlayerData::ProneRoot_315+1; i++)
		{
			PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
			if (anim.sequence != -1 && anim.speed) 
			{
				if(anim.dir.x==PRE_XDIR && anim.dir.y==PRE_YDIR){
					action = i;
					forward = true;
					break;
				}
			}
		}



		fsp = true;

		// Our feet are on something
		// Pick animation that is the best fit for our current velocity.
		// Assumes that root is the first animation in the list.
		mWorldToObj.mulV(mVelocity,&vel);
		for (U32 i = PlayerData::ProneWalk_0; i < PlayerData::ProneWalk_315+1; i++)
		{
			PlayerData::ActionAnimation &anim = mDataBlock->actionList[i];
			if (anim.sequence != -1 && anim.speed) 
			{
				if(anim.dir.x==XDIR && anim.dir.y==YDIR){
					if(XDIR!=0||YDIR!=0){
						PRE_XDIR=XDIR;
						PRE_YDIR=YDIR;
					}
					action = i;
					forward = true;
					break;
				}
			}
		}
	}
	setActionThread(action,forward,false,false,fsp);
}


void Player::onUnmount( ShapeBase *obj, S32 node )
{
	// Reset back to root position during dismount.
	setActionThread(PlayerData::Root_90,true,false,false);

	// Re-orient the player straight up
	Point3F pos,vec;
	getTransform().getColumn(1,&vec);
	getTransform().getColumn(3,&pos);
	Point3F rot(0.0f,0.0f,-mAtan2(-vec.x,vec.y));
	setPosition(pos,rot);

	// Parent function will call script
	Parent::onUnmount( obj, node );
}






Video:






Let me know if you have problems implementing this.
Page«First 1 2 Next»
#21
04/09/2010 (6:07 am)
@yadhi:

Make sure your packupdate and unpackupdate line up EXACTLY (what goes into the pack, must be unpacked in the exact same way). Without a stack trace it is a bit difficult to say why exactly you got the error, but not matching the streams is a common way to get a crash there.
#22
04/11/2010 (9:46 pm)
i have check the line, the sequence between unpackupdate and packupdate has matched exactly, i've try to change the value of ActionAnimBits
from Jet_315 to 9, and engine not crash, but the strange happen, the animation sometime not updated to other client.

now, my big question is what value of ActionAnimBits it should be? is there a formula for define the value of this ?
#23
04/20/2010 (12:09 am)
Having a lot of trouble getting this working in T3D Pro 1.1 Beta 1.
When I step left or any diagonal no animation is played (and I have all the required animations working).
Been debugging and having a helluv a time tracking it down.
#24
04/20/2010 (12:15 am)
It doesn't seem to change state when I move. :/
#25
04/20/2010 (2:20 am)
get the demo of Beyond compair and diff these files.

my files from 1.1

The tori.cs is my player cs file for animations.


There are some really big problems with doing 8 way this way, I really want to figure out the practical way of doing this with out all of these animations. and only needing one forward vector and only changing the rotation axis.
#26
04/21/2010 (3:13 pm)
Ok, this resource works multiplayer out of the box with 2 minor changes:
NumExtraActionAnims = 1024 - NumTableActionAnims,//512
	  NumActionAnims = NumTableActionAnims + NumExtraActionAnims,
      ActionAnimBits = 10,
      NullAnimation = (1 << ActionAnimBits) - 1
Some good info about this is here.

and move:
F32 YDIR;
F32 XDIR;
F32 PRE_YDIR;
F32 PRE_XDIR;
to player.h in public member of class Player (as per Yadhi and Kevin).

If you are testing and just copying old anims, make sure the ground transforms are removed or correct or the animation may not play (I used DSQ TWeaker to remove the XForms and change the internal names).
#27
11/18/2010 (5:32 pm)
download link broken.
Who do you got the file?


#28
11/18/2010 (6:46 pm)
Hey guys,
don't forget to include these two fixes.Client side animations sometimes are not set due to wrong animation bit check.
Go to the T3D 1.1 beta3 bugs section and find "T3D 1.1 Beta 3 - Player::setActionThread - LOGGED"
#29
01/29/2011 (11:04 pm)
So I have been trying to get this working in T3D 1.1 Beta 3 but I have ran into a problem. I got it to compile with no errors but when I start the game and run forward. The animation keeps playing after I stop and even if I move in another direction. Any ideas on what's going on?

EDIT: Note to self, Make sure to have all the animations listed. If you don't, you run into problems like I had. So the resource works like a charm. It was my fault.
Page«First 1 2 Next»