1 using System;
    2 using System.Collections.Generic;
    3 using System.Text;
    4 using Microsoft.Xna.Framework.Graphics;
    5 using Microsoft.Xna.Framework;
    6 
    7 namespace BrawlerGame
    8 {
    9     public class SpriteAnimation
   10     {
   11         #region Declarations
   12         // The texture that holds the images for this sprite
   13         Texture2D t2dTexture;
   14 
   15         // True if animations are being played
   16         bool bAnimating = true;
   17         bool allowMove = true;
   18 
   19         // If set to anything other than Color.White, will colorize
   20         // the sprite with that color.
   21         Color colorTint = Color.White;
   22 
   23         // Screen Position of the Sprite
   24         Vector2 v2Position = new Vector2(0, 0);
   25         Vector2 v2LastPosition = new Vector2(0, 0);
   26 
   27         // Dictionary holding all of the FrameAnimation objects
   28         // associated with this sprite.
   29         Dictionary<string, FrameAnimation> faAnimations = new Dictionary<string, FrameAnimation>();
   30 
   31         // Which FrameAnimation from the dictionary above is playing
   32         string sCurrentAnimation = null;
   33 
   34         // If true, the sprite will automatically rotate to align itself
   35         // with the angle difference between it's new position and
   36         // it's previous position.  In this case, the 0 rotation point
   37         // is to the right (so the sprite should start out facing to
   38         // the right.
   39         bool bRotateByPosition = false;
   40 
   41         // How much the sprite should be rotated by when drawn
   42         // Value is in Radians, and 0 indicates no rotation.
   43         float fRotation = 0f;
   44 
   45         // Calcualted center of the sprite
   46         Vector2 v2Center;
   47 
   48         // Calculated width and height of the sprite
   49         int iWidth;
   50         int iHeight;
   51 
   52         // Scale of Sprite
   53         float fScale = 1f;
   54 
   55         // Flip image
   56         byte flipImage = 0;
   57 
   58         // Used to add damage to entity at the END of the animation
   59         public bool bDamage = false;
   60         #endregion
   61 
   62 
   63         #region Properties
   64         /// <summary>
   65         /// Vector2 representing the position of the sprite's upper left
   66         /// corner pixel.
   67         /// </summary>
   68         public Vector2 Position
   69         {
   70             get { return v2Position; }
   71             set
   72             {
   73                 v2LastPosition = v2Position;
   74                 v2Position = value;
   75                 UpdateRotation();
   76             }
   77         }
   78 
   79         /// <summary>
   80         /// The X position of the sprite's upper left corner pixel.
   81         /// </summary>
   82         public float PositionX
   83         {
   84             get { return v2Position.X; }
   85             set
   86             {
   87                 v2LastPosition.X = v2Position.X;
   88                 v2Position.X = value;
   89                 UpdateRotation();
   90             }
   91         }
   92 
   93         /// <summary>
   94         /// The Y position of the sprite's upper left corner pixel.
   95         /// </summary>
   96         public float PositionY
   97         {
   98             get { return v2Position.Y; }
   99             set
  100             {
  101                 v2LastPosition.Y = v2Position.Y;
  102                 v2Position.Y = value;
  103                 UpdateRotation();
  104             }
  105         }
  106 
  107         /// <summary>
  108         /// The X position of the sprite's upper left corner pixel.
  109         /// </summary>
  110         public int X
  111         {
  112             get { return (int)v2Position.X; }
  113             set
  114             {
  115                 v2LastPosition.X = v2Position.X;
  116                 v2Position.X = value;
  117                 UpdateRotation();
  118             }
  119         }
  120 
  121         /// <summary>
  122         /// The Y position of the sprite's upper left corner pixel.
  123         /// </summary>
  124         public int Y
  125         {
  126             get { return (int)v2Position.Y; }
  127             set
  128             {
  129                 v2LastPosition.Y = v2Position.Y;
  130                 v2Position.Y = value;
  131                 UpdateRotation();
  132             }
  133         }
  134 
  135         /// <summary>
  136         /// Width (in pixels) of the sprite animation frames
  137         /// </summary>
  138         public int Width
  139         {
  140             get { return iWidth; }
  141         }
  142 
  143         /// <summary>
  144         /// Height (in pixels) of the sprite animation frames
  145         /// </summary>
  146         public int Height
  147         {
  148             get { return iHeight; }
  149         }
  150 
  151 
  152         /// <summary>
  153         /// If true, the sprite will automatically rotate in the direction
  154         /// of motion whenever the sprite's Position changes.
  155         /// </summary>
  156         public bool AutoRotate
  157         {
  158             get { return bRotateByPosition; }
  159             set { bRotateByPosition = value; }
  160         }
  161 
  162         /// <summary>
  163         /// The degree of rotation (in radians) to be applied to the
  164         /// sprite when drawn.
  165         /// </summary>
  166         public float Rotation
  167         {
  168             get { return fRotation; }
  169             set { fRotation = value; }
  170         }
  171 
  172         /// <summary>
  173         /// Screen coordinates of the bounding box surrounding this sprite
  174         /// </summary>
  175         public Rectangle BoundingBox
  176         {
  177             get { return new Rectangle(X, Y, iWidth, iHeight); }
  178         }
  179 
  180 
  181         /// <summary>
  182         /// The texture associated with this sprite.  All FrameAnimations will be
  183         /// relative to this texture.
  184         /// </summary>
  185         public Texture2D Texture
  186         {
  187             get { return t2dTexture; }
  188         }
  189 
  190         /// <summary>
  191         /// Color value to tint the sprite with when drawing.  Color.White
  192         /// (the default) indicates no tinting.
  193         /// </summary>
  194         public Color Tint
  195         {
  196             get { return colorTint; }
  197             set { colorTint = value; }
  198         }
  199 
  200         /// <summary>
  201         /// Scale of sprite
  202         /// </summary>
  203         public float Scale
  204         {
  205             get { return fScale; }
  206             set { fScale = value; }
  207         }
  208 
  209         /// <summary>
  210         /// Determined to flip image
  211         /// </summary>
  212         public byte IsFlipped
  213         {
  214             get { return flipImage; }
  215             set { flipImage = value; }
  216         }
  217 
  218         /// <summary>
  219         /// True if the sprite is (or should be) playing animation frames.  If this value is set
  220         /// to false, the sprite will not be drawn (a sprite needs at least 1 single frame animation
  221         /// in order to be displayed.
  222         /// </summary>
  223         public bool IsAnimating
  224         {
  225             get { return bAnimating; }
  226             set { bAnimating = value; }
  227         }
  228 
  229         public bool CanMove
  230         {
  231             get { return allowMove; }
  232             set { allowMove = value; }
  233         }
  234 
  235         /// <summary>
  236         /// The FrameAnimation object of the currently playing animation
  237         /// </summary>
  238         public FrameAnimation CurrentFrameAnimation
  239         {
  240             get
  241             {
  242                 if (!string.IsNullOrEmpty(sCurrentAnimation))
  243                     return faAnimations[sCurrentAnimation];
  244                 else
  245                     return null;
  246             }
  247         }
  248 
  249         /// <summary>
  250         /// The string name of the currently playing animaton.  Setting the animation
  251         /// resets the CurrentFrame and PlayCount properties to zero.
  252         /// </summary>
  253         public string CurrentAnimation
  254         {
  255             get { return sCurrentAnimation; }
  256             set
  257             {
  258                 if (faAnimations.ContainsKey(value))
  259                 {
  260                     sCurrentAnimation = value;
  261                     faAnimations[sCurrentAnimation].CurrentFrame = 0;
  262                     faAnimations[sCurrentAnimation].PlayCount = 0;
  263                 }
  264             }
  265         }
  266         #endregion
  267 
  268 
  269         #region Constructors
  270         public SpriteAnimation(Texture2D Texture)
  271         {
  272             t2dTexture = Texture;
  273         }
  274         #endregion
  275 
  276 
  277         #region Methods
  278         /// <summary>
  279         /// Updates the rotation of the sprite based on it's "last known" position
  280         /// if the "bRotatebyPosition" parameter is true.
  281         /// </summary>
  282         void UpdateRotation()
  283         {
  284             if (bRotateByPosition)
  285             {
  286                 if (IsFlipped == 0)
  287                 {
  288                     flipImage = 0;
  289                 }
  290                 else
  291                     flipImage = 1;
  292             }
  293         }
  294 
  295         /// <summary>
  296         /// Add an animation to the animations dictionary.
  297         /// </summary>
  298         /// <param name="Name">Sprite-specific name of the animation.</param>
  299         /// <param name="X">X Location of the upper right corner of the first frame of the animation</param>
  300         /// <param name="Y">Y Location of the upper right corner of the first frame of the animation</param>
  301         /// <param name="Width">Width of the animation's frames</param>
  302         /// <param name="Height">Height of the animation's frames</param>
  303         /// <param name="Frames">Number of frames in the animation</param>
  304         /// <param name="FrameLength">Length (in seconds) to display each frame of the animation</param>
  305         public void AddAnimation(string Name, int X, int Y, int Width, int Height, int Frames, float FrameLength)
  306         {
  307             faAnimations.Add(Name, new FrameAnimation(X, Y, Width, Height, Frames, FrameLength));
  308             iWidth = Width;
  309             iHeight = Height;
  310             v2Center = new Vector2(iWidth / 2, iHeight / 2);
  311         }
  312 
  313         /// <summary>
  314         /// Add an animation to the animations dictionary.
  315         /// </summary>
  316         /// <param name="Name">Sprite-specific name of the animation.</param>
  317         /// <param name="X">X Location of the upper right corner of the first frame of the animation</param>
  318         /// <param name="Y">Y Location of the upper right corner of the first frame of the animation</param>
  319         /// <param name="Width">Width of the animation's frames</param>
  320         /// <param name="Height">Height of the animation's frames</param>
  321         /// <param name="Frames">Number of frames in the animation</param>
  322         /// <param name="NextAnimation">Name of the animation to play after this animation ends</param>
  323         public void AddAnimation(string Name, int X, int Y, int Width, int Height, int Frames, float FrameLength, string NextAnimation)
  324         {
  325             faAnimations.Add(Name, new FrameAnimation(X, Y, Width, Height, Frames, FrameLength, NextAnimation));
  326             iWidth = Width;
  327             iHeight = Height;
  328             v2Center = new Vector2(iWidth / 2, iHeight / 2);
  329         }
  330 
  331         /// <summary>
  332         /// Returns a FrameAnimation object associated with this sprite via 
  333         /// the animation name.
  334         /// </summary>
  335         /// <param name="Name"></param>
  336         /// <returns></returns>
  337         public FrameAnimation GetAnimationByName(string Name)
  338         {
  339             if (faAnimations.ContainsKey(Name))
  340             {
  341                 return faAnimations[Name];
  342             }
  343             else
  344             {
  345                 return null;
  346             }
  347         }
  348 
  349         public void MoveBy(float x, float y)
  350         {
  351             v2LastPosition = v2Position;
  352             v2Position.X += x;
  353             v2Position.Y += y;
  354             UpdateRotation();
  355         }
  356         #endregion
  357 
  358 
  359         #region Update
  360         public void Update(GameTime gameTime)
  361         {
  362             if (bAnimating)
  363             {
  364                 // If there is not a currently active animation
  365                 if (CurrentFrameAnimation == null)
  366                 {
  367                     // Make sure we have an animation associated with this sprite
  368                     if (faAnimations.Count > 0)
  369                     {
  370                         // Set the active animation to the first animation
  371                         // associated with this sprite
  372                         string[] sKeys = new string[faAnimations.Count];
  373                         faAnimations.Keys.CopyTo(sKeys, 0);
  374                         CurrentAnimation = sKeys[0];
  375                     }
  376                     else
  377                     {
  378                         return;
  379                     }
  380                 }
  381 
  382                 if (CurrentFrameAnimation.PlayCount > 0)
  383                 {
  384                     // Update damge
  385                     bDamage = true;
  386 
  387                     // Check to see if there is a "followup" animation named for this animation
  388                     if (!String.IsNullOrEmpty(CurrentFrameAnimation.NextAnimation))
  389                     {
  390                         // If it has, set up the next animation
  391                         CurrentAnimation = CurrentFrameAnimation.NextAnimation;
  392                     }
  393                     string[] sKeys = new string[faAnimations.Count];
  394                     faAnimations.Keys.CopyTo(sKeys, 0);
  395                     CurrentAnimation = sKeys[0];
  396                 }
  397                 else
  398                     bDamage = false;
  399 
  400                 CurrentFrameAnimation.Update(gameTime);
  401             }
  402         }
  403         #endregion
  404 
  405 
  406         #region Draw
  407         public void Draw(SpriteBatch spriteBatch, int XOffset, int YOffset)
  408         {
  409             if (bAnimating)
  410             {
  411                 SpriteEffects spriteEffect = SpriteEffects.None;
  412                 if (flipImage == 1)
  413                 {
  414                     spriteEffect = SpriteEffects.FlipHorizontally;
  415                 }
  416                 spriteBatch.Draw(t2dTexture, (v2Position + new Vector2(XOffset, YOffset) + v2Center),
  417                                      CurrentFrameAnimation.FrameRectangle, colorTint,
  418                                      fRotation, v2Center, fScale, spriteEffect, 0);
  419             }
  420         }
  421         #endregion
  422 
  423     }
  424 }