This project is read-only.
Now we are going to allow our dwarf to run when the user presses shift and w.
  • We need to add a new run animation and a run speed variable. The goal for the run speed is to make it so that it looks like the dwarf's feet are not sliding when the run animation is playing. I found .5f to be decent enough:
    // Add this as a member variable
    const float RUN_SPEED = .5f;
  • When we are walking, if the shift and w key are down, we will start to shift to the run state. To correctly shift between these animations, we will need to manually set the time in the run animation. Add this code to the walk state:
    // Add this to the "else if (state == "walk")" block in UpdateState
    if (keyState.IsKeyDown(Keys.LeftShift) && keyState.IsKeyDown(Keys.W))
    {
        blendFactor = 0;
        state = "walkToRun";
        run.SpeedFactor = 0;
    }

  • Now for the tricky part. Luckily for us, the walk and run animation both start on a comparable frame and end on a comparable frame; they both start with the dwarf's legs in similar positions. Their durations are different, however. We will resolve this problem by scaling the elapsed time in the run animation to sync with the elapsed time in the walk animation. This can be done by the formula: run animation time = (walk animation time) / (walk animation duration) * (run animation duration). The speed is also scaled in a similar fashion. Here is the complete code for walkToRun:
    // Add this to the UpdateState method
    else if (state == "walkToRun")
    {
        blendFactor += .05f;
        if (blendFactor >= 1)
        {
            blendFactor = 1;
            run.SpeedFactor = 1;
            state = "run";
        }
        double factor = (double)walk.ElapsedTime / walk.AnimationSource.Duration;
        run.ElapsedTime = (long)(factor * run.AnimationSource.Duration);
        currentSpeed = WALK_SPEED+ blendFactor * (RUN_SPEED-WALK_SPEED);
        foreach (BonePose p in poses)
        {
            p.CurrentController = walk;
            p.CurrentBlendController = run;
            p.BlendFactor = blendFactor;
        }
    }
  • This pattern translates almost directly into the transition from run to walk. Create a new run state:
    else if (state == "run")
    {
        currentSpeed = RUN_SPEED;
        if (keyState.IsKeyUp(Keys.LeftShift))
        {
            blendFactor = 0;
            state = "runToWalk";
            walk.SpeedFactor = 0;
        }
        foreach (BonePose p in poses)
        {
            p.CurrentController = run;
            p.CurrentBlendController = null;
        }
    }
  • The runToWalk state follows the same pattern as walkToRun, except we have to remember that as the blend factor increases, the dwarf slows down:
    else if (state == "runToWalk")
    {
        blendFactor += .05f;
        if (blendFactor >= 1)
        {
            blendFactor = 1;
            walk.SpeedFactor = 1;
            state = "walk";
        }
        double factor = (double)run.ElapsedTime / run.AnimationSource.Duration;
        walk.ElapsedTime = (long)(factor * walk.AnimationSource.Duration);
        currentSpeed = WALK_SPEED + (1f - blendFactor) * (RUN_SPEED - WALK_SPEED);
        foreach (BonePose p in poses)
        {
            p.CurrentController = run;
            p.CurrentBlendController= walk;
            p.BlendFactor = blendFactor;
        }
    }
  • That's it for the tutorial! Feedback is appreciated!

Last edited Mar 7, 2007 at 9:50 PM by dastle, version 6

Comments

MorphVGX May 27, 2008 at 3:51 PM 
It may be obvious. But I want to know what exactly the SpeedFactor of an animation is, please. ^^

Catalyst Oct 2, 2007 at 8:52 PM 
You rock the casbah.