Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Phone

Developing for Windows Phone and Xbox Live : Blending Between Animations

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
8/2/2011 3:47:22 PM
Your game will most likely contain more than one animation. If you switch between animations, the location of the bones of the avatar quickly move to their new position and appear to pop from one location to another. What you really want is a way to blend from one animation to another smoothly so that the avatar does not appear to pop from one to the other.

To accomplish this, blend from using one set of transforms to the other over a short period of time. The bone’s position and rotation values need to be interpolated over the time from one animation to the other.

To demonstrate how to blend between two avatar animations, create a new type that you will use to play back the blending avatar animation.

Add a new class to the sample by right-clicking the project and selecting Add -> Class as seen in Figure 1.

Figure 1. Add new class menu

When the Add New Item dialog appears, enter the name of the new class called AnimationBlender.cs and select Add as in Figure 2.

Figure 2. Add New Item dialog

Our new class needs to be public and implement the IAvatarAnimation interface. Update the class definition for your new class to the following:

public class AnimationBlender : IAvatarAnimation

After you type the interface name, Visual Studio displays a tool tip that can be used to implement the interface with stubs as shown in Figure 3.

Figure 3. Tool tip for interface implementation

The AnimationBlender contains a two-member variable to hold references to the current and next animation that are blended together. There are two states the AnimationBlender can be in. The first is playing just a single animation, which works just like a normal AvatarAnimation. The second is a blending state where the current animation starts to blend to the next animation and ends when the blend is complete and the next animation becomes the current animation.

Add the following member variables to the new AnimationBlender class:

// The current aniamtion that is playing
private AvatarAnimation currentAnimation;
// The animation to blend to
private AvatarAnimation nextAnimation;
// The total time to blend to the next animation
private TimeSpan totalBlendTime = TimeSpan.FromMilliseconds(300);
// How far along the blend we are
private TimeSpan currentBlendTime;

We also need two variables to store the current blend time and how long the blend from one animation to the other should take.

Implement each of the properties exposed by the IAvatarAnimation interface. The first is the BoneTransfroms.

/// <summary>
/// Returns the bone transforms to use with the AvatarRenderer
/// </summary>
public ReadOnlyCollection<Matrix> BoneTransforms
{
get { return boneTransforms; }
}
private Matrix[] blendedAvatarBones = new Matrix[AvatarRenderer.BoneCount];
private ReadOnlyCollection<Matrix> boneTransforms;

Next, implement the CurrentPosition property.

/// <summary>
/// The current position in the animation
/// If we are blending then we use the next animation
/// </summary>
public TimeSpan CurrentPosition
{
get
{
TimeSpan returnValue;

if (nextAnimation != null)
returnValue = nextAnimation.CurrentPosition;
else
returnValue = currentAnimation.CurrentPosition;

// Call update to set the avatar transforms
Update(TimeSpan.Zero, false);

return returnValue;
}
set
{
if (nextAnimation != null)
nextAnimation.CurrentPosition = value;
else
currentAnimation.CurrentPosition = value;
}
}


For the CurrentPosition, use the value from the nextAnimation if you are currently blending; otherwise, use the currentAnimation value. Do the same for the Expression and Length properties.

/// <summary>
/// The current expression in the animation
/// If we are blending then we use the next animation
/// The expression is not blended so we just use
/// the next animations expression
/// </summary>
public AvatarExpression Expression
{
get
{
if (nextAnimation != null)
return nextAnimation.Expression;
else
return currentAnimation.Expression;
}
}

/// <summary>
/// The length of the animation
/// If we are blending then we use the next animation
/// </summary>
public TimeSpan Length
{
get
{
if (nextAnimation != null)
return nextAnimation.Length;
else
return currentAnimation.Length;
}
}


The constructor is quite simple and takes the initial AvatarAnimation that should be playing. Add the following constructor to the AnimationBlender:

public AnimationBlender(AvatarAnimation startingAnimation)
{
currentAnimation = startingAnimation;

boneTransforms = new ReadOnlyCollection<Matrix>(blendedAvatarBones);
}

Set the currentAnimation variable and initialize the ReadOnlyCollection of matrices that you return from the BoneTransforms property.

Now you need an animation to call when you start playing a new animation. This kicks off the blend from the current animation to the new animation. Add the following method to the AnimationBlender class:

/// <summary>
/// Starts the process of blending to the next animation
/// </summary>
public void Play(AvatarAnimation animation)
{
// Animation to blend to
nextAnimation = animation;
// Reset the animation to start at the beginning
nextAnimation.CurrentPosition = TimeSpan.Zero;

// Set our current blend position
currentBlendTime = TimeSpan.Zero;
}

First, set the nextAnimation to the one passed into the method. Then, reset the animation’s CurrentPosition so that it is at the start of the animation. This is not required, but is helpful when playing the same animations over and over again. The last line of code resets the currentBlendTime back to zero.

The final method that is required for your AnimationBlender class is to implement the Update method. The Update method is where you update the private bone transforms and perform any blending that is required. Add the following Update method to the AnimationBlender class:

/// <summary>
/// Updates the animation and performs blending to the next animation
/// </summary>
public void Update(TimeSpan elapsedAnimationTime, bool loop)
{
// Update the current animation
currentAnimation.Update(elapsedAnimationTime, loop);

// If we are not blending to an animation just copy the current transforms
if (nextAnimation == null)
{
currentAnimation.BoneTransforms.CopyTo(blendedAvatarBones, 0);
return;
}

// If we get here we are blending and we need to update the next animation
nextAnimation.Update(elapsedAnimationTime, loop);

// Update where we are in the blend
currentBlendTime += elapsedAnimationTime;
// Calculate blend factor
float blendAmount = (float)(currentBlendTime.TotalSeconds /
totalBlendTime.TotalSeconds);

// If the blend is over 1 then we are done blending
// We can just use the next animation transforms
if (blendAmount >= 1.0f)
{
// Set the current animtion and remove the target animation
currentAnimation = nextAnimation;
nextAnimation.BoneTransforms.CopyTo(blendedAvatarBones, 0);
nextAnimation = null;
return;
}

// We need to store the rotation and translation for each bone in
// the current and next animations. We then need to calculate the
// final values using the blend amount as a weight between the
// current and next values.
Quaternion currentRotation, nextRotation, blendedRotation;
Vector3 currentTranslation, nextTranslation, blendedTranslation;

// Loop all bone transforms
for (int i = 0; i < blendedAvatarBones.Length; ++i)
{
currentRotation =
Quaternion.CreateFromRotationMatrix(currentAnimation.BoneTransforms[i]);
currentTranslation = currentAnimation.BoneTransforms[i].Translation;
nextRotation =
Quaternion.CreateFromRotationMatrix(nextAnimation.BoneTransforms[i]);
nextTranslation = nextAnimation.BoneTransforms[i].Translation;

// Calculate the blended rotation
Quaternion.Slerp(ref currentRotation, ref nextRotation,
blendAmount, out blendedRotation);

// Calculate the blended translation
Vector3.Lerp(ref currentTranslation, ref nextTranslation,
blendAmount, out blendedTranslation);

// Create the blended bone matrix
blendedAvatarBones[i] = Matrix.CreateFromQuaternion(blendedRotation) *
Matrix.CreateTranslation(blendedTranslation);
}
}


That was a lot code, so let’s take a look at it piece by piece. The first section of code updates the current animation and checks whether there is blending by checking the nextAnimation for null. If there is no blending, the transforms from the current animation are copied to the blendedAvatarBones.

If there is blending, then the nextAnimation Update method is called to update the playback of the animation. The amount of time the blending has been occurring is then updated and the blendAmount is calculated. The blendAmount ranges from 0 to 1 over the course of the blend. If the value is equal to 1 or higher, then you should complete the blend and set the currentAnimation to the nextAnimation.

The final section of code is the blend between the two sets of bones from the animations. Each bone in the avatar skeleton is looped over and the matrix value for the animation frame is broken down into its rotation and translation components. The rotation value is then calculated by taking the Slerp value using the blendAmount. The translation value is then calculated with a linear transformation using Lerp. The rotation and translation are then combined to form the blended bone transform that is saved in the blendedAvatarBones array.

Now that you created the AnimationBlender class, you can use it in the ongoing sample. The game needs an array of AvatarAnimations and an instance of the AnimationBlender. You also need to save the state of the GamePad, so you can track button presses. Add the following member variables to your game class:

AvatarAnimation[] avatarAnimations;
AnimationBlender animationBlender;

GamePadState lastGamePadState;

In the game’s LoadContent method, load the multiple animations that you will use and initialize your AnimationBlender. Add the following lines of code to the LoadContent method:

// Load all of the animation
avatarAnimations = new AvatarAnimation[3];
avatarAnimations[0] = new AvatarAnimation(AvatarAnimationPreset.Celebrate);
avatarAnimations[1] = new AvatarAnimation(AvatarAnimationPreset.Clap);
avatarAnimations[2] = new AvatarAnimation(AvatarAnimationPreset.Wave);

// Create the animation blender
animationBlender = new AnimationBlender(avatarAnimations[0]);

Next, in the game’s Update method, call Update on the AnimationBlender. Also detect button presses and play different animations depending on which button you press.

// Update the animation blender
animationBlender.Update(gameTime.ElapsedGameTime, true);

// Get the current state of player one controller
GamePadState currentGamePadState = GamePad.GetState(PlayerIndex.One);
// If the user presses the X, Y, or B buttons blend to an animation
if (currentGamePadState.Buttons.X == ButtonState.Pressed &&
lastGamePadState.Buttons.X == ButtonState.Released)
{
animationBlender.Play(avatarAnimations[0]);
}
if (currentGamePadState.Buttons.Y == ButtonState.Pressed &&
lastGamePadState.Buttons.Y == ButtonState.Released)
{
animationBlender.Play(avatarAnimations[1]);
}
if (currentGamePadState.Buttons.B == ButtonState.Pressed &&
lastGamePadState.Buttons.B == ButtonState.Released)
{
animationBlender.Play(avatarAnimations[2]);
}

// Save the state so we can prevent repeat button presses
lastGamePadState = currentGamePadState;


The final step is to use the AvatarBlender to draw the avatar. Update the Draw method with the following line to draw the avatar using the blended animation:

avatarRenderer.Draw(animationBlender);

Running the sample now should enable you to press the X,Y, and B buttons to blend between animations. The blended animation should look similar to Figure 4 below:

Figure 4. Avatar drawn with a blended animation

Other -----------------
- Managing Gestures from the Silverlight for Windows Phone 7 Toolkit
- Windows Phone 7 : Handling Gestures in a Graphical Context Such as a Game Menu
- Developing for Windows Phone and Xbox Live : Modifying Avatar Lighting & Playing Multiple Animations
- Windows Phone 7 : Adding Gestures Management to Click-less Silverlight Controls
- Managing Gestures in a Silverlight Windows Phone 7 Application
- Developing for Windows Phone and Xbox Live : Introduction to Avatars (part 2) - Loading Avatar Animations with AvatarAnimation & Drawing the Avatar Using AvatarRenderer
- Developing for Windows Phone and Xbox Live : Introduction to Avatars (part 1) - Accessing Avatar Information Using AvatarDescription
- Windows Phone 7 : User Interface With Expression Blend - Customizing a Control
- Windows Phone 7 : User Interface With Expression Blend - Creating Some Cool Animation
- Windows Phone 7 : User Interface With Expression Blend - Changing the Skin of Your App
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server