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
player.cpp
Line 578
Add any where above "void Player::updateMove(const Move* move)"
Inside "void Player::updateMove(const Move* move)"
Video:
Let me know if you have problems implementing this.
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.
About the author
Riding Solo since 2005. Current Project: Fated World 2005-Present RPG Engine Tool Kit - Now available.
#22
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 ?
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 ActionAnimBitsfrom 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
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.
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
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.
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
and move:
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).
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) - 1Some 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).
#28
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"
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
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.
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.
Torque 3D Owner Jameson Bennett
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.