Game Development Community

dev|Pro Game Development Curriculum

Working with pickActionAnimation()

by Erik Madison · 10/31/2005 (2:00 pm) · 6 comments

The current method of choosing your main action animation bases it's decision on the animations speed and the players velocity. While it works, and is possibly the more efficient method (I'm not a pro, I don't know), it's also extremely confusing to follow. And, personally, I've never managed to get my animation speeds nor ground transform changes to match the ingame velocity properly, which is how you would switch from a walk to a run.

Here's the current method:
for (i = 1; i < PlayerData::NumMoveActionAnims; i++) {
			      PlayerData::ActionAnimation &anim = mDataBlock->actionList[ i ];
			      if (anim.sequence != -1 && anim.speed) {
			         F32 d = mDot(vel, anim.dir);
			         if (d > curMax) {
			            curMax = d;
			            action = i;
			            forward = true;
			         } else {
			            // Special case, re-use slide left animation to slide right
			            if (i == PlayerData::SideLeftAnim && -d > curMax) {
			               curMax = -d;
			               action = i;
			               forward = false;
			            }
			         }
			      }
			   }
And here's my version: Like I said, it may not be quite as efficient, but its a whole lot more readable, and thus allows me to insert and check for any conditions I wish.
bool sprinting = vel.y > mDataBlock->maxForwardSpeed; // optional

			if (!vel.len() || vel.len() < .01) {  // anti twitch. If on a slope, they want to move 
				action = PlayerData::RootAnim;    // just a little bit. Slope code here?
				forward = false;
			} else if (abs(vel.y) > abs(vel.x)) { // forward/back
				if (sprinting && vel.y) {
					action = PlayerData::RunForwardAnim;
					forward = true;
					//Con::errorf("SPRINT %f %f", vel.x, vel.y);
				} else if (vel.y > 0.0) {
					action = PlayerData::WalkForwardAnim;
					forward = true;
					//Con::errorf("WALK %f %f", vel.x, vel.y);
				} else if (vel.y < 0.0) {
					action = PlayerData::BackBackwardAnim;
					forward = false;
					//Con::errorf("BACK %f %f", vel.x, vel.y);
				}
			} else if (vel.x < 0.0) {
				action = PlayerData::SideLeftAnim;
				forward = false;
				//Con::errorf("LEFT %f %f", vel.x, vel.y);
			} else if (vel.x > 0.0) {
				action = PlayerData::SideRightAnim;
				forward = false;
				//Con::errorf("RIGHT %f %f", vel.x, vel.y);
			}
		}
	}
A note about the anti twitch thingy; I noticed during testing that on a level ground, velocity was always 0. On even the slightest slope, there was always some velocity. Although the player never moved (small value negated by another force later on?), they would 'twitch' a bit. So for the moment, I just ignore small values. But, this has given me the idea of a better 'conform to terrain' method of standing. if val.x is the largest of the small values, they are on a left downward slope (or vv), and thus their idle animation should be one with the left foot lower than the right. If the opposite is true, we would lower the right foot instead, etc.....

And one more note; the sprinting bool is non-stock, and is just an extension of any of the multitude of player set agility, speed, etc. resources. In our case, the datablock maxspeed is set to a normal walk speed. Various factors will cause your player to exceed this, such as going downhill, or adding any form of speed multiplier. Even stock Torque will exceed your DB value in some cases.

#1
10/22/2005 (4:30 pm)
Not to step on your toes or anything, but I've added Player animations for crouch, prone, swim, and sprint by expanding on the stock animation picking. I find it works fairly well. I also have it supporting 6 directions of movement(foreward, backward, left, right, foreward right, and foreward left).
#2
11/02/2005 (2:56 pm)
Nod, you did a great job expanding my original resource, and thus now have the headache of helping everyone who can't understand it :)
This minor thing is of course completely unnessecary, but I found myself getting confused a few times when trying something new in this function. After 'indulging', the original method becomes senseless, so I simplified the whole thing and made it readable no matter what state of mind I'm in on coding nights.

Another main reason for this is we really needed numerous different velocity based animations. Those MUST be done right in the animations themselves, or the code will simply not transisition properly. I find it far easier to do the animation speeds the best I can, and then manually set the speed via code.
#3
11/19/2005 (1:39 pm)
I just wrote a post about how I switched to using this system over the stock one, but GG ate it. :( Anyway, this is a very nice resource, and it looks to work alot better than the stock code and it's alot easier to follow. Nice work!
#4
06/21/2006 (8:01 am)
Excellent resource, I've switched to this system as well. My own solution for picking animations seemed to be breaking under 1.4 and this solved my problems.
#5
11/15/2006 (10:21 pm)
Josh, where is your expanded resource?
#6
01/26/2008 (8:35 am)
Good! Much clear than the original.