Browse Source

Added Flocking demo

Dominique Louis 13 years ago
parent
commit
e2b63c02d6

+ 198 - 0
Flocking/Animals/Animal.cs

@@ -0,0 +1,198 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Animal.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+#endregion
+
+namespace Flocking
+{
+    public enum AnimalType
+    {
+        // no type
+        Generic,
+        // flies around and reacts
+        Bird,
+        // controled by teh thumbstick, birds flee from it
+        Cat
+    }
+    /// <summary>
+    /// base class for moveable, drawable critters onscreen
+    /// </summary>
+    public class Animal
+    {
+        #region Fields
+        /// <summary>
+        /// texture drawn to represent this animal
+        /// </summary>
+        protected Texture2D texture;
+        /// <summary>
+        /// tint color to draw the texture with
+        /// </summary>
+        protected Color color = Color.White;
+        /// <summary>
+        /// center of the draw texture
+        /// </summary>
+        protected Vector2 textureCenter;
+        /// <summary>
+        /// movement speed in pixels/second
+        /// </summary>
+        protected float moveSpeed;
+
+        /// <summary>
+        /// All the behavior that this animal has
+        /// </summary>
+        protected Dictionary<AnimalType, Behaviors> behaviors;
+
+        /// <summary>
+        /// The animal type
+        /// </summary>
+        public AnimalType AnimalType
+        {
+            get
+            {
+                return animaltype;
+            }
+        }
+        protected AnimalType animaltype = AnimalType.Generic;
+
+        /// <summary>
+        /// Reaction distance
+        /// </summary>
+        public float ReactionDistance
+        {
+            get
+            {
+                return reactionDistance;
+            }
+        }
+        protected float reactionDistance;
+
+        /// <summary>
+        /// Reaction location
+        /// </summary>
+        public Vector2 ReactionLocation
+        {
+            get
+            {
+                return reactionLocation;
+            }
+        }
+        protected Vector2 reactionLocation;
+
+        public bool Fleeing
+        {
+            get
+            {
+                return fleeing;
+            }
+            set 
+            { 
+                fleeing = value; 
+            }
+        }
+        protected bool fleeing = false;
+
+        public int BoundryWidth
+        {
+            get
+            {
+                return boundryWidth;
+            }
+        }
+        protected int boundryWidth;
+
+        public int BoundryHeight
+        {
+            get
+            {
+                return boundryHeight;
+            }
+        }
+        protected int boundryHeight;
+
+        /// <summary>
+        /// Direction the animal is moving in
+        /// </summary>
+        public Vector2 Direction
+        {
+            get
+            {
+                return direction;
+            }
+        }
+        protected Vector2 direction;
+
+        /// <summary>
+        /// Location on screen
+        /// </summary>
+        public Vector2 Location
+        {
+            get
+            {
+                return location;
+            }
+            set
+            {
+                location = value;
+            }
+        }
+        protected Vector2 location;
+
+        #endregion
+
+        #region Initialization
+        /// <summary>
+        /// Sets the boundries the animal can move in the texture used in Draw
+        /// </summary>
+        /// <param name="tex">Texture to use</param>
+        /// <param name="screenSize">Size of the sample screen</param>
+        public Animal(Texture2D tex, int screenWidth, int screenHeight) 
+        {
+            if (tex != null)
+            {
+                texture = tex;
+                textureCenter = new Vector2(texture.Width / 2, texture.Height / 2);
+            }
+            boundryWidth = screenWidth;
+            boundryHeight = screenHeight;
+            moveSpeed = 0.0f;
+
+            behaviors = new Dictionary<AnimalType, Behaviors>();
+        }
+        #endregion
+
+        #region Update and Draw
+        /// <summary>
+        /// Empty update function
+        /// </summary>
+        /// <param name="gameTime"></param>
+        public virtual void Update(GameTime gameTime)
+        {
+        }
+
+        /// <summary>
+        /// Draw the Animal with the specified SpriteBatch
+        /// </summary>
+        /// <param name="spriteBatch"></param>
+        /// <param name="gameTime"></param>
+        public virtual void Draw(SpriteBatch spriteBatch, GameTime gameTime)
+        {
+            float rotation = (float)Math.Atan2(direction.Y, direction.X);            
+
+            spriteBatch.Draw(texture, location, null, color,
+                rotation, textureCenter, 1.0f, SpriteEffects.None, 0.0f);
+        }
+        #endregion
+    }
+}

+ 295 - 0
Flocking/Animals/Bird.cs

@@ -0,0 +1,295 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Bird.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Collections.Generic;
+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;
+#endregion
+
+namespace Flocking
+{
+    class Bird : Animal
+    {
+        #region Fields
+
+        protected Random random;
+        Vector2 aiNewDir;
+        int aiNumSeen;
+
+        #endregion
+
+        #region Initialization
+        /// <summary>
+        /// Bird constructor
+        /// </summary>
+        /// <param name="tex"></param>
+        /// <param name="dir">movement direction</param>
+        /// <param name="loc">spawn location</param>
+        /// <param name="screenSize">screen size</param>
+        public Bird(Texture2D tex, Vector2 dir, Vector2 loc, 
+            int screenWidth, int screenHeight)
+            : base(tex, screenWidth, screenHeight)
+        {
+            direction = dir;
+            direction.Normalize();
+            location = loc;
+            moveSpeed = 125.0f;
+            fleeing = false;
+            random = new Random((int)loc.X + (int)loc.Y);
+            animaltype = AnimalType.Bird;
+            BuildBehaviors();
+        }
+        #endregion
+
+        #region Update and Draw
+
+        /// <summary>
+        /// update bird position, wrapping around the screen edges
+        /// </summary>
+        /// <param name="gameTime"></param>
+        public void Update(GameTime gameTime, ref AIParameters aiParams)
+        {
+            float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
+            Vector2 randomDir = Vector2.Zero;
+
+            randomDir.X = (float)random.NextDouble() - 0.5f;
+            randomDir.Y = (float)random.NextDouble() - 0.5f;
+            Vector2.Normalize(ref randomDir, out randomDir);
+
+            if (aiNumSeen > 0)
+            {
+                aiNewDir = (direction * aiParams.MoveInOldDirectionInfluence) +
+                    (aiNewDir * (aiParams.MoveInFlockDirectionInfluence / 
+                    (float)aiNumSeen));
+            }
+            else
+            {
+                aiNewDir = direction * aiParams.MoveInOldDirectionInfluence;
+            }
+
+            aiNewDir += (randomDir * aiParams.MoveInRandomDirectionInfluence);
+            Vector2.Normalize(ref aiNewDir, out aiNewDir);
+            aiNewDir = ChangeDirection(direction, aiNewDir, 
+                aiParams.MaxTurnRadians * elapsedTime);
+            direction = aiNewDir;
+
+            if (direction.LengthSquared() > .01f)
+            {
+                Vector2 moveAmount = direction * moveSpeed * elapsedTime;
+                location = location + moveAmount;
+
+                //wrap bird to the other side of the screen if needed
+                if (location.X < 0.0f)
+                {
+                    location.X = boundryWidth + location.X;
+                }
+                else if (location.X > boundryWidth)
+                {
+                    location.X = location.X - boundryWidth;
+                }
+
+                location.Y += direction.Y * moveSpeed * elapsedTime;
+                if (location.Y < 0.0f)
+                {
+                    location.Y = boundryHeight + location.Y;
+                }
+                else if (location.Y > boundryHeight)
+                {
+                    location.Y = location.Y - boundryHeight;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Draw the bird, tinting it if it's currently fleeing
+        /// </summary>
+        /// <param name="spriteBatch"></param>
+        /// <param name="gameTime"></param>
+        public override void Draw(SpriteBatch spriteBatch, GameTime gameTime)
+        {
+            Color tintColor = color;
+            float rotation = 0.0f;
+            rotation = (float)Math.Atan2(direction.Y, direction.X);
+
+            // if the entity is highlighted, we want to make it pulse with a red tint.
+            if (fleeing)
+            {
+                // to do this, we'll first generate a value t, which we'll use to
+                // determine how much tint to have.
+                float t = (float)Math.Sin(10 * gameTime.TotalGameTime.TotalSeconds);
+
+                // Sin varies from -1 to 1, and we want t to go from 0 to 1, so we'll 
+                // scale it now.
+                t = .5f + .5f * t;
+
+                // finally, we'll calculate our tint color by using Lerp to generate
+                // a color in between Red and White.
+                tintColor = new Color(Vector4.Lerp(
+                    Color.Red.ToVector4(), Color.White.ToVector4(), t));
+            }
+
+            // Draw the animal, centered around its position, and using the 
+            //orientation and tint color.
+            spriteBatch.Draw(texture, location, null, tintColor,
+                rotation, textureCenter, 1.0f, SpriteEffects.None, 0.0f);
+        }
+        #endregion
+
+        #region Methods
+
+        /// <summary>
+        /// Instantiates all the behaviors that this Bird knows about
+        /// </summary>
+        public void BuildBehaviors()
+        {
+            Behaviors catReactions = new Behaviors();
+            catReactions.Add(new FleeBehavior(this));
+            behaviors.Add(AnimalType.Cat, catReactions);
+
+            Behaviors birdReactions = new Behaviors();
+            birdReactions.Add(new AlignBehavior(this));
+            birdReactions.Add(new CohesionBehavior(this));
+            birdReactions.Add(new SeparationBehavior(this));
+            behaviors.Add(AnimalType.Bird, birdReactions);
+        }
+        /// <summary>
+        /// Setup the bird to figure out it's new movement direction
+        /// </summary>
+        /// <param name="AIparams">flock AI parameters</param>
+        public void ResetThink()
+        {
+            Fleeing = false;
+            aiNewDir = Vector2.Zero;
+            aiNumSeen = 0;
+            reactionDistance = 0f;
+            reactionLocation = Vector2.Zero;
+        }
+
+        /// <summary>
+        /// Since we're wrapping movement around the screen, two point at extreme 
+        /// sides of the screen are actually very close together, this function 
+        /// figures out if destLocation is closer the srcLocation if you wrap around
+        /// the screen
+        /// </summary>
+        /// <param name="srcLocation">screen location of src</param>
+        /// <param name="destLocation">screen location of dest</param>
+        /// <param name="outVector">relative location of dest to src</param>
+        private void ClosestLocation(ref Vector2 srcLocation, 
+            ref Vector2 destLocation, out Vector2 outLocation)
+        {
+            outLocation = new Vector2();
+            float x = destLocation.X;
+            float y = destLocation.Y;
+            float dX = Math.Abs(destLocation.X - srcLocation.X);
+            float dY = Math.Abs(destLocation.Y - srcLocation.Y);
+
+            // now see if the distance between birds is closer if going off one
+            // side of the map and onto the other.
+            if (Math.Abs(boundryWidth - destLocation.X + srcLocation.X) < dX)
+            {
+                dX = boundryWidth - destLocation.X + srcLocation.X;
+                x = destLocation.X - boundryWidth;
+            }
+            if (Math.Abs(boundryWidth - srcLocation.X + destLocation.X) < dX)
+            {
+                dX = boundryWidth - srcLocation.X + destLocation.X;
+                x = destLocation.X + boundryWidth;
+            }
+
+            if (Math.Abs(boundryHeight - destLocation.Y + srcLocation.Y) < dY)
+            {
+                dY = boundryHeight - destLocation.Y + srcLocation.Y;
+                y = destLocation.Y - boundryHeight;
+            }
+            if (Math.Abs(boundryHeight - srcLocation.Y + destLocation.Y) < dY)
+            {
+                dY = boundryHeight - srcLocation.Y + destLocation.Y;
+                y = destLocation.Y + boundryHeight;
+            }
+            outLocation.X = x;
+            outLocation.Y = y;
+        }
+
+        /// <summary>
+        /// React to an Animal based on it's type
+        /// </summary>
+        /// <param name="animal"></param>
+        public void ReactTo(Animal animal, ref AIParameters AIparams)
+        {
+            if (animal != null)
+            {
+                //setting the the reactionLocation and reactionDistance here is
+                //an optimization, many of the possible reactions use the distance
+                //and location of theAnimal, so we might as well figure them out
+                //only once !
+                Vector2 otherLocation = animal.Location;
+                ClosestLocation(ref location, ref otherLocation, 
+                    out reactionLocation);
+                reactionDistance = Vector2.Distance(location, reactionLocation);
+
+                //we only react if theAnimal is close enough that we can see it
+                if (reactionDistance < AIparams.DetectionDistance)
+                {
+                    Behaviors reactions = behaviors[animal.AnimalType];
+                    foreach (Behavior reaction in reactions)
+                    {
+                        reaction.Update(animal, AIparams);
+                        if (reaction.Reacted)
+                        {
+                            aiNewDir += reaction.Reaction;
+                            aiNumSeen++;
+                        }
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// This function clamps turn rates to no more than maxTurnRadians
+        /// </summary>
+        /// <param name="oldDir">current movement direction</param>
+        /// <param name="newDir">desired movement direction</param>
+        /// <param name="maxTurnRadians">max turn in radians</param>
+        /// <returns></returns>
+        private static Vector2 ChangeDirection(
+            Vector2 oldDir, Vector2 newDir, float maxTurnRadians)
+        {
+            float oldAngle = (float)Math.Atan2(oldDir.Y, oldDir.X);
+            float desiredAngle = (float)Math.Atan2(newDir.Y, newDir.X);
+            float newAngle = MathHelper.Clamp(desiredAngle, WrapAngle(
+                    oldAngle - maxTurnRadians), WrapAngle(oldAngle + maxTurnRadians));
+            return new Vector2((float)Math.Cos(newAngle), (float)Math.Sin(newAngle));
+        }
+        /// <summary>
+        /// clamps the angle in radians between -Pi and Pi.
+        /// </summary>
+        /// <param name="radians"></param>
+        /// <returns></returns>
+        private static float WrapAngle(float radians)
+        {
+            while (radians < -MathHelper.Pi)
+            {
+                radians += MathHelper.TwoPi;
+            }
+            while (radians > MathHelper.Pi)
+            {
+                radians -= MathHelper.TwoPi;
+            }
+            return radians;
+        }
+        #endregion
+    }
+}

+ 115 - 0
Flocking/Animals/Cat.cs

@@ -0,0 +1,115 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Cat.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Collections.Generic;
+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;
+#endregion
+
+namespace Flocking
+{
+    /// <summary>
+    /// Represents a dangerous object that the flocks flees from
+    /// </summary>
+    class Cat : Animal
+    {
+        #region Fields
+        protected Vector2 center;
+        #endregion
+
+        #region Initialization
+        /// <summary>
+        /// Sets up the Cat's move speed and puts it in the center of the screen
+        /// </summary>
+        /// <param name="tex">Texture to use</param>
+        /// <param name="screenSize">Size of the sample screen</param>
+        public Cat(Texture2D tex, int screenWidth, int screenHeight)
+            : base(tex, screenWidth, screenHeight)
+        {
+            if (tex != null)
+            {
+                texture = tex;
+                textureCenter = new Vector2(texture.Width / 2, texture.Height / 2);
+            }
+            center.X = screenWidth / 2;
+            center.Y = screenHeight / 2;
+            location = center;
+            moveSpeed = 500.0f;
+            animaltype = AnimalType.Cat;
+        }
+        #endregion
+
+        #region Update and Draw
+        /// <summary>
+        /// Move the cat, keeping in inside screen boundry
+        /// </summary>
+        /// <param name="gameTime"></param>
+        public override void Update(GameTime gameTime)
+        {
+            if (gameTime != null)
+            {
+                if (direction.Length() > .01f)
+                {
+                    float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
+                    location.X += direction.X * moveSpeed * elapsedTime;
+
+                    if (location.X < 0.0f)
+                    {
+                        location.X = 0.0f;
+                    }
+                    else if (location.X > boundryWidth)
+                    {
+                        location.X = boundryWidth;
+                    }
+
+                    location.Y += direction.Y * moveSpeed * elapsedTime;
+                    if (location.Y < 0.0f)
+                    {
+                        location.Y = 0.0f;
+                    }
+                    else if (location.Y > boundryHeight)
+                    {
+                        location.Y = boundryHeight;
+                    }
+                }
+            }
+        }
+        /// <summary>
+        /// Draw the cat
+        /// </summary>
+        /// <param name="spriteBatch"></param>
+        /// <param name="gameTime"></param>
+        public override void Draw(SpriteBatch spriteBatch, GameTime gameTime)
+        {
+            spriteBatch.Draw(texture, location, null, color,
+                0f, textureCenter, 1.0f, SpriteEffects.None, 0.0f);
+        }
+        #endregion
+
+        #region Handle Input
+        /// <summary>
+        /// Poll the input state for movement
+        /// </summary>
+        /// <param name="input"></param>
+        public void HandleInput(InputState input)
+        {
+            direction.X = input.MoveCatX;
+            direction.Y = input.MoveCatY;
+        }
+        #endregion
+
+    }
+}

BIN
Flocking/Background.png


+ 51 - 0
Flocking/Behaviors/AlignBehavior.cs

@@ -0,0 +1,51 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// AlignBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+#endregion
+
+
+namespace Flocking
+{
+    /// <summary>
+    /// AlignBehavior is a Behavior that makes an animal move in the same
+    /// direction that the other Animal it sees is
+    /// </summary>
+    class AlignBehavior : Behavior
+    {
+        #region Initialization
+        public AlignBehavior(Animal animal)
+            : base(animal)
+        {
+        }
+        #endregion
+
+        #region Update
+
+        /// <summary>
+        /// AlignBehavior.Update infuences the owning animal to move in same the 
+        /// direction as the otherAnimal that it sees.
+        /// </summary>
+        /// <param name="otherAnimal">the Animal to react to</param>
+        /// <param name="aiParams">the Behaviors' parameters</param>
+        public override void Update(Animal otherAnimal, AIParameters aiParams)
+        {
+            base.ResetReaction();
+
+            if (otherAnimal != null)
+            {
+                reacted = true;
+                reaction = otherAnimal.Direction * aiParams.PerMemberWeight;
+            }
+        }
+        #endregion
+    }
+}

+ 83 - 0
Flocking/Behaviors/Behavior.cs

@@ -0,0 +1,83 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Behavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace Flocking
+{
+    /// <summary>
+    /// Behavior is the base class for the four flock behaviors in this sample: 
+    /// aligning, cohesion, separation and fleeing. It is an abstract class, 
+    /// leaving the implementation of Update up to its subclasses. Animal objects 
+    /// can have an arbitrary number of behaviors, after the entity calls Update 
+    /// on the behavior the reaction results are stored in reaction so the owner 
+    /// can query it.
+    /// </summary>
+    public abstract class Behavior
+    {
+        #region Fields
+        /// <summary>
+        /// Keep track of the animal that this behavior belongs to.
+        /// </summary>
+        public Animal Animal
+        {
+            get { return animal; }
+            set { animal = value; }
+        }
+        private Animal animal;
+
+        /// <summary>
+        /// Store the behavior reaction here.
+        /// </summary>
+        public Vector2 Reaction
+        {
+            get { return reaction; }
+        }
+        protected Vector2 reaction;
+
+        /// <summary>
+        /// Store if the behavior has reaction results here.
+        /// </summary>
+        public bool Reacted
+        {
+            get { return reacted; }
+        }
+        protected bool reacted;
+        #endregion
+
+        #region Initialization
+        protected Behavior(Animal animal)
+        {
+            this.animal = animal;
+        }
+        #endregion
+
+        #region Update
+        /// <summary>
+        /// Abstract function that the subclass must impliment. Figure out the 
+        /// Behavior reaction here.
+        /// </summary>
+        /// <param name="otherAnimal">the Animal to react to</param>
+        /// <param name="aiParams">the Behaviors' parameters</param>
+        public abstract void Update(Animal otherAnimal, AIParameters aiParams);
+
+        /// <summary>
+        /// Reset the behavior reactions from the last Update
+        /// </summary>
+        protected void ResetReaction()
+        {
+            reacted = false;
+            reaction = Vector2.Zero;
+        }
+        #endregion
+    }
+}

+ 24 - 0
Flocking/Behaviors/Behaviors.cs

@@ -0,0 +1,24 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// AlignBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace Flocking
+{
+    /// <summary>
+    /// Container for Behavior Classes
+    /// </summary>
+    public class Behaviors : List<Behavior>
+    {
+    }
+}

+ 71 - 0
Flocking/Behaviors/CohesionBehavior.cs

@@ -0,0 +1,71 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// CohesionBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+#endregion
+
+
+namespace Flocking
+{
+    /// <summary>
+    /// CohesionBehavior is a Behavior that  makes an animal move towards another 
+    /// if it's not already too close
+    /// </summary>
+    class CohesionBehavior : Behavior
+    {
+        #region Initialization
+        public CohesionBehavior(Animal animal)
+            : base(animal)
+        {
+        }
+        #endregion
+
+        #region Update
+
+        /// <summary>
+        /// CohesionBehavior.Update infuences the owning animal to move towards the
+        /// otherAnimal that it sees as long as it isn’t too close, in this case 
+        /// that means inside the separationDist in the passed in AIParameters.
+        /// </summary>
+        /// <param name="otherAnimal">the Animal to react to</param>
+        /// <param name="aiParams">the Behaviors' parameters</param>
+        public override void Update(Animal otherAnimal, AIParameters aiParams)
+        {
+            base.ResetReaction();
+
+            Vector2 pullDirection = Vector2.Zero;
+            float weight = aiParams.PerMemberWeight;
+
+            //if the otherAnimal is too close we dont' want to fly any
+            //closer to it
+            if (Animal.ReactionDistance > 0.0f
+                && Animal.ReactionDistance > aiParams.SeparationDistance)
+            {
+                //We want to make the animal move closer the the otherAnimal so we 
+                //create a pullDirection vector pointing to the otherAnimal bird and 
+                //weigh it based on how close the otherAnimal is relative to the 
+                //AIParameters.separationDistance.
+                pullDirection = -(Animal.Location - Animal.ReactionLocation);
+                Vector2.Normalize(ref pullDirection, out pullDirection);
+
+                weight *= (float)Math.Pow((double)
+                    (Animal.ReactionDistance - aiParams.SeparationDistance) /
+                        (aiParams.DetectionDistance - aiParams.SeparationDistance), 2);
+
+                pullDirection *= weight;
+
+                reacted = true;
+                reaction = pullDirection;
+            }
+        }
+        #endregion
+    }
+}

+ 54 - 0
Flocking/Behaviors/FleeBehavior.cs

@@ -0,0 +1,54 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// FleeBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace Flocking
+{
+    /// <summary>
+    /// FleeBehavior is a Behavior that makes an animal run from another
+    /// </summary>
+    public class FleeBehavior : Behavior
+    {
+        #region Initialization
+        public FleeBehavior(Animal animal)
+            : base(animal)
+        {
+        }
+        #endregion
+
+        #region Update
+        public override void Update(Animal otherAnimal, AIParameters aiParams)
+        {
+            base.ResetReaction();
+
+            Vector2 dangerDirection = Vector2.Zero;
+
+            //Vector2.Dot will return a negative result in this case if the 
+            //otherAnimal is behind the animal, in that case we don’t have to 
+            //worry about it because we’re already moving away from it.
+            if (Vector2.Dot(
+                Animal.Location, Animal.ReactionLocation) >= -(Math.PI / 2))
+            {
+                //set the animal to fleeing so that it flashes red
+                Animal.Fleeing = true;
+                reacted = true;
+
+                dangerDirection = Animal.Location - Animal.ReactionLocation;
+                Vector2.Normalize(ref dangerDirection, out dangerDirection);
+                
+                reaction = (aiParams.PerDangerWeight * dangerDirection);
+            }
+        }
+        #endregion
+    }
+}

+ 69 - 0
Flocking/Behaviors/SeparationBehavior.cs

@@ -0,0 +1,69 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// SeparationBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+#endregion
+
+
+namespace Flocking
+{
+    /// <summary>
+    /// SeparationBehavior is a Behavior that will make an animal move away from
+    /// another if it's too close for comfort
+    /// </summary>
+    class SeparationBehavior : Behavior
+    {
+        #region Initialization
+        public SeparationBehavior(Animal animal)
+            : base(animal)
+        {
+        }
+        #endregion
+
+        #region Update
+
+        /// <summary>
+        /// separationBehavior.Update infuences the owning animal to move away from
+        /// the otherAnimal is it’s too close, in this case if it’s inside 
+        /// AIParameters.separationDistance.
+        /// </summary>
+        /// <param name="otherAnimal">the Animal to react to</param>
+        /// <param name="aiParams">the Behaviors' parameters</param>
+        public override void Update(Animal otherAnimal, AIParameters aiParams)
+        {
+            base.ResetReaction();
+
+            Vector2 pushDirection = Vector2.Zero;
+            float weight = aiParams.PerMemberWeight;
+
+            if (Animal.ReactionDistance > 0.0f && 
+                Animal.ReactionDistance <= aiParams.SeparationDistance)
+            {
+                //The otherAnimal is too close so we figure out a pushDirection 
+                //vector in the opposite direction of the otherAnimal and then weight
+                //that reaction based on how close it is vs. our separationDistance
+
+                pushDirection = Animal.Location - Animal.ReactionLocation;
+                Vector2.Normalize(ref pushDirection, out pushDirection);
+
+                //push away
+                weight *= (1 - 
+                    (float)Animal.ReactionDistance / aiParams.SeparationDistance);
+
+                pushDirection *= weight;
+
+                reacted = true;
+                reaction += pushDirection;
+            }
+        }
+        #endregion
+    }
+}

+ 67 - 0
Flocking/Content/FlockingContent.contentproj

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
+    <ProjectGuid>{E32187E9-81EA-4BD0-BAD4-D98BED915D9C}</ProjectGuid>
+    <ProjectTypeGuids>{96E2B04D-8817-42c6-938A-82C39BA4D311};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
+    <OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
+    <ContentRootDirectory>Content</ContentRootDirectory>
+  </PropertyGroup>
+  <PropertyGroup>
+    <RootNamespace>FlockingContent</RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="cat.tga">
+      <Name>cat</Name>
+      <Importer>TextureImporter</Importer>
+      <Processor>TextureProcessor</Processor>
+    </Compile>
+    <Compile Include="HUDFont.spritefont">
+      <Name>HUDFont</Name>
+      <Importer>FontDescriptionImporter</Importer>
+      <Processor>FontDescriptionProcessor</Processor>
+    </Compile>
+    <Compile Include="mouse.tga">
+      <Name>mouse</Name>
+      <Importer>TextureImporter</Importer>
+      <Processor>TextureProcessor</Processor>
+    </Compile>
+    <Compile Include="xboxControllerButtonB.tga">
+      <Name>xboxControllerButtonB</Name>
+      <Importer>TextureImporter</Importer>
+      <Processor>TextureProcessor</Processor>
+    </Compile>
+    <Compile Include="xboxControllerButtonX.tga">
+      <Name>xboxControllerButtonX</Name>
+      <Importer>TextureImporter</Importer>
+      <Processor>TextureProcessor</Processor>
+    </Compile>
+    <Compile Include="xboxControllerButtonY.tga">
+      <Name>xboxControllerButtonY</Name>
+      <Importer>TextureImporter</Importer>
+      <Processor>TextureProcessor</Processor>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="Microsoft.Xna.Framework.Content.Pipeline, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
+    <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.AudioImporters, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
+    <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.EffectImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
+    <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.FBXImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
+    <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.TextureImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
+    <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.VideoImporters, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
+    <Reference Include="Microsoft.Xna.Framework.Content.Pipeline.XImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\$(XnaFrameworkVersion)\Microsoft.Xna.GameStudio.ContentPipeline.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

BIN
Flocking/Content/HUDFont.xnb


BIN
Flocking/Content/cat.png


BIN
Flocking/Content/logo.png


BIN
Flocking/Content/mouse.png


BIN
Flocking/Content/xboxControllerButtonB.png


BIN
Flocking/Content/xboxControllerButtonX.png


BIN
Flocking/Content/xboxControllerButtonY.png


BIN
Flocking/Default.png


+ 168 - 0
Flocking/Flock.cs

@@ -0,0 +1,168 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Flock.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+#endregion
+
+namespace Flocking
+{
+    /// <summary>
+    /// This class manages all the birds in the flock and handles 
+    /// their update and draw
+    /// </summary>
+    class Flock
+    {
+        #region Constants
+        //Number of FLock members
+        const int flockSize = 40;
+        #endregion
+
+        #region Fields
+
+        //birds that fly out of the boundry(screen) will wrap around to 
+        //the other side
+        int boundryWidth;
+        int boundryHeight;
+
+        /// <summary>
+        /// Tecture used to draw the Flock
+        /// </summary>
+        Texture2D birdTexture;
+
+        /// <summary>
+        /// List of Flock Members
+        /// </summary>
+        List<Bird> flock;
+
+        /// <summary>
+        /// Parameters flock members use to move and think
+        /// </summary>
+        public AIParameters FlockParams
+        {
+            get
+            {
+                return FlockParams;
+            }
+
+            set
+            {
+                flockParams = value;
+            }           
+        }
+        protected AIParameters flockParams;
+        
+
+        #endregion
+
+        #region Initialization
+
+        /// <summary>
+        /// Setup the flock boundaries and generate individual members of the flock
+        /// </summary>
+        /// <param name="tex"> The texture to be used by the birds</param>
+        /// <param name="screenWidth">Width of the screen</param>
+        /// <param name="screenHeight">Height of the screen</param>
+        /// <param name="flockParameters">Behavior of the flock</param>
+        public Flock(Texture2D tex, int screenWidth, int screenHeight,
+            AIParameters flockParameters)
+        {
+            boundryWidth = screenWidth;
+            boundryHeight = screenHeight;
+
+            birdTexture = tex;
+
+            flock = new List<Bird>();
+            flockParams = flockParameters;
+
+            ResetFlock();
+        }
+        #endregion
+
+        #region Update and Draw
+        /// <summary>
+        /// Update each flock member, Each bird want to fly with or flee from everything
+        /// it sees depending on what type it is
+        /// </summary>
+        /// <param name="gameTime">Provides a snapshot of timing values.</param>
+        /// <param name="cat"></param>
+        public void Update(GameTime gameTime, Cat cat)
+        {
+            foreach (Bird thisBird in flock)
+            {
+                thisBird.ResetThink();
+
+                foreach (Bird otherBird in flock)
+                {
+                    //this check is so we don't try to fly to ourself!
+                    if (thisBird != otherBird)
+                    {
+                        thisBird.ReactTo(otherBird, ref flockParams);
+                    }
+                }
+
+                //Look for the cat
+                thisBird.ReactTo(cat, ref flockParams);
+
+                thisBird.Update(gameTime, ref flockParams);
+            }
+        }
+
+        /// <summary>
+        /// Calls Draw on every member of the Flock
+        /// </summary>
+        /// <param name="spriteBatch"></param>
+        /// <param name="gameTime"></param>
+        public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
+        {
+            foreach (Bird theBird in flock)
+            {
+                theBird.Draw(spriteBatch, gameTime);
+            }
+        }
+
+        #endregion
+
+        #region Methods
+
+        /// <summary>
+        /// Clear the current flock if it exists and randomly generate a new one
+        /// </summary>
+        public void ResetFlock()
+        {
+            flock.Clear();
+            flock.Capacity = flockSize;
+
+            Bird tempBird;
+            Vector2 tempDir;
+            Vector2 tempLoc;
+
+            Random random = new Random();
+
+            for (int i = 0; i < flockSize; i++)
+            {
+                tempLoc = new Vector2((float)
+                    random.Next(boundryWidth), (float)random.Next(boundryHeight));
+                tempDir = new Vector2((float)
+                    random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f);
+                tempDir.Normalize();
+
+                tempBird = new Bird(birdTexture, tempDir, tempLoc, 
+                    boundryWidth, boundryHeight);
+                flock.Add(tempBird);
+            }
+        }
+        #endregion
+    }
+}

+ 968 - 0
Flocking/Flocking.htm

@@ -0,0 +1,968 @@
+<html xmlns:MSHelp="http://msdn.microsoft.com/mshelp" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xanx="http://schemas.microsoft.com/developer/xanx/2005"><head><META http-equiv="Content-Type" content="text/html; charset=utf-8"><META NAME="save" CONTENT="history"><title>Flocking Sample</title>
+<style><!--
+/***********************************************************
+ *             SCRIPT-SUPPORTING STYLES
+ ***********************************************************/
+
+/* Defines the userData cache persistence mechanism. */
+.userDataStyle
+{
+	behavior: url(#default#userData);
+}
+
+/* Used to save the scroll bar position when navigating away from a page. */
+div.saveHistory
+{
+	behavior: url(#default#saveHistory);
+}
+
+/* Formats the expand/collapse images for all collapsible regions. */
+img.toggle
+{
+	border: 0;
+	margin-right: 5;
+}
+
+/* Formats the Language filter drop-down image. */
+img#languageFilterImage
+{
+	border: 0;
+	margin-left: 0;
+	vertical-align: middle;
+}
+
+/* Formats the Members Options filter drop-down image. */
+img#membersOptionsFilterImage
+{
+	border: 0;
+	margin-left: 0;
+	vertical-align: middle;
+}
+
+/* Formats the Collapse All/Expand All images. */
+img#toggleAllImage
+{
+	margin-left: 0;
+	vertical-align: middle;
+}
+
+/* Supports XLinks */
+MSHelp\:link
+{
+ 	text-decoration: underline;
+	color: #0000ff; 
+	hoverColor: #3366ff;
+	filterString: ;
+}
+
+
+body
+	{
+	background:	#FFFFFF;
+	color: #000000;
+	font-family:	Verdana;
+	font-size: medium;
+	font-style: normal;
+	font-weight: normal;
+	margin-top:	0;
+	margin-bottom:	0;
+	margin-left:	0;
+	margin-right:	0;
+	width:	100%;
+	/*font-size: 110%;*/
+	}
+
+div.section
+	{
+	margin-left: 15px;
+	}
+
+div.hxnx5
+	{
+	margin-left: 1.5em;
+	}
+
+/* Font for all headings */	
+h1, h2, h3, h4, h5, h6
+	{
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	margin-top: 18;
+	margin-bottom: 8; 
+	font-weight: bold;
+	}
+h1
+	{
+	font-size: 130%;
+	color: #003399;
+	}
+div#scrollyes h1 /* Changes font size for full-scrolling topic */
+	{
+	font-size: 150%;
+	}
+h2
+	{
+	font-size: 125%;
+	}
+h3
+	{
+	font-size: 115%;
+	margin-top: 9;
+	margin-bottom: 4; 
+	}
+h4
+	{
+	font-size: 115%;
+	margin-top: 9;
+	margin-bottom: 4; 
+	}
+h5
+	{
+	font-size: 100%;
+	margin-top: 9;
+	margin-bottom: 4; 
+	}
+h6
+	{
+	font-size: 100%;
+	margin-top: 9;
+	margin-bottom: 4; 
+	}
+
+ul p, ol p, dl p
+	{
+	margin-left: 0em;
+	}
+
+p
+	{
+	margin-top: .6em;
+	margin-bottom: .6em;
+	}
+	
+td p
+	{
+	margin-top: 0.0em;
+	margin-bottom: 0.6em;
+	}
+
+dd p
+	{
+	margin-top: 0.0em;
+	margin-bottom: 0.6em;
+	}
+
+.image
+	{
+	text-align: center;
+	}
+
+dl
+	{
+	margin-top: 0em; 
+	margin-bottom: 1.3em;
+	}
+
+dd
+	{
+	margin-bottom: 0em;
+	margin-left: 0;
+	}
+
+dl.glossary dd 
+{
+	margin-bottom: 0em;  
+	margin-left: 1.5em; 
+}
+
+dt
+	{
+	margin-top: .6em;
+	margin-bottom: 1;
+	}
+
+ul, ol
+	{
+	margin-top: 0.6em;
+	margin-bottom: 0.6em; 	
+	}
+	
+ol
+	{
+	margin-left: 2.5em; 	
+	}	
+	
+ul
+	{
+	margin-left: 1.9em; 
+	}
+
+li
+	{
+	margin-bottom: 0.4em;
+	}
+
+ul ol, ol ol
+	{
+	list-style-type: lower-alpha;
+	}
+
+pre
+	{
+	margin-top: .6em;
+	margin-bottom: .6em; 
+	}
+
+pre
+	{
+	font: 105% Lucida, mono; 
+	color: #000066;
+	}
+
+code
+{
+	font-family: Monospace, Courier New, Courier;
+	font-size: 105%;
+	color:	#000066;
+}
+
+table.userdata td 
+	{
+	background: #ffffff;
+	background-color: #F5F5F5;
+	border-color: #ffffff;
+	border: none;
+	}	
+table.clsWarning
+	{
+	background: #ffffff;
+	padding: 0px;
+	margin: 0px;
+	border: none;
+	}
+table.clsWarning td
+	{
+	padding: 0px;
+	margin: 0px;
+	background: #ffffff;
+	vertical-align: middle;
+	font-size: 70%;
+	}
+
+div#mainSection table
+	{
+	width: 98%;
+	background: #ffffff;
+	margin-top: 5px;
+	margin-bottom: 5px;
+	}
+
+div#mainSection table th
+	{ 
+	padding: 5px 6px;
+	background: #EFEFF7;
+	text-align: left;
+	font-size: 70%;
+	vertical-align: bottom;
+	border-bottom: 1px solid #C8CDDE;
+	}
+div#mainSection table td
+	{ 
+	padding: 5px 5px;
+	background: #F7F7FF;
+	vertical-align: top;
+	font-size: 70%;
+	border-bottom: 1px solid #D5D5D3;
+	}
+
+div#syntaxCodeBlocks table th
+	{
+	padding: 1px 6px;
+	color: #000066;
+	}
+
+div#syntaxCodeBlocks table td
+	{
+	padding: 1px 5px;
+	}
+
+/* Applies to the running header text in the first row of the upper table in the
+   non-scrolling header region. */
+span#runningHeaderText
+{
+	color: #003399;
+	font-size: 90%;
+	padding-left: 13;
+}
+
+/* Applies to the topic title in the second row of the upper table in the
+   non-scrolling header region. */
+span#nsrTitle
+{
+	color: #003399;
+	font-size: 120%;
+	font-weight: 600;
+	padding-left: 13;
+}
+
+/* Applies to everything below the non-scrolling header region. */
+div#mainSection
+{
+	font-size: 70%;
+	width: 100%;
+}
+
+/* Applies to everything below the non-scrolling header region, minus the footer. */
+div#mainBody
+{
+	font-size: 90%;
+	margin-left: 15;
+	margin-top: 10;
+	padding-bottom: 20;
+}
+
+/* Adds right padding for all blocks in mainBody */
+div#mainBody p, div#mainBody ol, div#mainBody ul, div#mainBody dl
+{
+	padding-right: 5;
+}
+
+div#mainBody div.alert, div#mainBody div.code, div#mainBody div.tableSection
+{
+	width:98.9%;
+}
+
+div.alert p, div.code p
+{
+	margin-top:5;
+	margin-bottom:8;
+}
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Note Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+div#mainSection div.alert table
+{
+	border: 0;
+}
+
+div#mainSection div.alert table th
+{
+	padding-top: 0;
+	padding-bottom: 0;
+	padding-left: 5;
+	padding-right: 5;
+}
+
+div#mainSection div.alert table td
+{
+	padding-left: 5;
+	padding-right: 5;
+}
+
+img.note
+{
+	border: 0;
+	margin-left: 0;
+	margin-right: 3;
+}
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - End Note Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Begin Non-scrolling Header Region Styles - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+/* Applies to the entire non-scrolling header region. */
+div#header
+{
+	background-color: #D4DFFF;
+	padding-top:	0;
+	padding-bottom:	0;
+	padding-left:	0;
+	padding-right:	0;
+	width:	100%;
+}
+
+/* Applies to both tables in the non-scrolling header region. */
+div#header table
+{
+	margin-top:	0;
+	margin-bottom: 0;
+	border-bottom-color: #C8CDDE;
+	border-bottom-style: solid;
+	border-bottom-width: 1;
+	background: #D4DFFF;
+	width:	100%;
+}
+
+/* Applies to cells in both tables in the non-scrolling header region. */
+div#header table td
+{
+	color: #0000FF;
+	font-size: 70%;
+	padding-right: 20;
+	padding-top: 1;
+	padding-bottom: 1;
+	border: none;
+	background: #D4DFFF;
+}
+
+/* Applies to the last row in the upper table of the non-scrolling header region. Text 
+   in this row includes See Also, Constructors, Methods, and Properties. */
+div#header table tr#headerTableRow3 td
+{
+	padding-bottom: 2;
+	padding-top: 5;
+	padding-left: 15;
+}
+
+/* Applies to the lower table in the non-scrolling header region. Text in this table
+   includes Collapse All/Expand All, Language Filter, and Members Options. */
+div#header table#bottomTable
+{
+	border-top-color: #FFFFFF;
+	border-top-style: solid;
+	border-top-width: 1;
+	text-align: left;
+	padding-left: 15;
+}
+
+
+blockquote
+	{
+	margin-left: 3.8em;
+	margin-right: 3.8em;
+	margin-top: .6em;
+	margin-bottom: .6em;
+	}
+
+sup
+	{
+	text-decoration: none;
+	font-size: smaller; 
+	}
+
+a:link
+	{
+	color: #0000FF;
+/*    font-weight: bold */
+	}
+	
+a:visited
+	{
+	color: #0000AA;
+/*    font-weight: bold	*/
+	}
+	
+a:hover
+	{
+	color: #3366FF;
+/*    font-weight: bold */
+	}
+	
+.label
+	{
+	font-weight: bold; 
+	margin-top: 1em;
+	margin-left: -26px;
+	}
+	
+.tl
+	{
+	margin-bottom: .75em; 
+	}
+	
+.atl
+	{
+	padding-left: 1.5em;
+	padding-bottom: .75em; 
+	}
+	
+.cfe
+	{
+	font-weight: bold; 
+	}
+	
+.mini
+	{
+	font-size: smaller;
+	}
+	
+.dt
+	{
+	margin-bottom: -.6em; 
+	}
+	
+.indent
+	{
+	margin-left: 1.9em; 
+	margin-right: 1.9em;
+	}
+
+.product
+	{
+	text-align: right;
+	color: #333333;
+	font-size: smaller;
+	font-style: italic;
+	}
+
+.buttonbarshade
+	{
+	position: relative;
+	margin: 0;
+	left: 0px;
+	top: 2;
+	width: 50%;
+	height: 40px;
+	}
+
+.buttonbartable
+	{
+	position: absolute;
+	margin: 0;
+	padding:0;
+	border:0;
+	left:0px;
+	top: 2;
+	width: 100%;
+	height: 40px;
+	}
+
+/* background color, font for header */ 
+table.buttonbartable td, table.buttonbarshade td
+	{
+	background: #ffffff; /*#5177B8; #80C615;*/
+	border-left: 0px solid #80C615;
+	margin: 0;
+	padding: 0px 0px 0px 0px;
+	font-family: Impact, sans-serif;
+	font-size: 14pt;
+	}
+
+table.buttonbartable td.button1
+	{
+	background: #5177B8; /*#80C615;*/;
+	padding: 0;
+	font-weight: bold;
+	text-align: center;
+	cursor: hand;
+	}
+
+table.buttonbartable td.button2
+	{
+	background: #5177B8; /*#80C615;*/;
+	font-weight: bold;
+	text-align: center;
+	}
+
+table.buttonbartable td.button3
+	{
+	background: #5177B8; /*#80C615;*/;
+	font-weight: bold;
+	text-align: center;
+	}
+
+table.buttonbartable td.runninghead
+	{
+	padding-left: 0px;
+	font-style: italic;
+	text-align: left;
+	}
+
+.version
+	{
+	text-align: left;
+	color: #000000;
+	margin-top: 3em;
+	margin-left: -26px;
+	font-size: smaller;
+	font-style: italic;
+	}
+
+.lang, .ilang
+	{
+	color: #0000ff;
+	font: normal 7pt Arial, Helvetica, sans-serif;
+	}
+
+div.langMenu
+	{
+	position: absolute;
+	z-index: 1;
+	width: 96pt;
+	padding: 8pt;
+	visibility: hidden;
+	border: 1px solid #000000;
+	background: #ffffd0;
+	}
+
+div.langMenu ul
+	{
+	padding-left: 2em;
+	margin-left: 0;
+	}
+
+div.filtered
+	{
+	margin: 4pt 0 8pt -26px;
+	padding: 4px 4px 8px 26px;
+	width: 100%;
+	border: 2px solid #aaaacc;
+	background: #ffffff;
+	}
+
+div.filtered2
+	{
+	margin: 4pt 0 8pt -26px;
+	padding: 4px 4px 8px 26px;
+	width: 100%;
+	border: none;
+	background: #ffffff;
+	}
+
+div.filtered h1, div.filtered h2, div.filtered h3, div.filtered h4
+	{
+	margin-left: -22px;
+	}
+
+div.filtered span.lang
+	{
+	position: relative;
+	left: -22px;
+	}
+
+div.reftip
+	{
+	position: absolute;
+	z-index: 1;
+	padding: 8pt;
+	visibility: hidden;
+	border: 1px solid #000000;
+	background: #ffffd0;
+	}
+
+a.synParam
+	{
+	color: #0000FF;
+	/*color: #3F7800;*/ 	
+	/*color: #8DC54F;*/
+	text-decoration: none;
+    font-weight: normal;
+	}
+
+a.synParam:hover
+	{
+	text-decoration: underline;
+    font-weight: normal;
+	}
+
+div.sapop
+	{
+	position: absolute;
+	z-index: 1;
+	left: 26px;
+	width: 100%;
+	padding: 10px 10px 10px 36px;
+	visibility: hidden;
+	border: 1px solid #000000;
+	background: #ffffd0;
+	}
+
+div.footer
+	{
+	width: 100%;
+	border: none;
+	background: #ffffff;
+	margin-top: 18pt;
+	padding-bottom: 12pt;
+	color: #0000FF;
+	/*color: #228B22; */
+	text-align: center;
+	font-size: 76%;
+	}
+
+div.preliminary
+	{
+	margin-top: 8pt;
+	padding-bottom: 12pt;
+	color: #A0A0A0;
+	}
+
+/* A procedure section. eg. 'To create a file', 'To add a value' */
+div.proc
+    {
+	margin-left: 0.5em; 
+    }
+     
+/* The title of a 'procedure' section. */
+div.proc h3
+    {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	font-weight: bold;
+	font-size: 115%;
+	margin-top: 1em;
+	margin-bottom: 0.4em;
+	margin-left: -0.5em; 
+	color: #003399;
+    }
+
+div.proc ul
+    {
+    margin-left: 1.5em;
+    }
+
+div.proc ol
+    {
+    margin-left: 2.0em;
+    }
+      
+.note
+	{
+	margin-left: 14pt;
+	margin-right: 12pt;
+	}
+
+.indent1
+	{
+	margin-left: 12pt;
+	}
+
+.indent2
+	{
+	margin-left: 24pt;
+	}
+
+.indent3
+	{
+	margin-left: 36pt;
+	}
+
+p.proch
+	{
+	padding-left: 16px;
+	}
+
+p.proch img
+	{
+	position: relative; 
+	vertical-align: top;
+	left: -18px; 
+	margin-right: -14px; 
+	margin-bottom: -18px;
+	}
+	
+div.clsPlatSpec
+{
+	background-color:#FFF8DC;
+	border-style:solid;
+	border-width:1pt 0pt 0pt 1pt;
+	border-color:#ffE4C4;
+	margin-top:0.6em;
+	width:100%;
+}
+
+
+/* Applies to the language labels in the Language Filter drop-down list. */
+.languageFilter
+{
+	color:	#0000FF;
+	cursor:hand;
+	text-decoration:underline;
+	padding-bottom:4;
+}
+
+/* Dropdown areas */
+
+#languageSpan {
+	position: absolute;
+	visibility: hidden;
+	border-style: solid;
+	border-width: 1px;
+	border-color: #C8CDDE;
+	background: #d4dfff;
+	padding: 4px;
+	font-size: 70%;
+}
+
+#membersOptionsSpan {
+	position: absolute;
+	visibility: hidden;
+	border-style: solid;
+	border-width: 1px;
+	border-color: #C8CDDE;
+	background: #d4dfff;
+	padding: 4px;
+	font-size: 70%;
+}
+--></style>
+
+<xml>
+<MSHelp:TOCTitle Title="Flocking Sample" />
+<MSHelp:RLTitle Title="Flocking Sample" />
+<MSHelp:Keyword Index="A" Term="O:Microsoft.Xna.Flocking" />
+<MSHelp:Keyword Index="A" Term="398f9c2c-f42f-5ea8-9bb4-ed2e946c5012" />
+<MSHelp:Keyword Index="K" Term="Flocking Sample" />
+<MSHelp:Attr Name="ProjType" Value="LocalProj" />
+<MSHelp:Attr Name="ProjType" Value="XNA_30" />
+<MSHelp:Attr Name="DocSet" Value="XNA" />
+<MSHelp:Attr Name="DocSet" Value="ExpressLibVS" />
+<MSHelp:Attr Name="DocSet" Value="C#" />
+<MSHelp:Attr Name="Locale" Value="en-us" />
+<MSHelp:Attr Name="CommunityContent" Value="1" />
+<MSHelp:Attr Name="AssetID" Value="398f9c2c-f42f-5ea8-9bb4-ed2e946c5012" />
+<MSHelp:Attr Name="TopicType" Value="kbOrient" />
+</xml>
+</head><body><div id="mainSection"><div id="mainBody">
+  <h1>Flocking Sample</h1>
+
+ This sample demonstrates how AIs can use simple rules to move together and create complex behaviors.
+
+  <a name="ID2EK"></a><h1 class="heading">Sample Overview</h1><div id="ID2EK" class="hxnx1">
+    
+
+    <p>
+      When programming the AI for your game, you often want your actors to move and react together without having to behave identically. For example, you might want to simulate a school of fish that all swim together without a centralized control or a battalion of soldiers that can march together in formation around obstacles. 
+
+This sample demonstrates some of these behaviors. The sample has a flock of birds that fly to, and in the same direction as, other birds they see nearby. The sample also has a cat that you can turn on and who then chases the birds as they run away. 
+
+This sample is based on the Chase and Evade sample, and assumes that the reader is familiar with the code and concepts explained in that sample. 
+
+    </p>
+
+          
+      <p>This sample uses the following controls.</p>
+      <table>
+        <tr>
+          <th>Action</th>
+          <th style="width: 192px">Windows Phone</th>
+          <th>Windows - Keyboard Control</th>
+          <th>Windows/Xbox - Gamepad Control</th>
+        </tr>
+        <tr>
+          <td>Select the tuning parameter.</td>
+          <td style="width: 192px"><strong>DRAG</strong> tuning bar</td>
+          <td>UP ARROW, DOWN ARROW</td>
+          <td>D-Pad Up and Down</td>
+        </tr>
+        <tr>
+          <td>Increase/decrease the tuning parameter.</td>
+          <td style="width: 192px"><strong>DRAG </strong>tuning bar</td>
+          <td>LEFT ARROW, RIGHT ARROW</td>
+          <td>
+            D-Pad Left and Right, Left and Right Triggers</td>
+        </tr>
+        <tr>
+          <td>Reset the bird flock.</td>
+          <td style="width: 192px"><strong>TAP</strong> &quot;Reset Flock&quot; button</td>
+          <td>X</td>
+          <td>
+            X</td>
+        </tr>
+        <tr>
+          <td>Reset the tuning parameters.</td>
+          <td style="width: 192px"><strong>TAP</strong> &quot;Reset Distance&quot; button</td>
+          <td>B</td>
+          <td>B</td>
+        </tr>
+        <tr>
+          <td>Add/remove the cat</td>
+          <td style="width: 192px"><strong>TAP</strong> &quot;Add/Remove Cat&quot; button</td>
+          <td>Y</td>
+          <td>
+            Y</td>
+        </tr>
+        <tr>
+          <td>Move the cat.</td>
+          <td style="width: 192px"><strong>TAP </strong>or <strong>DRAG </strong>
+		  on screen</td>
+          <td>W, S, A, D</td>
+          <td>
+            Left Thumbstick</td>
+        </tr>
+        <tr>
+          <td>Exit the game.</td>
+          <td style="width: 192px"><strong>BACK</strong></td>
+          <td>ESC or ALT+F4</td>
+          <td>
+            <b>BACK</b>
+          </td>
+        </tr>
+      </table>
+    </div>
+  </div>
+
+  <a name="ID2EHE"></a><h1 class="heading">How the Sample Works</h1><div id="ID2EHE" class="hxnx1">
+    
+
+    <p>
+      &nbsp;</p>
+		<h2 class="subHeading">Flocking Behavior</h2>
+		<div id="ID2E1D" class="hxnx2">
+			<p>Flocking behavior is controlled by three simple behaviors: 
+			cohesion, alignment, and separation. Other behaviors can be present, 
+			but they are not required. In this sample, the birds also have a 
+			flee behavior. </p>
+			<p>Cohesion is the birds’ tendency to fly together with others. 
+			Alignment is the birds’ tendency to fly in the same direction as 
+			other birds. Separation is the birds’ tendency to fly away from 
+			others that are too close. Fleeing is the birds’ tendency to avoid 
+			dangerous things. </p>
+			<a name="ID2ECE"></a>
+			<h4 class="subHeading">Cohesion</h4>
+			<div id="ID2ECE" class="hxnx3">
+				<p>Each bird flies towards others it can see. To make one bird 
+				fly closer to another, for each other bird inside its <b>
+				detectionDist</b> value, the bird changes its <b>direction</b> 
+				towards the other bird in proportion to its <b>
+				moveInFlockDirInfluence</b> setting and according to how close 
+				it is to the midpoint between its <b>detectionDist</b> and <b>
+				separationDist</b> values. </p>
+			</div>
+			<a name="ID2EUE"></a>
+			<h4 class="subHeading">Alignment</h4>
+			<div id="ID2EUE" class="hxnx3">
+				<p>Each bird flies in the general direction of others it can 
+				see. To make one bird line up with another, for each other bird 
+				inside its <b>detectionDist</b> value, the bird adds the <b>
+				direction</b> the other bird is facing to its own <b>direction</b> 
+				in proportion to its <b>moveInFlockDirInfluence</b> setting. </p>
+			</div>
+			<a name="ID2EEF"></a>
+			<h4 class="subHeading">Separation</h4>
+			<div id="ID2EEF" class="hxnx3">
+				<p>Each bird flies away from others that that are too close. For 
+				each other bird inside both its <b>detectionDist</b> <i>and</i> 
+				its <b>separationDist</b> values, the bird applies the 
+				separation rule instead of the cohesion rule. To move one bird a 
+				comfortable distance away from another, the bird adds the 
+				opposite of the direction towards the other bird&#39;s direction to 
+				its <b>direction</b> in proportion to its <b>
+				moveInFlockDirInfluence</b> setting and according to the ratio 
+				of how close the other bird is relative to its <b>separationDist</b> 
+				value. </p>
+			</div>
+			<a name="ID2EYF"></a>
+			<h4 class="subHeading">Flee</h4>
+			<div id="ID2EYF" class="hxnx3">
+				<p>Each bird flies away from the cat if the bird can see the 
+				cat. To move a bird away from the cat, if the cat is inside the 
+				bird&#39;s <b>detectionDist</b> and the bird isn&#39;t already moving 
+				away from the cat, the bird adds the opposite of the direction 
+				towards the cat to its <b>direction</b> value.</p>
+			</div>
+		</div>
+
+  </div>
+
+  <a name="ID2EAH"></a><h1 class="heading">Extending the Sample</h1><div id="ID2EAH" class="hxnx1">
+    
+
+    	<ul>
+			<li>Make one bird in the flock the leader and give it the wander 
+			behavior from the Chase and Evade sample. Then make the other birds 
+			in the flock follow the leader. </li>
+			<li>Add different colored flocks and make the birds fly with their 
+			own kind and avoid other birds. </li>
+			<li>Add formations. </li>
+			<li>Add predator birds that chase the others.</li>
+		</ul>
+  </div>
+
+</div><div class="footer" id="footer"><p>© 2010 Microsoft Corporation. All rights reserved.<br>Send feedback to 
+	<a href="mailto:[email protected]?subject=Documentation Feedback: Flocking Sample">
+	[email protected]</a>.</p></div></div></body></html>

+ 542 - 0
Flocking/FlockingSample.cs

@@ -0,0 +1,542 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// FlockingSample.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Input.Touch;
+#endregion
+
+namespace Flocking
+{
+    #region FlockingAIParameters
+    public struct AIParameters
+    {
+        /// <summary>
+        /// how far away the animals see each other
+        /// </summary>
+        public float DetectionDistance;
+        /// <summary>
+        /// seperate from animals inside this distance
+        /// </summary>
+        public float SeparationDistance;
+        /// <summary>
+        /// how much the animal tends to move in it's previous direction
+        /// </summary>
+        public float MoveInOldDirectionInfluence;
+        /// <summary>
+        /// how much the animal tends to move with animals in it's detection distance
+        /// </summary>
+        public float MoveInFlockDirectionInfluence;
+        /// <summary>
+        /// how much the animal tends to move randomly
+        /// </summary>
+        public float MoveInRandomDirectionInfluence;
+        /// <summary>
+        /// how quickly the animal can turn
+        /// </summary>
+        public float MaxTurnRadians;
+        /// <summary>
+        /// how much each nearby animal influences it's behavior
+        /// </summary>
+        public float PerMemberWeight;
+        /// <summary>
+        /// how much dangerous animals influence it's behavior
+        /// </summary>
+        public float PerDangerWeight;
+    }
+    #endregion
+    /// <summary>
+    /// This is the main type for your game
+    /// </summary>
+    public class FlockingSample : Microsoft.Xna.Framework.Game
+    {
+        #region Constants
+
+        // X location to start drawing the HUD from        
+        const int hudLocX = 200;
+
+        // Y location to start drawing the HUD from
+        const int hudLocY = 30;
+
+        // Min value for the distance sliders
+        const float sliderMin = 0.0f;
+
+        // Max value for the distance sliders        
+        const float sliderMax = 100f;
+
+        // Width of the slider button
+        const int sliderButtonWidth = 10;
+
+        // Default value for the AI parameters
+        const float detectionDefault = 70.0f;
+        const float separationDefault = 50.0f;
+        const float moveInOldDirInfluenceDefault = 1.0f;
+        const float moveInFlockDirInfluenceDefault = 1.0f;
+        const float moveInRandomDirInfluenceDefault = 0.05f;
+        const float maxTurnRadiansDefault = 6.0f;
+        const float perMemberWeightDefault = 1.0f;
+        const float perDangerWeightDefault = 50.0f;
+        #endregion
+
+        #region Fields
+        GraphicsDeviceManager graphics;
+        SpriteBatch spriteBatch;
+        InputState inputState;
+        SpriteFont hudFont;
+
+        // Do we need to update AI parameers this Update
+        bool aiParameterUpdate = false;
+        bool moveCat = false;
+
+#if WINDOWS || XBOX
+        Texture2D bButton;
+        Texture2D xButton;
+        Texture2D yButton;
+#endif
+        Texture2D onePixelWhite;
+
+        Texture2D birdTexture;
+        Texture2D catTexture;
+
+        Cat cat;
+        Flock flock;
+
+        AIParameters flockParams;
+
+        // Definte the dimensions of the controls
+        Rectangle barDetectionDistance = new Rectangle(205, 45, 85, 40);
+        Rectangle barSeparationDistance = new Rectangle(205, 125, 85, 40);        
+        Rectangle buttonResetDistance = new Rectangle(105, 205, 140, 40);
+        Rectangle buttonResetFlock = new Rectangle(105, 285, 140, 40);
+        Rectangle buttonToggleCat = new Rectangle(105, 365, 140, 40);
+
+        int selectionNum;
+
+        #endregion
+
+        #region Initialization
+
+        public FlockingSample()
+        {
+            graphics = new GraphicsDeviceManager(this);
+            Content.RootDirectory = "Content";
+
+#if WINDOWS_PHONE || IOS
+            // Frame rate is 30 fps by default for Windows Phone.
+            TargetElapsedTime = TimeSpan.FromTicks(333333);
+            graphics.IsFullScreen = true;
+#endif
+            inputState = new InputState();
+
+            flock = null;
+            cat = null;
+
+            flockParams = new AIParameters();
+            ResetAIParams();
+        }
+
+        /// <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()
+        {
+            // Enable the gestures we care about. you must set EnabledGestures before
+            // you can use any of the other gesture APIs.
+            TouchPanel.EnabledGestures =
+                GestureType.Tap |
+                GestureType.FreeDrag;
+
+            base.Initialize();
+        }
+
+        /// <summary>
+        /// LoadContent will be called once per game and is the place to load
+        /// all of your content.
+        /// </summary>
+        protected override void LoadContent()
+        {
+            spriteBatch = new SpriteBatch(GraphicsDevice);
+
+            catTexture = Content.Load<Texture2D>("cat");
+            birdTexture = Content.Load<Texture2D>("mouse");
+
+#if WINDOWS || XBOX
+            bButton = Content.Load<Texture2D>("xboxControllerButtonB");
+            xButton = Content.Load<Texture2D>("xboxControllerButtonX");
+            yButton = Content.Load<Texture2D>("xboxControllerButtonY");
+#endif
+            hudFont = Content.Load<SpriteFont>("HUDFont");
+
+            onePixelWhite = new Texture2D(
+                GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
+            // TODO onePixelWhite.SetData<Color>(new Color[] { Color.White });
+        }
+
+        #endregion
+
+        #region Handle Input
+
+        /// <summary>
+        /// Handles input for quitting the game.
+        /// </summary>
+        void HandleInput()
+        {
+            inputState.Update();
+            
+            // Check for exit.
+            if (inputState.Exit)
+            {
+                Exit();
+            }
+            
+            float dragDelta = 0f;
+
+            // Check to see whether the user wants to modify their currently selected
+            // weight.
+            if (inputState.Up)
+            {
+                selectionNum--;
+                if (selectionNum < 0)
+                    selectionNum = 1;
+            }
+
+            if (inputState.Down)
+            {
+                selectionNum = (selectionNum + 1) % 2;
+            }
+
+            // Update move for the cat
+            if (cat != null)
+            {
+                cat.HandleInput(inputState);
+            }
+
+            // Turn the cat on or off
+            if (inputState.ToggleCatButton)
+            {
+                ToggleCat();
+            }
+
+            // Resets flock parameters back to default
+            if (inputState.ResetDistances)
+            {
+                ResetAIParams();
+                aiParameterUpdate = true;
+            }
+
+            // Resets the location and orientation of the members of the flock
+            if (inputState.ResetFlock)
+            {
+                flock.ResetFlock();
+                aiParameterUpdate = true;
+            }
+
+            dragDelta = inputState.SliderMove;
+
+            // Apply to the changeAmount to the currentlySelectedWeight
+            switch (selectionNum)
+            {
+                case 0:
+                    flockParams.DetectionDistance += dragDelta;
+                    break;
+                case 1:
+                    flockParams.SeparationDistance += dragDelta;
+                    break;
+                default:
+                    break;
+            }
+
+            if (dragDelta != 0f)
+                aiParameterUpdate = true;
+
+            // By default we can move the cat but if a touch registers against a control do not move the cat
+            moveCat = true;
+            
+            TouchCollection rawTouch = TouchPanel.GetState();
+            
+            // Use raw touch for the sliders
+            if (rawTouch.Count > 0)
+            {
+                // Only grab the first one
+                TouchLocation touchLocation = rawTouch[0];
+
+                // Create a collidable rectangle to determine if we touched the controls
+                Rectangle touchRectangle = new Rectangle((int)touchLocation.Position.X, 
+                                                         (int)touchLocation.Position.Y, 20, 20);
+
+                // Have the sliders rely on the raw touch to function properly
+                SliderInputHelper(touchRectangle);
+            }
+                       
+            // Next we handle all of the gestures. since we may have multiple gestures available,
+            // we use a loop to read in all of the gestures. this is important to make sure the 
+            // TouchPanel's queue doesn't get backed up with old data
+            while (TouchPanel.IsGestureAvailable)
+            {                
+                // Read the next gesture from the queue
+                GestureSample gesture = TouchPanel.ReadGesture();
+
+                // Create a collidable rectangle to determine if we touched the controls
+                Rectangle touch = new Rectangle((int)gesture.Position.X, (int)gesture.Position.Y, 20, 20);
+                               
+                // We can use the type of gesture to determine our behavior
+                switch (gesture.GestureType)
+                {                        
+                    case GestureType.Tap:
+                       
+                        if (buttonResetDistance.Intersects(touch))
+                        {                            
+                            // Resets flock parameters back to default                            
+                            ResetAIParams();
+                            aiParameterUpdate = true;
+                            moveCat = false;
+                        }
+                        else if (buttonResetFlock.Intersects(touch))
+                        {
+                            // Resets the location and orientation of the members of the flock
+                            flock.ResetFlock();
+                            aiParameterUpdate = true;
+                            moveCat = false;
+                        }
+                        else if (buttonToggleCat.Intersects(touch))
+                        {
+                            ToggleCat();
+                            moveCat = false;
+                        }                        
+
+                        break;
+                }
+
+                // Check if we can move the cat
+                if (cat != null && moveCat)
+                {
+                    // If we did not touch any controls then move the cat
+                    cat.Location = gesture.Position;
+                }
+            }            
+
+            // Clamp the slider values
+            flockParams.DetectionDistance = MathHelper.Clamp(flockParams.DetectionDistance, sliderMin, sliderMax);
+            flockParams.SeparationDistance = MathHelper.Clamp(flockParams.SeparationDistance, sliderMin, sliderMax);
+
+            if (aiParameterUpdate)
+            {
+                flock.FlockParams = flockParams;
+            }
+        }
+
+        /// <summary>
+        /// Helper function that handles Slider interaction logic
+        /// </summary>
+        /// <param name="touchRectangle">Rectangle representing a touch</param>
+        private void SliderInputHelper( Rectangle touchRectangle)
+        {
+            if (barDetectionDistance.Intersects(touchRectangle))
+            {
+                selectionNum = 0;
+                aiParameterUpdate = true;
+                moveCat = false;
+                flockParams.DetectionDistance = touchRectangle.X - barDetectionDistance.X;
+            }
+            else if (barSeparationDistance.Intersects(touchRectangle))
+            {
+                selectionNum = 1;
+                aiParameterUpdate = true;
+                moveCat = false;
+                flockParams.SeparationDistance = touchRectangle.X - barDetectionDistance.X;
+            }            
+        }
+
+        #endregion
+
+        #region Update and Draw
+
+        /// <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)
+        {
+            HandleInput();
+
+            if (cat != null)
+            {
+                cat.Update(gameTime);
+            }
+
+            if (flock != null)
+            {
+                flock.Update(gameTime, cat);
+            }
+            else
+            {
+                SpawnFlock();
+            }
+
+            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);
+
+            spriteBatch.Begin();
+
+            if (flock != null)
+            {
+                flock.Draw(spriteBatch, gameTime);
+            }
+
+            if (cat != null)
+            {
+                cat.Draw(spriteBatch, gameTime);
+            }
+
+            // Draw all the HUD elements
+            DrawBar(barDetectionDistance, flockParams.DetectionDistance / 100f, 
+                    "Detection Distance:", gameTime, selectionNum == 0);
+
+            DrawBar(barSeparationDistance, flockParams.SeparationDistance / 100f, 
+                    "Separation  Distance:", gameTime, selectionNum == 1);
+
+#if WINDOWS_PHONE || IOS
+            DrawButton(buttonResetDistance, "Reset Distance");
+            DrawButton(buttonResetFlock, "Reset Flock");
+            DrawButton(buttonToggleCat, "Add/Remove Cat");
+#else
+            spriteBatch.Draw(bButton, 
+                new Vector2(hudLocX + 110.0f, hudLocY), Color.White);
+            spriteBatch.Draw(xButton, 
+                new Vector2(hudLocX + 110.0f, hudLocY + 20.0f), Color.White);
+            spriteBatch.Draw(yButton, 
+                new Vector2(hudLocX + 110.0f, hudLocY + 40.0f), Color.White);
+
+            spriteBatch.DrawString(hudFont, "Reset Distances", 
+                new Vector2(hudLocX + 135.0f, hudLocY), Color.White);
+            spriteBatch.DrawString(hudFont, "Reset flock", 
+                new Vector2(hudLocX + 135.0f, hudLocY+20.0f), Color.White);
+            spriteBatch.DrawString(hudFont, "Spawn/remove cat", 
+                new Vector2(hudLocX + 135.0f, hudLocY+40.0f), Color.White);
+            
+#endif
+            spriteBatch.End();
+            base.Draw(gameTime);
+        }
+
+        /// <summary>
+        /// Helper function used by Draw. It is used to draw the buttons
+        /// </summary>
+        /// <param name="button"></param>
+        /// <param name="label"></param>
+        private void DrawButton(Rectangle button, string label)
+        {
+            spriteBatch.Draw(onePixelWhite, button, Color.Orange);
+            spriteBatch.DrawString(hudFont, label, new Vector2(button.Left + 10, button.Top + 10), Color.Black);
+        }
+
+        /// <summary>
+        /// Helper function used by Draw. It is used to draw the slider bars
+        /// </summary>
+        private void DrawBar(Rectangle bar, float barWidthNormalized, string label, GameTime gameTime, bool highlighted)
+        {
+            Color tintColor = Color.White;
+
+            // If the bar is highlighted, we want to make it pulse with a red tint.
+            if (highlighted)
+            {
+                // To do this, we'll first generate a value t, which we'll use to
+                // determine how much tint to have.
+                float t = (float)Math.Sin(10 * gameTime.TotalGameTime.TotalSeconds);
+
+                // Sin varies from -1 to 1, and we want t to go from 0 to 1, so we'll 
+                // scale it now.
+                t = .5f + .5f * t;
+
+                // Finally, we'll calculate our tint color by using Lerp to generate
+                // a color in between Red and White.
+                tintColor = new Color(Vector4.Lerp(
+                    Color.Red.ToVector4(), Color.White.ToVector4(), t));
+            }
+
+            // Calculate how wide the bar should be, and then draw it.            
+            bar.Height /= 2;
+            spriteBatch.Draw(onePixelWhite, bar, Color.White);
+
+            // Draw the slider
+            spriteBatch.Draw(onePixelWhite, new Rectangle(bar.X + (int)(bar.Width * barWidthNormalized), 
+                             bar.Y - bar.Height / 2, sliderButtonWidth, bar.Height * 2), Color.Orange);
+
+            // Finally, draw the label to the left of the bar.
+            Vector2 labelSize = hudFont.MeasureString(label);
+            Vector2 labelPosition = new Vector2(bar.X - 5 - labelSize.X, bar.Y);
+            spriteBatch.DrawString(hudFont, label, labelPosition, tintColor);
+        }
+
+        #endregion
+
+        #region Methods
+        /// <summary>
+        /// Create the bird flock
+        /// </summary>
+        /// <param name="theNum"></param>
+        protected void SpawnFlock()
+        {
+            if (flock == null)
+            {
+                flock = new Flock(birdTexture, GraphicsDevice.Viewport.TitleSafeArea.Width, 
+                                  GraphicsDevice.Viewport.TitleSafeArea.Height, flockParams);
+            }
+        }
+
+        /// <summary>
+        /// Reset flock AI parameters
+        /// </summary>
+        private void ResetAIParams()
+        {
+            flockParams.DetectionDistance = detectionDefault;
+            flockParams.SeparationDistance = separationDefault;
+            flockParams.MoveInOldDirectionInfluence = moveInOldDirInfluenceDefault;
+            flockParams.MoveInFlockDirectionInfluence = moveInFlockDirInfluenceDefault;
+            flockParams.MoveInRandomDirectionInfluence = moveInRandomDirInfluenceDefault;
+            flockParams.MaxTurnRadians = maxTurnRadiansDefault;
+            flockParams.PerMemberWeight = perMemberWeightDefault;
+            flockParams.PerDangerWeight = perDangerWeightDefault;
+        }
+
+        /// <summary>
+        /// Create or remove the cat
+        /// </summary>
+        protected void ToggleCat()
+        {
+            if (cat == null)
+            {
+                cat = new Cat(catTexture, GraphicsDevice.Viewport.TitleSafeArea.Width, 
+                              GraphicsDevice.Viewport.TitleSafeArea.Height);
+            }
+            else
+            {
+                cat = null;
+            }
+        }
+        #endregion
+    }
+}

BIN
Flocking/GameThumbnail.png


+ 22 - 0
Flocking/Info.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDisplayName</key>
+	<string>Flocking</string>
+	<key>CFBundleIconFiles</key>
+	<array>
+		<string>GameThumbnail.png</string>
+	</array>
+	<key>CFBundleIdentifier</key>
+	<string>project.MonoGame.Flocking</string>
+	<key>MinimumOSVersion</key>
+	<string>4.2</string>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+</dict>
+</plist>
+

+ 217 - 0
Flocking/InputState.cs

@@ -0,0 +1,217 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// InputState.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+#endregion
+
+namespace Flocking
+{
+    /// <summary>
+    /// Helper for reading input from keyboard and gamepad. This public class tracks
+    /// the current and previous state of both input devices, and implements query
+    /// properties for high level input actions such as "move up through the menu"
+    /// or "pause the game".
+    /// </summary>
+    /// <remarks>
+    /// This public class is similar to one in the GameStateManagement sample.
+    /// </remarks>
+    public class InputState
+    {
+        #region Fields
+
+        public KeyboardState CurrentKeyState;
+        public GamePadState CurrentPadState;
+
+        public KeyboardState LastKeyState;
+        public GamePadState LastPadState;
+
+        #endregion
+
+        #region Properties
+
+
+        /// <summary>
+        /// Checks for Y move amount on either keyboard or gamepad.
+        /// </summary>
+        public float MoveCatY
+        {
+            get
+            {
+                if (CurrentKeyState.IsKeyDown(Keys.W))
+                {
+                    return -1.0f;
+                }
+                else if (CurrentKeyState.IsKeyDown(Keys.S))
+                {
+                    return 1.0f;
+                }
+                else
+                {
+                    //negative = move up
+                    return -(CurrentPadState.ThumbSticks.Left.Y);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Checks for X move amount on either keyboard or gamepad.
+        /// </summary>
+        public float MoveCatX
+        {
+            get
+            {
+                if (CurrentKeyState.IsKeyDown(Keys.A))
+                {
+                    return -1.0f;
+                }
+                else if (CurrentKeyState.IsKeyDown(Keys.D))
+                {
+                    return 1.0f;
+                }
+                else
+                {
+                    return CurrentPadState.ThumbSticks.Left.X;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Checks for slider move amount on either keyboard or gamepad.
+        /// </summary>
+        public float SliderMove
+        {
+            get
+            {
+                if (CurrentKeyState.IsKeyDown(Keys.Left)||
+                    CurrentPadState.IsButtonDown(Buttons.DPadLeft))
+                {
+                    return -1.0f;
+                }
+                else if (CurrentKeyState.IsKeyDown(Keys.Right) ||
+                    CurrentPadState.IsButtonDown(Buttons.DPadRight))
+                {
+                    return 1.0f;
+                }
+                return -CurrentPadState.Triggers.Left + CurrentPadState.Triggers.Right;
+            }
+        }
+
+        /// <summary>
+        /// Checks for a "menu cancel" input action (on either keyboard or gamepad).
+        /// </summary>
+        public bool Exit
+        {
+            get
+            {
+                return IsNewKeyPress(Keys.Escape) ||
+                       (CurrentPadState.Buttons.Back == ButtonState.Pressed &&
+                        LastPadState.Buttons.Back == ButtonState.Released);
+            }
+        }
+
+        /// <summary>
+        /// Checks for a "reset distances" input action (on either keyboard or gamepad).
+        /// </summary>
+        public bool ResetDistances
+        {
+            get
+            {
+                return IsNewKeyPress(Keys.B) ||
+                       (CurrentPadState.Buttons.B == ButtonState.Pressed &&
+                        LastPadState.Buttons.B == ButtonState.Released);
+            }
+        }
+
+        /// <summary>
+        /// Checks for a "reset flock" input action (on either keyboard or gamepad).
+        /// </summary>
+        public bool ResetFlock
+        {
+            get
+            {
+                return IsNewKeyPress(Keys.X) ||
+                       (CurrentPadState.Buttons.X == ButtonState.Pressed &&
+                        LastPadState.Buttons.X == ButtonState.Released);
+            }
+        }
+
+        /// <summary>
+        /// Checks for an "up" input action (on either keyboard or gamepad).
+        /// </summary>
+        public bool Up
+        {
+            get
+            {
+                return IsNewKeyPress(Keys.Up) ||
+                       (CurrentPadState.DPad.Up == ButtonState.Pressed &&
+                        LastPadState.DPad.Up == ButtonState.Released);
+            }
+        }
+
+        /// <summary>
+        /// Checks for an "down" input action (on either keyboard or gamepad).
+        /// </summary>
+        public bool Down
+        {
+            get
+            {
+                return IsNewKeyPress(Keys.Down) ||
+                       (CurrentPadState.DPad.Down == ButtonState.Pressed &&
+                        LastPadState.DPad.Down == ButtonState.Released);
+            }
+        }
+
+        /// <summary>
+        /// Add or remove the cat
+        /// </summary>
+        public bool ToggleCatButton
+        {
+            get
+            {
+                return IsNewKeyPress(Keys.Y) ||
+                       (CurrentPadState.Buttons.Y == ButtonState.Pressed &&
+                        LastPadState.Buttons.Y == ButtonState.Released);
+            }
+        }
+
+
+        #endregion
+
+        #region Methods
+
+
+        /// <summary>
+        /// Reads the latest state of the keyboard and gamepad.
+        /// </summary>
+        public void Update()
+        {
+            LastKeyState = CurrentKeyState;
+            LastPadState = CurrentPadState;
+
+            CurrentKeyState = Keyboard.GetState();
+            CurrentPadState = GamePad.GetState(PlayerIndex.One);
+        }
+
+
+        /// <summary>
+        /// Helper for checking if a key was newly pressed during this update.
+        /// </summary>
+        bool IsNewKeyPress(Keys key)
+        {
+            return (CurrentKeyState.IsKeyDown(key) &&
+                    LastKeyState.IsKeyUp(key));
+        }
+
+
+        #endregion
+    }
+}

+ 33 - 0
Flocking/Main.cs

@@ -0,0 +1,33 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+
+namespace Flocking
+{
+	[Register("AppDelegate")]
+	class Program : UIApplicationDelegate
+	{
+		FlockingSample game;
+
+		public override void FinishedLaunching (UIApplication app)
+		{
+			// Fun begins..
+			game = new FlockingSample ();
+			game.Run ();
+		}
+
+		/// <summary>
+		/// The main entry point for the application.
+		/// </summary>
+		static void Main (string[] args)
+		{
+			UIApplication.Main (args, null, "AppDelegate");
+		}
+	}    
+}
+
+

BIN
Flocking/Microsoft Permissive License.rtf


+ 133 - 0
Flocking/MonoGame.Samples.Flocking.iOS.csproj

@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{05EB969D-B86A-4071-A60F-122F474C5968}</ProjectGuid>
+    <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Flocking</RootNamespace>
+    <AssemblyName>Flocking</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
+    <DefineConstants>DEBUG;IOS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <MtouchDebug>true</MtouchDebug>
+    <MtouchProfiling>true</MtouchProfiling>
+    <MtouchLink>None</MtouchLink>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <MtouchLink>None</MtouchLink>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\iPhone\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <CodesignKey>iPhone Developer</CodesignKey>
+    <MtouchDebug>true</MtouchDebug>
+    <MtouchProfiling>true</MtouchProfiling>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\iPhone\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <CodesignKey>iPhone Developer</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\iPhone\Ad-Hoc</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <BuildIpa>true</BuildIpa>
+    <CodesignKey>iPhone Distribution</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\iPhone\AppStore</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <CodesignKey>iPhone Distribution</CodesignKey>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="monotouch" />
+    <Reference Include="OpenTK" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\MonoGame.Framework\MonoGame.Framework.iOS.csproj">
+      <Project>{DB8508BB-9849-4CC2-BC0F-8EB5DACB3C47}</Project>
+      <Name>MonoGame.Framework.iOS</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\ThirdParty\Lidgren.Network\Lidgren.Network.iOS.csproj">
+      <Project>{734EAA48-F1CA-481A-B391-0285BC0E8B40}</Project>
+      <Name>Lidgren.Network.iOS</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Animals\Animal.cs" />
+    <Compile Include="Animals\Bird.cs" />
+    <Compile Include="Animals\Cat.cs" />
+    <Compile Include="Behaviors\AlignBehavior.cs" />
+    <Compile Include="Behaviors\Behavior.cs" />
+    <Compile Include="Behaviors\Behaviors.cs" />
+    <Compile Include="Behaviors\CohesionBehavior.cs" />
+    <Compile Include="Behaviors\FleeBehavior.cs" />
+    <Compile Include="Behaviors\SeparationBehavior.cs" />
+    <Compile Include="Flock.cs" />
+    <Compile Include="FlockingSample.cs" />
+    <Compile Include="InputState.cs" />
+    <Compile Include="Program.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Info.plist" />
+    <None Include="Content\FlockingContent.contentproj" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="Default.png" />
+    <Content Include="GameThumbnail.png" />
+    <Content Include="Content\logo.png" />
+    <Content Include="Content\HUDFont.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="Content\cat.png" />
+    <Content Include="Content\mouse.png" />
+    <Content Include="Content\xboxControllerButtonB.png" />
+    <Content Include="Content\xboxControllerButtonX.png" />
+    <Content Include="Content\xboxControllerButtonY.png" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Folder Include="Animals\" />
+    <Folder Include="Behaviors\" />
+  </ItemGroup>
+</Project>

+ 32 - 0
Flocking/Program.cs

@@ -0,0 +1,32 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Program.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+#endregion
+
+namespace Flocking
+{
+#if WINDOWS || XBOX
+    static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        static void Main(string[] args)
+        {
+            using (FlockingSample game = new FlockingSample())
+            {
+                game.Run();
+            }
+        }
+    }
+#endif
+}
+

+ 6 - 0
Flocking/Properties/AppManifest.xml

@@ -0,0 +1,6 @@
+<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+>
+    <Deployment.Parts>
+    </Deployment.Parts>
+</Deployment>

+ 34 - 0
Flocking/Properties/AssemblyInfo.cs

@@ -0,0 +1,34 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Flocking")]
+[assembly: AssemblyProduct("Flocking")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type. Only Windows
+// assemblies support COM.
+[assembly: ComVisible(false)]
+
+// On Windows, the following GUID is for the ID of the typelib if this
+// project is exposed to COM. On other platforms, it unique identifies the
+// title storage container when deploying this assembly to the device.
+[assembly: Guid("f2314f25-bcd5-4b56-86fd-752ed82adddd")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]

+ 30 - 0
Flocking/Properties/WMAppManifest.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.0">
+  <App xmlns="" ProductID="{f2314f25-bcd5-4b56-86fd-752ed82adddd}" Title="Flocking" RuntimeType="XNA" Version="1.0.0.0" Genre="Apps.Normal" Author="" Description="" Publisher="">
+    <IconPath IsRelative="true" IsResource="false"></IconPath>
+    <Capabilities>
+        <Capability Name="ID_CAP_NETWORKING" />
+        <Capability Name="ID_CAP_LOCATION" />
+        <Capability Name="ID_CAP_SENSORS" />
+        <Capability Name="ID_CAP_MICROPHONE" />
+        <Capability Name="ID_CAP_MEDIALIB" />
+        <Capability Name="ID_CAP_GAMERSERVICES" />
+        <Capability Name="ID_CAP_PHONEDIALER" />
+        <Capability Name="ID_CAP_PUSH_NOTIFICATION" />
+        <Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
+    </Capabilities>
+    <Tasks>
+      <DefaultTask Name="_default"/>
+    </Tasks>
+    <Tokens>
+      <PrimaryToken TokenID="FlockingToken" TaskName="_default">
+        <TemplateType5>
+          <BackgroundImageURI IsRelative="true" IsResource="false"></BackgroundImageURI>
+          <Count>0</Count>
+          <Title></Title>
+        </TemplateType5>
+      </PrimaryToken>
+    </Tokens>
+  </App>
+</Deployment>
+