The following is the complete code for the tutorial. Replace your Game class code with this to see it in action.

It is procedural in style because that lends itself to the easiest explanation of how to use the library.

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        ContentManager content;
        ModelAnimator dwarfAnimator, ground;
        Matrix view, rotation = Matrix.Identity;
        Vector3 dwarfPosition = Vector3.Zero;
        Vector3 camOffset = new Vector3(0, 15, -20);
        float blendFactor = 0;
        string state = "idle";
        AnimationController idle, walk, nod;
        AnimationController crouchDown, stayCrouched;
        AnimationController run;
        const float RUN_SPEED = .5f;
        float currentSpeed = 0;
        const float WALK_SPEED = .115f;


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            content = new ContentManager(Services);
        }


        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }


        /// <summary>
        /// Load your graphics content.  If loadAllContent is true, you should
        /// load content from both ResourceManagementMode pools.  Otherwise, just
        /// load ResourceManagementMode.Manual content.
        /// </summary>
        /// <param name="loadAllContent">Which type of content to load.</param>
        protected override void LoadGraphicsContent(bool loadAllContent)
        {
            if (loadAllContent)
            {


                Model model = content.Load<Model>("dwarfmodel");
                dwarfAnimator = new ModelAnimator(this, model);
                Viewport port = graphics.GraphicsDevice.Viewport;
                view = Matrix.CreateLookAt(
                    camOffset, Vector3.Zero, Vector3.Up);
                Matrix projection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.PiOver4, (float)port.Width / port.Height, .1f, 100000f);

                foreach (ModelMesh mesh in model.Meshes)
                {
                    foreach (BasicPaletteEffect effect in mesh.Effects)
                    {
                        effect.View = view;
                        effect.Projection = projection;
                    }
                }

                Model groundModel = content.Load<Model>("flat");
                ground = new ModelAnimator(this, groundModel);
                foreach (ModelMesh mesh in groundModel.Meshes)
                {
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        effect.View = view;
                        effect.Projection = projection;
                    }
                }
                ground.World =  Matrix.CreateScale(10, 1, 10);
  
                idle = new AnimationController(this,
                    dwarfAnimator.Animations["idle0"]);
                walk = new AnimationController(this, dwarfAnimator.Animations["walk"]);
                nod = new AnimationController(this, dwarfAnimator.Animations["nodHead"]);
                crouchDown = new AnimationController(this, dwarfAnimator.Animations["crouchDown"]);
                stayCrouched = new AnimationController(this, dwarfAnimator.Animations["stayCrouched"]);
                run = new AnimationController(this, dwarfAnimator.Animations["run"]);
                foreach (BonePose p in dwarfAnimator.BonePoses)
                    p.CurrentAnimation = idle;

            }



        }

        /// <summary>
        /// Unload your graphics content.  If unloadAllContent is true, you should
        /// unload content from both ResourceManagementMode pools.  Otherwise, just
        /// unload ResourceManagementMode.Manual content.  Manual content will get
        /// Disposed by the GraphicsDevice during a Reset.
        /// </summary>
        /// <param name="unloadAllContent">Which type of content to unload.</param>
        protected override void UnloadGraphicsContent(bool unloadAllContent)
        {
            if (unloadAllContent == true)
            {
                content.Unload();
            }
        }

        private void UpdateState(GameTime gameTime)
        {
            KeyboardState keyState = Keyboard.GetState();
            BonePoseCollection poses = dwarfAnimator.BonePoses;
            if (state == "idle")
            {
                currentSpeed = 0;
                if (keyState.IsKeyDown(Keys.W))
                {
                    blendFactor = 0;
                    state = "idleToWalk";
                }
                if (keyState.IsKeyDown(Keys.Space))
                {
                    crouchDown.ElapsedTime = 0;
                    crouchDown.IsLooping = false;
                    crouchDown.AnimationEnded += new AnimationEventHandler(crouchDown_AnimationEnded);
                    state = "crouchDown";
                }
                foreach (BonePose p in poses)
                {
                    p.CurrentAnimation = idle;
                    p.CurrentBlendAnimation = null;
                }
            }
            else if (state == "crouchDown")
            {
                foreach (BonePose p in poses)
                {
                    p.CurrentAnimation = crouchDown;
                    p.CurrentBlendAnimation = null;
                }
            }
            else if (state == "stayCrouched")
            {
                if (keyState.IsKeyDown(Keys.Space))
                {
                    crouchDown.ElapsedTime = crouchDown.AnimationSource.Duration;
                    crouchDown.SpeedFactor = 0;
                    state = "standUp";
                }
                foreach (BonePose p in poses)
                {
                    p.CurrentAnimation = stayCrouched;
                    p.CurrentBlendAnimation = null;
                }
            }
            else if (state == "standUp")
            {
                if (crouchDown.ElapsedTime - gameTime.ElapsedGameTime.Ticks <= 0)
                {
                    crouchDown.SpeedFactor = 1;
                    crouchDown.ElapsedTime = 0;
                    idle.ElapsedTime = 0;
                    state = "idle";
                }
                else
                    crouchDown.ElapsedTime -= gameTime.ElapsedGameTime.Ticks;
                foreach (BonePose p in poses)
                {
                    p.CurrentAnimation = crouchDown;
                    p.CurrentBlendAnimation = null;
                }
            }
            else if (state == "walk")
            {
                currentSpeed = WALK_SPEED;
                if (keyState.IsKeyUp(Keys.W))
                {
                    blendFactor = 0;
                    state = "walkToIdle";
                }
                if (keyState.IsKeyDown(Keys.LeftShift) && keyState.IsKeyDown(Keys.W))
                {
                    blendFactor = 0;
                    state = "walkToRun";
                    run.SpeedFactor = 0;
                }
                foreach (BonePose p in poses)
                {
                    p.CurrentAnimation = walk;
                    p.CurrentBlendAnimation = null;
                }
            }
            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.CurrentAnimation = walk;
                    p.CurrentBlendAnimation = run;
                    p.BlendFactor = blendFactor;
                }
            }
            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.CurrentAnimation = run;
                    p.CurrentBlendAnimation = null;
                }
            }
            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.CurrentAnimation = run;
                    p.CurrentBlendAnimation = walk;
                    p.BlendFactor = blendFactor;
                }
            }
            else if (state == "idleToWalk")
            {
                blendFactor += .1f;
                currentSpeed = blendFactor * WALK_SPEED;
                if (blendFactor >= 1)
                {
                    blendFactor = 1;
                    state = "walk";
                }
                foreach (BonePose p in poses)
                {
                    p.CurrentAnimation = idle;
                    p.CurrentBlendAnimation = walk;
                    p.BlendFactor = blendFactor;
                }
            }
            else if (state == "walkToIdle")
            {
                blendFactor += .1f;
                currentSpeed = (1f - blendFactor) * WALK_SPEED;
                if (blendFactor >= 1)
                {
                    blendFactor = 1;
                    state = "idle";
                }
                foreach (BonePose p in poses)
                {
                    p.CurrentAnimation = walk;
                    p.CurrentBlendAnimation = idle;
                    p.BlendFactor = blendFactor;
                }
            }
            
            BonePose weapon = dwarfAnimator.BonePoses["weapon"];
            weapon.CurrentAnimation = null;
            weapon.CurrentBlendAnimation = null;
            weapon.DefaultTransform =
                Matrix.CreateRotationX(MathHelper.Pi) *
                Matrix.CreateRotationY(MathHelper.Pi) *
                Matrix.CreateTranslation(weapon.DefaultTransform.Translation);

            BonePose head = dwarfAnimator.BonePoses["head"];
            head.CurrentAnimation = nod;
            head.CurrentBlendAnimation = null;
            
        }

        void crouchDown_AnimationEnded(AnimationController sender)
        {
                state = "stayCrouched";
                stayCrouched.ElapsedTime = 0;
                crouchDown.AnimationEnded -= crouchDown_AnimationEnded;
        }


        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            UpdateState(gameTime);
            KeyboardState keyState = Keyboard.GetState();
            if (currentSpeed > 0)
            {
                dwarfPosition += (-Matrix.CreateTranslation(0, 0, currentSpeed)
                    * rotation).Translation;
            }
            if (keyState.IsKeyDown(Keys.D))
            {
                rotation *=
                    Matrix.CreateFromAxisAngle(Vector3.Up, -MathHelper.Pi / 25.0f);

            }
            if (keyState.IsKeyDown(Keys.A))
            {
                rotation *=
                    Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi / 25.0f);
            }

            dwarfAnimator.World = rotation * Matrix.CreateTranslation(dwarfPosition);
            view = Matrix.CreateLookAt(
                 dwarfAnimator.World.Translation+camOffset,
                 dwarfAnimator.World.Translation,
                 Vector3.Up);

            foreach (ModelMesh mesh in dwarfAnimator.Model.Meshes)
                foreach (BasicPaletteEffect effect in mesh.Effects)
                    effect.View = view;

            foreach (ModelMesh mesh in ground.Model.Meshes)
                foreach (BasicEffect effect in mesh.Effects)
                    effect.View = view;

            base.Update(gameTime);
        }


        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }

Last edited Feb 14, 2007 at 7:58 AM by dastle, version 2

Comments

No comments yet.