Floating Score SpriteFont Class

From XNAWiki
Jump to: navigation, search

In many 3D and 2D games when an enemy is destroyed, a score value appears at the incident. The score then floats (typically upwards) on the screen for a set distance or time and then disappears. This class supports that behavior. Enjoy!

/* Class: SpriteFontFloatScore 
 * Author: Michael P. Scott
 * Date Created: 01/09/2009
 * Purpose: Provides "floating" scores (or simply text) that appear and disappear after a time frame.
 * 
 * Class: SpriteFontFloatScores
 * Author: Michael P. Scott
 * Date Created: 01/09/2009
 * Purpose: Encapsulates a collection of SpriteFontFloatScore(s).
 * 
 * Permissions: You may use this code in any way you see fit, including any modifications that enhance
 * the original behvior of the class.  However, please retain the original author's name.
 */ 
 
using System;  
using System.Collections;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using Microsoft.Xna.Framework;  
using Microsoft.Xna.Framework.Audio;  
using Microsoft.Xna.Framework.Content;  
using Microsoft.Xna.Framework.GamerServices;  
using Microsoft.Xna.Framework.Graphics;  
using Microsoft.Xna.Framework.Input;  
using Microsoft.Xna.Framework.Media;  
using Microsoft.Xna.Framework.Net;  
using Microsoft.Xna.Framework.Storage;  
 
namespace FloatingScore  
{  
    /// <summary>  
    /// Class useful in creating "floating scores" in a game environment.  This effect is seen in many games.  For example,  
    /// when an enemy is shot or killed in a shooter game, typically a score associated with that kill appears above the   
    /// incident.  The score then "floats" in a direction (typically upwards) and disappears after a period of time.  
    /// </summary>  
    internal class SpriteFontFloatScore  
    {
        #region Private Properties  
 
        private string _score;  
        private Vector2 _position;  
        private bool _alive;  
        private SpriteFont _spriteFont;  
        private Color _color;  
        private Vector2 _endPosition;  
        private Vector2 _startPosition;  
        private float _lifeSpan;  
        private float _lifeLeft;  
        private float _sizeTime;  
        private float _sizeTimeLeft;  
        private Vector3 _spawn3DCoordinates;  
        private Vector2 _scale;  
        private float _rotationDegrees;  
        private float _rotationRadians;  
        private float _layerDepth;  
        private bool _shadowEffect;
 
        #endregion  
 
        #region Constructors  
 
        /// <summary>  
        /// Creates a new instance of the SpriteFontFloatScore class.  
        /// </summary>  
        internal SpriteFontFloatScore()  
        {  
            this.Score = "";  
            this.Position = Vector2.Zero;  
            this.Alive = false;  
            this.SpriteFont = null;  
            this.Color = Color.White;  
            this.EndPosition = Vector2.Zero;  
            this.StartPosition = Vector2.Zero;  
            this.LifeSpan = (float)0.0;  
            this.SizeTime = (float)0.0;  
            this.Spawn3DCoordinates = Vector3.Zero;  
            this.Scale = Vector2.One;  
            this.RotationDegrees = (float)0.0;  
            this.LayerDepth = (float)0.0;  
            this.ShadowEffect = false;  
        }  
 
        /// <summary>  
        /// Creates a new instance of the SpriteFontFloatScore class, copying from the source.  
        /// </summary>  
        /// <param name="copySource">The source SpriteFontFloatScore to copy from.</param>  
        internal SpriteFontFloatScore(SpriteFontFloatScore copySource)  
        {  
            this.Score = copySource.Score;  
            this.Position = copySource.Position;  
            this.Alive = copySource.Alive;  
            this.SpriteFont = copySource.SpriteFont;  
            this.Color = copySource.Color;  
            this.EndPosition = copySource.EndPosition;  
            this.StartPosition = copySource.StartPosition;  
            this.LifeSpan = copySource.LifeSpan;  
            this.LifeLeft = copySource.LifeLeft;  
            this.SizeTime = copySource.SizeTime;  
            this.SizeTimeLeft = copySource.SizeTimeLeft;  
            this.Spawn3DCoordinates = copySource.Spawn3DCoordinates;  
            this.Scale = copySource.Scale;  
            this.RotationDegrees = copySource.RotationDegrees;  
            this.LayerDepth = copySource.LayerDepth;  
            this.ShadowEffect = copySource.ShadowEffect;  
        }
 
        #endregion  
 
        #region Property Accessors  
 
        /// <summary>  
        /// Gets/Sets the string "score" property.  This is the string text to be printed.  
        /// </summary>  
        internal string Score  
        {  
            get { return _score; }  
            set { _score = value; }  
        }  
 
        /// <summary>  
        /// Gets the Vector2 Position property.  This is the current Vector2 coordinates of the string text.  
        /// </summary>  
        internal Vector2 Position  
        {  
            get { return _position; }  
            private set { _position = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the Vector2 Start Position property.  This is the starting position Vector2 coordinates of the string text.  
        /// </summary>  
        internal Vector2 StartPosition  
        {  
            get { return _startPosition; }  
            set { _startPosition = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the Vector2 End Position property.  This is the ending position Vector2 coordinates of the string text.  
        /// </summary>  
        internal Vector2 EndPosition  
        {  
            get { return _endPosition; }  
            set { _endPosition = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the bool Alive property.  During the UpdateAnimatedPosition method, the LifeLeft property is  
        /// reduced by the amout of gameTime elapsed and the Position property is updated according to the direction  
        /// of the floating score.  When either the LifeLeft reaches zero or the EndPosition equals Position, the   
        /// Alive property is set to false.  
        /// </summary>  
        internal bool Alive  
        {  
            get { return _alive; }  
            set { _alive = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the SpriteFont SpriteFont property.  This is the SpriteFont used to render the string text.  
        /// </summary>  
        internal SpriteFont SpriteFont  
        {  
            get { return _spriteFont; }  
            set { _spriteFont = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the Color Color property.  This is the color used to render the string text.  
        /// </summary>  
        internal Color Color  
        {  
            get { return _color; }  
            set { _color = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the float LifeSpan property.  This is the length of GameTime the string text is to persist.  
        /// The value is expressed in terms of Milliseconds.  1 Second = 1000 Milliseconds.  
        /// </summary>  
        internal float LifeSpan  
        {  
            get { return _lifeSpan; }  
            set   
            {   
                _lifeSpan = value;  
                this.LifeLeft = value;  
            }  
        }  
 
        /// <summary>  
        /// Gets the float LifeLeft property.  This is the remaining length of GameTime the string text will continute to persist.  
        /// The value is expressed in terms of Milliseconds.  1 Second = 1000 Milliseconds.  
        /// </summary>  
        internal float LifeLeft  
        {  
            get { return _lifeLeft; }  
            private set   
            {   
                _lifeLeft = value;  
                if (_lifeLeft <= (float)0.0)  
                {  
                    _lifeLeft = (float)0.0;  
                    _alive = false;  
                }  
            }  
        }  
 
        /// <summary>  
        /// Gets/Sets the float SizeTime property.  This is the length of GameTime the string text will take to achieve its full scale size.  
        /// A value of zero results in no sizing effect, as the string text will always be rendered full-size.  
        /// The value is expressed in terms of Milliseconds.  1 Second = 1000 Milliseconds.  
        /// </summary>  
        internal float SizeTime  
        {  
            get { return this._sizeTime; }  
            set   
            {   
                this._sizeTime = value;  
                if (this._sizeTime > this._lifeSpan) this._sizeTime = this._lifeSpan;  
                this._sizeTimeLeft = this._sizeTime;  
            }  
        }  
 
        /// <summary>  
        /// Gets the float SizeTimeLeft property.  This is the length of remaining GameTime the string text will take to achieve its full scale size.  
        /// The value is expressed in terms of Milliseconds.  1 Second = 1000 Milliseconds.  
        /// </summary>  
        internal float SizeTimeLeft  
        {  
            get { return this._sizeTimeLeft; }  
            private set   
            {   
                this._sizeTimeLeft = value;  
                if (this._sizeTimeLeft <= (float)0.0) this._sizeTimeLeft = (float)0.0;  
            }  
        }  
 
        /// <summary>  
        /// Gets/Sets the Vector3 Spawn3DCoordinates property.  This is the originating game world coordinates of the string text.  
        /// This value should be set at creation time.  The value is used in conjunction with the RecalculatePositionFromCamera method.   
        /// Using the origin point, the class can determine the new world coordinates based on new camera coordinates.  
        /// This is helpful when the user rotates or moves the camera while the floating text is still persisting.  
        /// </summary>  
        internal Vector3 Spawn3DCoordinates  
        {  
            get { return _spawn3DCoordinates; }  
            set { _spawn3DCoordinates = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the Vector2 Scale property.  Use Vector2.One to retain original SpriteFont dimensions.  
        /// Scale.X can be set to increase/decrease width-wise and Scale.Y can be set to increase/decrease height-wise.  
        /// </summary>  
        internal Vector2 Scale  
        {  
            get { return this._scale; }  
            set { this._scale = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets float RotationDegrees property.  A value of zero will result in zero rotation.  
        /// The value is expressed in degrees.  
        /// </summary>  
        internal float RotationDegrees  
        {  
            get { return this._rotationDegrees; }  
            set 
            {  
                this._rotationDegrees = value;  
                this._rotationRadians = value * (MathHelper.Pi / 180);  
            }  
        }  
 
        /// <summary>  
        /// Gets the float RotationRadians property.  This is the conversion of RotationDegrees as expressed in terms of radians.  
        /// </summary>  
        internal float RotationRadians  
        {  
            get { return this._rotationRadians; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the float LayerDepth property.  This is the sorting depth of the SpriteFont.    
        /// 0.0 is Front, 1.0 is Back.  
        /// </summary>  
        internal float LayerDepth  
        {  
            get { return this._layerDepth; }  
            set { this._layerDepth = value; }  
        }  
 
        /// <summary>  
        /// Gets/Sets the bool ShadowEffect property.  If set to true, the string text is rendered twice.    
        /// The first rendering is a black color with transparency equal to the Color property.  
        /// This render occurs 3 pixels to the right and down of the Position property.    
        /// The second rendering is the string text in the color of the Color property with no offset.  
        /// </summary>  
        internal bool ShadowEffect  
        {  
            get { return this._shadowEffect; }  
            set { this._shadowEffect = value; }  
        }
 
        #endregion  
 
        #region Methods  
 
        /// <summary>  
        /// Draws the string text using the spriteBatch specified.  This method needs to be called in the XNA game.Draw method.  
        /// Only floating scores that are "Alive" are drawn.  
        /// </summary>  
        /// <param name="spriteBatch">The SpriteBatch to add draw the string text in.</param>  
        internal void Draw(SpriteBatch spriteBatch)  
        {  
            Vector2 screenOrigin = Vector2.Zero;  
            this.Draw(spriteBatch, screenOrigin);  
        }  
 
        /// <summary>  
        /// Draws the string text using the spriteBatch specified.  This method needs to be called in the XNA game.Draw method.  
        /// Only floating scores that are "Alive" are drawn.  
        /// </summary>  
        /// <param name="spriteBatch">The SpriteBatch to add draw the string text in.</param>  
        /// <param name="screenOrigin">In 2D games, an offset against the game-screen origin.  Use Vector2.Zero for no offset.</param>  
        internal void Draw(SpriteBatch spriteBatch, Vector2 screenOrigin)  
        {  
            if (!this.Alive) return;  
 
            Vector2 textOrigin = new Vector2((this.SpriteFont.MeasureString(this.Score).X * this.Scale.X) / 2, (this.SpriteFont.MeasureString(this.Score).Y * this.Scale.Y) / 2);  
            Vector2 scale = new Vector2(this.Scale.X, this.Scale.Y);  
 
            if (this.SizeTimeLeft > (float)0.0)  
            {  
                scale *= (1 - (this.SizeTimeLeft / this.SizeTime));              
            }  
 
            if (this.LifeLeft <= (float)0.25 * this.LifeSpan)  
            {  
                Microsoft.Xna.Framework.Graphics.Color drawColor = new Color(this.Color, (byte)MathHelper.Clamp((this.LifeLeft / ((float)0.25 * this.LifeSpan)) * 255, (float)0.0, (float)this.Color.A));  
 
                if (this.ShadowEffect)  
                {  
                    spriteBatch.DrawString(this.SpriteFont, this.Score, new Vector2(this.Position.X + screenOrigin.X + 3, this.Position.Y + screenOrigin.Y + 3), new Color(Color.Black, drawColor.A), this.RotationRadians, textOrigin, scale, SpriteEffects.None, this.LayerDepth + (float)0.01);  
                }  
                spriteBatch.DrawString(this.SpriteFont, this.Score, new Vector2(this.Position.X + screenOrigin.X, this.Position.Y + screenOrigin.Y), drawColor, this.RotationRadians, textOrigin, scale, SpriteEffects.None, this.LayerDepth);  
            }  
            else 
            {  
                if (this.ShadowEffect)  
                {  
                    spriteBatch.DrawString(this.SpriteFont, this.Score, new Vector2(this.Position.X + screenOrigin.X + 3, this.Position.Y + screenOrigin.Y + 3), new Color(Color.Black, this.Color.A), this.RotationRadians, textOrigin, scale, SpriteEffects.None, this.LayerDepth + (float)0.01);  
                }  
                spriteBatch.DrawString(this.SpriteFont, this.Score, new Vector2(this.Position.X + screenOrigin.X, this.Position.Y + screenOrigin.Y), this.Color, this.RotationRadians, textOrigin, scale, SpriteEffects.None, this.LayerDepth);  
            }  
        }  
 
        /// <summary>  
        /// Updates the position of the floating score string text.  This method needs to be called in the XNA game.Update method.  
        /// Only floating scores that are "Alive" are updated.  
        /// </summary>  
        /// <param name="gameTime">The gameTime value provided by the XNA framework in the game.Update method.</param>  
        internal void UpdateAnimatedPosition(GameTime gameTime)  
        {  
            this.LifeLeft -= gameTime.ElapsedGameTime.Milliseconds;  
            this.SizeTimeLeft -= gameTime.ElapsedGameTime.Milliseconds;  
 
            if (!this.Alive) return;  
 
            float x = (float)Math.Abs(this.StartPosition.X - this.EndPosition.X);  
            float y = (float)Math.Abs(this.StartPosition.Y - this.EndPosition.Y);  
 
            x *= (((this.LifeSpan) - (this.LifeLeft)) / (this.LifeSpan));  
 
            if (this.EndPosition.X > this.Position.X)  
            {  
                _position.X = this.StartPosition.X + x;  
                _position.X = MathHelper.Clamp(_position.X, this.StartPosition.X, this.EndPosition.X);  
            }  
            else 
            {  
                _position.X = this.StartPosition.X - x;  
                _position.X = MathHelper.Clamp(_position.X, this.EndPosition.X, this.StartPosition.X);  
            }  
 
            y *= (((this.LifeSpan) - (this.LifeLeft)) / (this.LifeSpan));  
 
            if (this.StartPosition.Y <= this.EndPosition.Y)  
            {  
                if (this.EndPosition.Y > this.Position.Y)  
                {  
                    _position.Y = this.StartPosition.Y + y;  
                    _position.Y = MathHelper.Clamp(_position.Y, this.StartPosition.Y, this.EndPosition.Y);  
                }  
                else 
                {  
                    _position.Y = this.StartPosition.Y - y;  
                    _position.Y = MathHelper.Clamp(_position.Y, this.EndPosition.Y, this.StartPosition.Y);  
                }  
            }  
            else 
            {  
                if (this.StartPosition.Y > this.Position.Y)  
                {  
                    _position.Y = this.StartPosition.Y - y;  
                    _position.Y = MathHelper.Clamp(_position.Y, this.EndPosition.Y, this.StartPosition.Y);  
                }  
                else 
                {  
                    _position.Y = this.StartPosition.Y + y;  
                    _position.Y = MathHelper.Clamp(_position.Y, this.StartPosition.Y, this.EndPosition.Y);  
                }  
            }  
 
            if (this.EndPosition.Equals(this.Position) && !this.EndPosition.Equals(this.StartPosition)) this.Alive = false;  
        }  
 
        /// <summary>  
        /// Recalculates string text position in relation to any camera adjustments.  The Spawn3DCoordinates property must contain  
        /// the origin of the string text at creation time.  
        /// Only floating scores that are "Alive" are recalculated.  
        /// </summary>  
        /// <param name="graphics">The GraphicsDeviceManager with the appropriate Viewport setting.  The Project method is  
        /// used in conjunction with the Spawn3DCoordinates property to calculate the new origin.  Then, the current Position is   
        /// determined relatively.</param>  
        /// <param name="cmaeraProjectionMatrix">The Matrix of the Projection Matrix of the camera.  Used with the  
        /// Project method of the GraphicsDeviceManager.</param>  
        /// /// <param name="cmaeraViewMatrix">The Matrix of the View Matrix of the camera.  Used with the  
        /// Project method of the GraphicsDeviceManager.</param>  
        internal void RecalculatePositionFromCamera(GraphicsDeviceManager graphics, Matrix cameraProjectionMatrix, Matrix cameraViewMatrix)  
        {  
            if (!this.Alive) return;  
 
            Vector3 newPosition = graphics.GraphicsDevice.Viewport.Project(this.Spawn3DCoordinates, cameraProjectionMatrix, cameraViewMatrix, Matrix.Identity);  
 
            Vector2 scoreStartPosition = new Vector2(newPosition.X, newPosition.Y);  
            Vector2 relative = this.StartPosition - this.EndPosition;  
            Vector2 scoreEndPosition = new Vector2(scoreStartPosition.X + relative.X, scoreStartPosition.Y + relative.Y);  
 
            this.StartPosition = scoreStartPosition;  
            this.EndPosition = scoreEndPosition;  
 
            UpdateAnimatedPosition(new GameTime());  
        }
 
        #endregion  
    }  
 
    /// <summary>  
    /// Class that contains methods operating over more than one SpriteFontFloatScore class.  
    /// </summary>  
    internal class SpriteFontFloatScores : IEnumerable  
    {
        #region Private Properties  
 
        private ArrayList _spriteFontFloatScores;
 
        #endregion  
 
        #region Constructors  
 
        /// <summary>  
        /// Creates a new empty set of floating scores.  
        /// </summary>  
        internal SpriteFontFloatScores()  
        {  
            _spriteFontFloatScores = new ArrayList();  
        }  
 
        /// <summary>  
        /// Creates a set of floating scores, copying from the source scores.  
        /// </summary>  
        /// <param name="copySource">Collection of SpriteFontFloatScore(s) to replicate.</param>  
        internal SpriteFontFloatScores(SpriteFontFloatScores copySource)  
            : this()  
        {  
            foreach (SpriteFontFloatScore entry in copySource)  
            {  
                SpriteFontFloatScore newEntry = new SpriteFontFloatScore(entry);  
                this.Add(newEntry);  
            }  
        }
 
        #endregion  
 
        #region Indexers  
 
        /// <summary>  
        /// Provides indexer support.  
        /// </summary>  
        /// <param name="index">Zero-based index of the collection retrieve.</param>  
        /// <returns>The SpriteFontFloatScore at the specified index, or null if not found.</returns>  
        internal SpriteFontFloatScore this[int index]  
        {  
            get 
            {  
                try 
                {  
                    return (SpriteFontFloatScore)_spriteFontFloatScores[index];  
                }  
                catch 
                {  
                    return null;  
                }  
            }  
        }
 
        #endregion  
 
        #region Methods  
 
        /// <summary>  
        /// Adds one or more new SpriteFontFloatScore(s) to the collection.  
        /// </summary>  
        /// <param name="spriteFontFloatScore">The SpriteFontFloatScore to add to the collection.</param>  
        /// <returns>The integer index of the newly added element.</returns>  
        internal int Add(SpriteFontFloatScore spriteFontFloatScore)  
        {  
            _spriteFontFloatScores.Add(spriteFontFloatScore);  
            return _spriteFontFloatScores.Count;  
        }  
 
        /// <summary>  
        /// Adds one or more new SpriteFontFloatScore(s) to the collection.  
        /// </summary>  
        /// <param name="spriteFontFloatScoreList">A list of two or more comma-delimited SpriteFontFloatScore(s) to   
        /// add to the collection.  You can also specify an array of SpriteFontFloatScore(s).</param>  
        /// <returns>The array of integers representing the indices of the newly added element(s).</returns>  
        internal int[] Add(params SpriteFontFloatScore[] spriteFontFloatScoreList)  
        {  
            int[] returnInts = new int[spriteFontFloatScoreList.Length];  
 
            for (int i = 0; i < spriteFontFloatScoreList.Length; i++)  
            {  
                returnInts[i] = _spriteFontFloatScores.Add(spriteFontFloatScoreList[i]);  
            }  
 
            return returnInts;  
        }  
 
        /// <summary>  
        /// Removes one SpriteFontFloatScore from the collection.  
        /// </summary>  
        /// <param name="index">Zero-based int index of the score to remove.</param>  
        internal void Remove(int index)  
        {  
            _spriteFontFloatScores.RemoveAt(index);  
        }  
 
        /// <summary>  
        /// Removes one or more SpriteFontFloatScore(s) from the collection.  
        /// </summary>  
        /// <param name="index">Zero-based comma-delimited list of int indices of the score(s) to remove.  
        /// You can also specify an array of indices.</param>  
        internal void Remove(params int[] indexList)  
        {  
            for (int i = 0; i < indexList.Length; i++)  
            {  
                _spriteFontFloatScores.RemoveAt(indexList[i]);  
            }  
        }  
 
        /// <summary>  
        /// Removes one SpriteFontFloatScore from the collection.  
        /// </summary>  
        /// <param name="spriteFontFloatScore">The object to remove from the collection.  The object will  
        /// be searched for and removed, if present.</param>  
        internal void Remove(SpriteFontFloatScore spriteFontFloatScore)  
        {  
            _spriteFontFloatScores.Remove(spriteFontFloatScore);  
        }  
 
        /// <summary>  
        /// Removes one or more SpriteFontFloatScore(s) from the collection.  
        /// </summary>  
        /// <param name="spriteFontFloatScore">The comma-delimited list of object(s) to remove from the collection.  The object(s) will  
        /// be searched for and removed, if present.  You can also specify an array of objects.</param>  
        internal void Remove(params SpriteFontFloatScore[] spriteFontFloatScoreList)  
        {  
            for (int i = 0; i < spriteFontFloatScoreList.Length; i++)  
            {  
                _spriteFontFloatScores.Remove(spriteFontFloatScoreList[i]);  
            }  
        }  
 
        /// <summary>  
        /// Clears the entire collection of floating scores.  
        /// </summary>  
        internal void Clear()  
        {  
            _spriteFontFloatScores.Clear();  
        }  
 
        /// <summary>  
        /// Provides C# foreach support.  
        /// </summary>  
        /// <returns>Enumerator useful in the foreach statement.</returns>  
        IEnumerator IEnumerable.GetEnumerator()  
        {  
            return _spriteFontFloatScores.GetEnumerator();  
        }  
 
        /// <summary>  
        /// Updates all positions of the SpriteFontFloatScore(s) in the collection.  This method needs to be called in the XNA game.Update method.  
        /// Only floating scores that are "Alive" are updated.  Any floating scores not "Alive" are automatically removed  
        /// from the collection.  
        /// </summary>  
        /// <param name="gameTime">The gameTime value provided by the XNA framework in the game.Update method.</param>  
        internal void UpdateAllAnimatedPositions(GameTime gameTime)  
        {  
            bool restart;  
            do 
            {  
                restart = false;  
                foreach (SpriteFontFloatScore floatScore in this)  
                {  
                    floatScore.UpdateAnimatedPosition(gameTime);  
                    if (!floatScore.Alive)  
                    {  
                        this.Remove(floatScore);  
                        restart = true;  
                        break;  
                    }  
                }  
            }  
            while (restart);  
        }  
 
        /// <summary>  
        /// Draws all the string text in the collection using the spriteBatch specified.  This method needs to be called in the XNA game.Draw method.  
        /// Only floating scores that are "Alive" are drawn.  
        /// </summary>  
        /// <param name="spriteBatch">The SpriteBatch to add draw the string text in.</param>  
        internal void DrawAll(SpriteBatch spriteBatch)  
        {  
            foreach (SpriteFontFloatScore floatScore in this)  
            {  
                floatScore.Draw(spriteBatch);  
            }  
        }  
 
        /// <summary>  
        /// Draws all the string text in the collection using the spriteBatch specified.  This method needs to be called in the XNA game.Draw method.  
        /// Only floating scores that are "Alive" are drawn.  
        /// </summary>  
        /// <param name="spriteBatch">The SpriteBatch to add draw the string text in.</param>  
        /// <param name="screenOrigin">In 2D games, an offset against the game-screen origin.  Use Vector2.Zero for no offset.</param>  
        internal void DrawAll(SpriteBatch spriteBatch, Vector2 screenOrigin)  
        {  
            foreach (SpriteFontFloatScore floatScore in this)  
            {  
                floatScore.Draw(spriteBatch, screenOrigin);  
            }  
        }  
 
        /// <summary>  
        /// Recalculates all string text positions in the collection in relation to any camera adjustments.  The Spawn3DCoordinates property must contain  
        /// the origin of the string text at creation time.  
        /// Only floating scores that are "Alive" are recalculated.  
        /// </summary>  
        /// <param name="graphics">The GraphicsDeviceManager with the appropriate Viewport setting.  The Project method is  
        /// used in conjunction with the Spawn3DCoordinates property to calculate the new origin.  Then, the current Position is   
        /// determined relatively.</param>  
        /// <param name="cmaeraProjectionMatrix">The Matrix of the Projection Matrix of the camera.  Used with the  
        /// Project method of the GraphicsDeviceManager.</param>  
        /// /// <param name="cmaeraViewMatrix">The Matrix of the View Matrix of the camera.  Used with the  
        /// Project method of the GraphicsDeviceManager.</param>  
        internal void RecalculateAllPositionsFromCamera(GraphicsDeviceManager graphics, Matrix cameraProjectionMatrix, Matrix cameraViewMatrix)  
        {  
            foreach (SpriteFontFloatScore floatScore in this)  
            {  
                floatScore.RecalculatePositionFromCamera(graphics, cameraProjectionMatrix, cameraViewMatrix);  
            }  
        }
 
        #endregion  
    }  
}