浏览代码

Flocking: Modernize project structure: move to Core/ and Platforms/, remove obsolete files, update solution and VSCode configs

CartBlanche 1 周之前
父节点
当前提交
046188932c
共有 58 个文件被更改,包括 2536 次插入3212 次删除
  1. 29 0
      Flocking/.vscode/launch.json
  2. 255 0
      Flocking/.vscode/tasks.json
  3. 171 198
      Flocking/Core/Animals/Animal.cs
  4. 255 295
      Flocking/Core/Animals/Bird.cs
  5. 94 115
      Flocking/Core/Animals/Cat.cs
  6. 37 51
      Flocking/Core/Behaviors/AlignBehavior.cs
  7. 66 83
      Flocking/Core/Behaviors/Behavior.cs
  8. 18 24
      Flocking/Core/Behaviors/Behaviors.cs
  9. 53 71
      Flocking/Core/Behaviors/CohesionBehavior.cs
  10. 39 54
      Flocking/Core/Behaviors/FleeBehavior.cs
  11. 50 69
      Flocking/Core/Behaviors/SeparationBehavior.cs
  12. 0 0
      Flocking/Core/Content/Background.png
  13. 85 0
      Flocking/Core/Content/Content.mgcb
  14. 0 0
      Flocking/Core/Content/Default.png
  15. 66 66
      Flocking/Core/Content/FlockingContent.contentproj
  16. 0 0
      Flocking/Core/Content/HUDFont.xnb
  17. 0 0
      Flocking/Core/Content/cat.png
  18. 二进制
      Flocking/Core/Content/cat.xnb
  19. 0 0
      Flocking/Core/Content/logo.png
  20. 二进制
      Flocking/Core/Content/logo.xnb
  21. 0 0
      Flocking/Core/Content/mouse.png
  22. 二进制
      Flocking/Core/Content/mouse.xnb
  23. 0 0
      Flocking/Core/Content/xboxControllerButtonB.png
  24. 二进制
      Flocking/Core/Content/xboxControllerButtonB.xnb
  25. 0 0
      Flocking/Core/Content/xboxControllerButtonX.png
  26. 二进制
      Flocking/Core/Content/xboxControllerButtonX.xnb
  27. 0 0
      Flocking/Core/Content/xboxControllerButtonY.png
  28. 二进制
      Flocking/Core/Content/xboxControllerButtonY.xnb
  29. 127 168
      Flocking/Core/Flock.cs
  30. 17 0
      Flocking/Core/Flocking.Core.csproj
  31. 489 542
      Flocking/Core/FlockingSample.cs
  32. 0 0
      Flocking/Core/GameThumbnail.png
  33. 181 217
      Flocking/Core/InputState.cs
  34. 0 90
      Flocking/Flocking.PSMobile.csproj
  35. 0 968
      Flocking/Flocking.htm
  36. 160 0
      Flocking/Flocking.sln
  37. 0 89
      Flocking/Main.cs
  38. 二进制
      Flocking/Microsoft Permissive License.rtf
  39. 34 0
      Flocking/Platforms/Android/Activity1.cs
  40. 29 0
      Flocking/Platforms/Android/AndroidManifest.xml
  41. 30 0
      Flocking/Platforms/Android/Flocking.Android.csproj
  42. 二进制
      Flocking/Platforms/Android/Resources/drawable/icon.png
  43. 4 0
      Flocking/Platforms/Android/Resources/values/strings.xml
  44. 21 0
      Flocking/Platforms/Desktop/Flocking.DesktopGL.csproj
  45. 14 0
      Flocking/Platforms/Desktop/Program.cs
  46. 0 0
      Flocking/Platforms/Info.plist
  47. 22 0
      Flocking/Platforms/Windows/Flocking.Windows.csproj
  48. 14 0
      Flocking/Platforms/Windows/Program.cs
  49. 34 0
      Flocking/Platforms/iOS/AppDelegate.cs
  50. 16 0
      Flocking/Platforms/iOS/Flocking.iOS.csproj
  51. 39 0
      Flocking/Platforms/iOS/Info.plist
  52. 15 0
      Flocking/Platforms/iOS/Program.cs
  53. 0 32
      Flocking/Program.cs
  54. 0 6
      Flocking/Properties/AppManifest.xml
  55. 0 34
      Flocking/Properties/AssemblyInfo.cs
  56. 0 30
      Flocking/Properties/WMAppManifest.xml
  57. 72 0
      Flocking/README.md
  58. 0 10
      Flocking/app.xml

+ 29 - 0
Flocking/.vscode/launch.json

@@ -0,0 +1,29 @@
+{
+  "version": "0.2.0",
+  "configurations": [
+    {
+      "name": "Launch DesktopGL",
+      "type": "coreclr",
+      "request": "launch",
+      "preLaunchTask": "build-desktopgl",
+      "program": "${workspaceFolder}/Platforms/Desktop/bin/Debug/net8.0/Flocking.DesktopGL.dll",
+      "args": [],
+      "cwd": "${workspaceFolder}/Platforms/Desktop",
+      "console": "internalConsole",
+      "stopAtEntry": false,
+      "internalConsoleOptions": "openOnSessionStart"
+    },
+    {
+      "name": "Launch Windows",
+      "type": "coreclr",
+      "request": "launch",
+      "preLaunchTask": "build-windows",
+      "program": "${workspaceFolder}/Platforms/Windows/bin/Debug/net8.0-windows/Flocking.Windows.exe",
+      "args": [],
+      "cwd": "${workspaceFolder}/Platforms/Windows",
+      "console": "internalConsole",
+      "stopAtEntry": false,
+      "internalConsoleOptions": "openOnSessionStart"
+    }
+  ]
+}

+ 255 - 0
Flocking/.vscode/tasks.json

@@ -0,0 +1,255 @@
+{
+  "version": "2.0.0",
+  "tasks": [
+    {
+      "label": "build-desktopgl",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "build",
+        "${workspaceFolder}/Platforms/Desktop/Flocking.DesktopGL.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      },
+      "problemMatcher": "$msCompile"
+    },
+    {
+      "label": "build-windows",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "build",
+        "${workspaceFolder}/Platforms/Windows/Flocking.Windows.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      },
+      "problemMatcher": "$msCompile"
+    },
+    {
+      "label": "run-desktopgl",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "run",
+        "--project",
+        "${workspaceFolder}/Platforms/Desktop/Flocking.DesktopGL.csproj"
+      ],
+      "group": "test",
+      "presentation": {
+        "echo": true,
+        "reveal": "always",
+        "focus": false,
+        "panel": "shared"
+      },
+      "dependsOn": "build-desktopgl"
+    },
+    {
+      "label": "run-windows",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "run",
+        "--project",
+        "${workspaceFolder}/Platforms/Windows/Flocking.Windows.csproj"
+      ],
+      "group": "test",
+      "presentation": {
+        "echo": true,
+        "reveal": "always",
+        "focus": false,
+        "panel": "shared"
+      },
+      "dependsOn": "build-windows"
+    },
+    {
+      "label": "clean-desktopgl",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "clean",
+        "${workspaceFolder}/Platforms/Desktop/Flocking.DesktopGL.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      }
+    },
+    {
+      "label": "clean-windows",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "clean",
+        "${workspaceFolder}/Platforms/Windows/Flocking.Windows.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      }
+    },
+    {
+      "label": "restore-desktopgl",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "restore",
+        "${workspaceFolder}/Platforms/Desktop/Flocking.DesktopGL.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      }
+    },
+    {
+      "label": "restore-windows",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "restore",
+        "${workspaceFolder}/Platforms/Windows/Flocking.Windows.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      }
+    },
+    {
+      "label": "build-android",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "build",
+        "${workspaceFolder}/Platforms/Android/Flocking.Android.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      },
+      "problemMatcher": "$msCompile"
+    },
+    {
+      "label": "build-ios",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "build",
+        "${workspaceFolder}/Platforms/iOS/Flocking.iOS.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      },
+      "problemMatcher": "$msCompile"
+    },
+    {
+      "label": "run-android",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "run",
+        "--project",
+        "${workspaceFolder}/Platforms/Android/Flocking.Android.csproj"
+      ],
+      "group": "test",
+      "presentation": {
+        "echo": true,
+        "reveal": "always",
+        "focus": false,
+        "panel": "shared"
+      },
+      "dependsOn": "build-android"
+    },
+    {
+      "label": "clean-android",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "clean",
+        "${workspaceFolder}/Platforms/Android/Flocking.Android.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      }
+    },
+    {
+      "label": "clean-ios",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "clean",
+        "${workspaceFolder}/Platforms/iOS/Flocking.iOS.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      }
+    },
+    {
+      "label": "restore-android",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "restore",
+        "${workspaceFolder}/Platforms/Android/Flocking.Android.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      }
+    },
+    {
+      "label": "restore-ios",
+      "command": "dotnet",
+      "type": "shell",
+      "args": [
+        "restore",
+        "${workspaceFolder}/Platforms/iOS/Flocking.iOS.csproj"
+      ],
+      "group": "build",
+      "presentation": {
+        "echo": true,
+        "reveal": "silent",
+        "focus": false,
+        "panel": "shared"
+      }
+    }
+  ]
+}

+ 171 - 198
Flocking/Animals/Animal.cs → Flocking/Core/Animals/Animal.cs

@@ -1,198 +1,171 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// Animal.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+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
+    {
+        /// <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;
+        /// <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>();
+        }
+        /// <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);
+        }
+    }
+}

+ 255 - 295
Flocking/Animals/Bird.cs → Flocking/Core/Animals/Bird.cs

@@ -1,295 +1,255 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// Bird.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+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.Graphics;
+using Microsoft.Xna.Framework.Input;
+namespace Flocking
+{
+    class Bird : Animal
+    {
+        protected Random random;
+        Vector2 aiNewDir;
+        int aiNumSeen;
+        /// <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();
+        }
+        /// <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);
+        }
+        /// <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;
+        }
+    }
+}

+ 94 - 115
Flocking/Animals/Cat.cs → Flocking/Core/Animals/Cat.cs

@@ -1,115 +1,94 @@
-#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
-
-    }
-}
+//-----------------------------------------------------------------------------
+// Cat.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+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.Graphics;
+using Microsoft.Xna.Framework.Input;
+namespace Flocking
+{
+    /// <summary>
+    /// Represents a dangerous object that the flocks flees from
+    /// </summary>
+    class Cat : Animal
+    {
+        protected Vector2 center;
+        /// <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;
+        }
+        /// <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);
+        }
+        /// <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;
+        }
+    }
+}

+ 37 - 51
Flocking/Behaviors/AlignBehavior.cs → Flocking/Core/Behaviors/AlignBehavior.cs

@@ -1,51 +1,37 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// AlignBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Xna.Framework;
+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
+    {
+        public AlignBehavior(Animal animal)
+            : base(animal)
+        {
+        }
+        /// <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;
+            }
+        }
+    }
+}

+ 66 - 83
Flocking/Behaviors/Behavior.cs → Flocking/Core/Behaviors/Behavior.cs

@@ -1,83 +1,66 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// Behavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Xna.Framework;
+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
+    {
+        /// <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;
+        protected Behavior(Animal animal)
+        {
+            this.animal = animal;
+        }
+        /// <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;
+        }
+    }
+}

+ 18 - 24
Flocking/Behaviors/Behaviors.cs → Flocking/Core/Behaviors/Behaviors.cs

@@ -1,24 +1,18 @@
-#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>
-    {
-    }
-}
+//-----------------------------------------------------------------------------
+// AlignBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+namespace Flocking
+{
+    /// <summary>
+    /// Container for Behavior Classes
+    /// </summary>
+    public class Behaviors : List<Behavior>
+    {
+    }
+}

+ 53 - 71
Flocking/Behaviors/CohesionBehavior.cs → Flocking/Core/Behaviors/CohesionBehavior.cs

@@ -1,71 +1,53 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// CohesionBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Xna.Framework;
+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
+    {
+        public CohesionBehavior(Animal animal)
+            : base(animal)
+        {
+        }
+        /// <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;
+            }
+        }
+    }
+}

+ 39 - 54
Flocking/Behaviors/FleeBehavior.cs → Flocking/Core/Behaviors/FleeBehavior.cs

@@ -1,54 +1,39 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// FleeBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Xna.Framework;
+namespace Flocking
+{
+    /// <summary>
+    /// FleeBehavior is a Behavior that makes an animal run from another
+    /// </summary>
+    public class FleeBehavior : Behavior
+    {
+        public FleeBehavior(Animal animal)
+            : base(animal)
+        {
+        }
+        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);
+            }
+        }
+    }
+}

+ 50 - 69
Flocking/Behaviors/SeparationBehavior.cs → Flocking/Core/Behaviors/SeparationBehavior.cs

@@ -1,69 +1,50 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// SeparationBehavior.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Xna.Framework;
+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
+    {
+        public SeparationBehavior(Animal animal)
+            : base(animal)
+        {
+        }
+        /// <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;
+            }
+        }
+    }
+}

+ 0 - 0
Flocking/Background.png → Flocking/Core/Content/Background.png


+ 85 - 0
Flocking/Core/Content/Content.mgcb

@@ -0,0 +1,85 @@
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin/$(Platform)
+/intermediateDir:obj/$(Platform)
+/platform:DesktopGL
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+
+#---------------------------------- Content ----------------------------------#
+
+#begin cat.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:cat.png
+
+#begin mouse.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:mouse.png
+
+#begin logo.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:logo.png
+
+#begin xboxControllerButtonB.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:xboxControllerButtonB.png
+
+#begin xboxControllerButtonX.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:xboxControllerButtonX.png
+
+#begin xboxControllerButtonY.png
+/importer:TextureImporter
+/processor:TextureProcessor
+/processorParam:ColorKeyColor=255,0,255,255
+/processorParam:ColorKeyEnabled=True
+/processorParam:GenerateMipmaps=False
+/processorParam:PremultiplyAlpha=True
+/processorParam:ResizeToPowerOfTwo=False
+/processorParam:MakeSquare=False
+/processorParam:TextureFormat=Color
+/build:xboxControllerButtonY.png

+ 0 - 0
Flocking/Default.png → Flocking/Core/Content/Default.png


+ 66 - 66
Flocking/Content/FlockingContent.contentproj → Flocking/Core/Content/FlockingContent.contentproj

@@ -1,67 +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>
-  -->
+<?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>

+ 0 - 0
Flocking/Content/HUDFont.xnb → Flocking/Core/Content/HUDFont.xnb


+ 0 - 0
Flocking/Content/cat.png → Flocking/Core/Content/cat.png


二进制
Flocking/Core/Content/cat.xnb


+ 0 - 0
Flocking/Content/logo.png → Flocking/Core/Content/logo.png


二进制
Flocking/Core/Content/logo.xnb


+ 0 - 0
Flocking/Content/mouse.png → Flocking/Core/Content/mouse.png


二进制
Flocking/Core/Content/mouse.xnb


+ 0 - 0
Flocking/Content/xboxControllerButtonB.png → Flocking/Core/Content/xboxControllerButtonB.png


二进制
Flocking/Core/Content/xboxControllerButtonB.xnb


+ 0 - 0
Flocking/Content/xboxControllerButtonX.png → Flocking/Core/Content/xboxControllerButtonX.png


二进制
Flocking/Core/Content/xboxControllerButtonX.xnb


+ 0 - 0
Flocking/Content/xboxControllerButtonY.png → Flocking/Core/Content/xboxControllerButtonY.png


二进制
Flocking/Core/Content/xboxControllerButtonY.xnb


+ 127 - 168
Flocking/Flock.cs → Flocking/Core/Flock.cs

@@ -1,168 +1,127 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// Flock.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+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;
+namespace Flocking
+{
+    /// <summary>
+    /// This class manages all the birds in the flock and handles 
+    /// their update and draw
+    /// </summary>
+    class Flock
+    {
+        //Number of FLock members
+        const int flockSize = 40;
+        //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;
+        /// <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();
+        }
+        /// <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);
+            }
+        }
+        /// <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);
+            }
+        }
+    }
+}

+ 17 - 0
Flocking/Core/Flocking.Core.csproj

@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>Flocking.Core</RootNamespace>
+    <AssemblyName>Flocking.Core</AssemblyName>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="Content\**\*.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+</Project>

+ 489 - 542
Flocking/FlockingSample.cs → Flocking/Core/FlockingSample.cs

@@ -1,542 +1,489 @@
-#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 || PSM
-            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
-    }
-}
+//-----------------------------------------------------------------------------
+// FlockingSample.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+
+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;
+
+namespace Flocking
+{
+    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;
+    }
+    /// <summary>
+    /// This is the main type for your game
+    /// </summary>
+    public class FlockingSample : Microsoft.Xna.Framework.Game
+    {
+        // 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;
+        GraphicsDeviceManager graphics;
+        SpriteBatch spriteBatch;
+        InputState inputState;
+        SpriteFont hudFont;
+        // Do we need to update AI parameers this Update
+        bool aiParameterUpdate = false;
+        bool moveCat = false;
+
+        Texture2D bButton;
+        Texture2D xButton;
+        Texture2D yButton;
+
+        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(hudLocX + 110, hudLocY, 140, 40);
+        Rectangle buttonResetFlock = new Rectangle(hudLocX + 110, hudLocY + 20, 140, 40);
+        Rectangle buttonToggleCat = new Rectangle(hudLocX + 110, hudLocY + 40, 140, 40);
+        int selectionNum;
+        private bool lastMousePressed;
+        public FlockingSample()
+        {
+            graphics = new GraphicsDeviceManager(this);
+            graphics.SupportedOrientations = DisplayOrientation.Portrait;
+			graphics.PreferredBackBufferWidth = 600;
+			graphics.PreferredBackBufferHeight = 720;
+
+            Content.RootDirectory = "Content";
+            IsMouseVisible = true;
+
+#if ___MOBILE___
+            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");
+
+            bButton = Content.Load<Texture2D>("xboxControllerButtonB");
+            xButton = Content.Load<Texture2D>("xboxControllerButtonX");
+            yButton = Content.Load<Texture2D>("xboxControllerButtonY");
+
+            hudFont = Content.Load<SpriteFont>("HUDFont");
+            onePixelWhite = new Texture2D(
+                GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
+            onePixelWhite.SetData<Color>(new Color[] { Color.White });
+        }
+        /// <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 or mouse 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);
+            }
+            // Handle gestures (taps)
+            while (TouchPanel.IsGestureAvailable)
+            {
+                GestureSample gesture = TouchPanel.ReadGesture();
+                Rectangle touch = new Rectangle((int)gesture.Position.X, (int)gesture.Position.Y, 20, 20);
+                switch (gesture.GestureType)
+                {
+                    case GestureType.Tap:
+                        HandleButtonTap(touch);
+                        break;
+                }
+                if (cat != null && moveCat)
+                {
+                    cat.Location = gesture.Position;
+                }
+            }
+
+            // Mouse input for desktop
+            MouseState mouse = Mouse.GetState();
+            Rectangle mouseRect = new Rectangle(mouse.X, mouse.Y, 1, 1);
+            bool mousePressed = mouse.LeftButton == ButtonState.Pressed;
+            bool mouseJustPressed = mousePressed && lastMousePressed == false;
+            lastMousePressed = mousePressed;
+
+            // Sliders: click or drag
+            if (mousePressed)
+            {
+                if (barDetectionDistance.Intersects(mouseRect))
+                {
+                    selectionNum = 0;
+                    aiParameterUpdate = true;
+                    moveCat = false;
+                    flockParams.DetectionDistance = mouse.X - barDetectionDistance.X;
+                }
+                else if (barSeparationDistance.Intersects(mouseRect))
+                {
+                    selectionNum = 1;
+                    aiParameterUpdate = true;
+                    moveCat = false;
+                    flockParams.SeparationDistance = mouse.X - barDetectionDistance.X;
+                }
+            }
+
+            // Buttons: single click
+            if (mouseJustPressed)
+            {
+                if (HandleButtonTap(mouseRect))
+                {
+                    moveCat = false;
+                }
+            }
+
+            // Move cat by clicking anywhere else
+            if (cat != null && moveCat && mouseJustPressed)
+            {
+                cat.Location = new Vector2(mouse.X, mouse.Y);
+            }
+
+            // 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;
+            }
+
+        }
+
+        // Shared button tap handler for both touch and mouse
+        private bool HandleButtonTap(Rectangle tapRect)
+        {
+            if (buttonResetDistance.Intersects(tapRect))
+            {
+                ResetAIParams();
+                aiParameterUpdate = true;
+                return true;
+            }
+            else if (buttonResetFlock.Intersects(tapRect))
+            {
+                flock.ResetFlock();
+                aiParameterUpdate = true;
+                return true;
+            }
+            else if (buttonToggleCat.Intersects(tapRect))
+            {
+                ToggleCat();
+                return true;
+            }
+            return false;
+        }
+        /// <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;
+            }            
+        }
+        /// <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);
+
+            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);
+#if DEBUG
+            spriteBatch.DrawString(hudFont, $"Mouse: {Mouse.GetState().Position.ToString()}",
+                new Vector2(hudLocX + 135.0f, hudLocY + 60.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);
+        }
+        /// <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;
+            }
+        }
+    }
+}

+ 0 - 0
Flocking/GameThumbnail.png → Flocking/Core/GameThumbnail.png


+ 181 - 217
Flocking/InputState.cs → Flocking/Core/InputState.cs

@@ -1,217 +1,181 @@
-#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
-    }
-}
+//-----------------------------------------------------------------------------
+// InputState.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+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
+    {
+        public KeyboardState CurrentKeyState;
+        public GamePadState CurrentPadState;
+        public KeyboardState LastKeyState;
+        public GamePadState LastPadState;
+        /// <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);
+            }
+        }
+        /// <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));
+        }
+    }
+}

+ 0 - 90
Flocking/Flocking.PSMobile.csproj

@@ -1,90 +0,0 @@
-<?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)' == '' ">AnyCPU</Platform>
-    <ProductVersion>10.0.0</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{F0B32BB5-1E28-453B-B4D6-BEC0E159DFB1}</ProjectGuid>
-    <ProjectTypeGuids>{69878862-DA7D-4DC6-B0A1-50D8FAB4242F};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
-    <OutputType>Exe</OutputType>
-    <RootNamespace>Flocking.PSMobile</RootNamespace>
-    <AssemblyName>Flocking.PSMobile</AssemblyName>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug</OutputPath>
-    <DefineConstants>DEBUG;PSM</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>none</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Release</OutputPath>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Core" />
-    <Reference Include="Sce.PlayStation.Core" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="Flock.cs" />
-    <Compile Include="FlockingSample.cs" />
-    <Compile Include="InputState.cs" />
-    <Compile Include="Main.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="Properties\AssemblyInfo.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <PsmMetadata Include="app.xml" />
-  </ItemGroup>
-  <Import Project="$(MSBuildExtensionsPath)\Sce\Sce.Psm.CSharp.targets" />
-  <ItemGroup>
-    <ProjectReference Include="..\..\MonoGame.Framework\MonoGame.Framework.PSMobile.csproj">
-      <Project>{EA26E76F-FDFE-4A8C-B5A3-C3B5761E28F9}</Project>
-      <Name>MonoGame.Framework.PSMobile</Name>
-    </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
-    <Folder Include="Content\" />
-  </ItemGroup>
-  <ItemGroup>
-    <Content Include="..\CompiledContent\Android\Content\Textures\cat.xnb">
-      <Link>Content\cat.xnb</Link>
-    </Content>
-    <Content Include="..\CompiledContent\Android\Content\Textures\logo.xnb">
-      <Link>Content\logo.xnb</Link>
-    </Content>
-    <Content Include="..\CompiledContent\Android\Content\Textures\mouse.xnb">
-      <Link>Content\mouse.xnb</Link>
-    </Content>
-    <Content Include="..\CompiledContent\Android\Content\Fonts\HUDFont.xnb">
-      <Link>Content\HUDFont.xnb</Link>
-    </Content>
-    <Content Include="..\CompiledContent\Android\Content\Textures\xboxControllerButtonB.xnb">
-      <Link>Content\xboxControllerButtonB.xnb</Link>
-    </Content>
-    <Content Include="..\CompiledContent\Android\Content\Textures\xboxControllerButtonX.xnb">
-      <Link>Content\xboxControllerButtonX.xnb</Link>
-    </Content>
-    <Content Include="..\CompiledContent\Android\Content\Textures\xboxControllerButtonY.xnb">
-      <Link>Content\xboxControllerButtonY.xnb</Link>
-    </Content>
-  </ItemGroup>
-</Project>

+ 0 - 968
Flocking/Flocking.htm

@@ -1,968 +0,0 @@
-<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>

+ 160 - 0
Flocking/Flocking.sln

@@ -0,0 +1,160 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.2.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flocking.DesktopGL", "Flocking.DesktopGL.csproj", "{2F11B2AB-FD16-1B27-7C3F-72B356E15847}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flocking.Windows", "Flocking.Windows.csproj", "{F6644476-5880-3A16-ED8A-FB06A0F1394F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flocking.Android", "Flocking.Android.csproj", "{7938BD41-E3F0-78E0-20EB-3E5806E30F38}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flocking.iOS", "Flocking.iOS.csproj", "{13685E8F-3D51-C405-652E-8361DB8A84C1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{FBF56CC3-7AE6-AD2D-3F14-7F97FD322CD6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flocking.Core", "Core\Flocking.Core.csproj", "{1372D093-204C-4DCC-844F-D42929A6536B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platforms", "Platforms", "{324791A1-5798-203D-0CA6-A8E0DAEC81C8}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Windows", "Windows", "{E4D925BB-EB21-135E-07FA-7558DA769730}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flocking.Windows", "Platforms\Windows\Flocking.Windows.csproj", "{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Desktop", "Desktop", "{5A24DBFA-C605-72AB-2DAB-0CDF0C553B09}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flocking.DesktopGL", "Platforms\Desktop\Flocking.DesktopGL.csproj", "{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{C12F4581-1215-E9D3-7920-679DE6ABBC05}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flocking.Android", "Platforms\Android\Flocking.Android.csproj", "{61C7AFDF-725C-4833-8332-D812162E64AF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{3260BC3A-D039-20BF-4861-22673C64F5D4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flocking.iOS", "Platforms\iOS\Flocking.iOS.csproj", "{92C8095D-B85D-4C5F-A535-D5837C047EDF}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Debug|x64.Build.0 = Debug|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Debug|x86.Build.0 = Debug|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Release|x64.ActiveCfg = Release|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Release|x64.Build.0 = Release|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Release|x86.ActiveCfg = Release|Any CPU
+		{2F11B2AB-FD16-1B27-7C3F-72B356E15847}.Release|x86.Build.0 = Release|Any CPU
+		{F6644476-5880-3A16-ED8A-FB06A0F1394F}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{F6644476-5880-3A16-ED8A-FB06A0F1394F}.Debug|x64.Build.0 = Debug|Any CPU
+		{F6644476-5880-3A16-ED8A-FB06A0F1394F}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{F6644476-5880-3A16-ED8A-FB06A0F1394F}.Debug|x86.Build.0 = Debug|Any CPU
+		{F6644476-5880-3A16-ED8A-FB06A0F1394F}.Release|x64.ActiveCfg = Release|Any CPU
+		{F6644476-5880-3A16-ED8A-FB06A0F1394F}.Release|x64.Build.0 = Release|Any CPU
+		{F6644476-5880-3A16-ED8A-FB06A0F1394F}.Release|x86.ActiveCfg = Release|Any CPU
+		{F6644476-5880-3A16-ED8A-FB06A0F1394F}.Release|x86.Build.0 = Release|Any CPU
+		{7938BD41-E3F0-78E0-20EB-3E5806E30F38}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{7938BD41-E3F0-78E0-20EB-3E5806E30F38}.Debug|x64.Build.0 = Debug|Any CPU
+		{7938BD41-E3F0-78E0-20EB-3E5806E30F38}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{7938BD41-E3F0-78E0-20EB-3E5806E30F38}.Debug|x86.Build.0 = Debug|Any CPU
+		{7938BD41-E3F0-78E0-20EB-3E5806E30F38}.Release|x64.ActiveCfg = Release|Any CPU
+		{7938BD41-E3F0-78E0-20EB-3E5806E30F38}.Release|x64.Build.0 = Release|Any CPU
+		{7938BD41-E3F0-78E0-20EB-3E5806E30F38}.Release|x86.ActiveCfg = Release|Any CPU
+		{7938BD41-E3F0-78E0-20EB-3E5806E30F38}.Release|x86.Build.0 = Release|Any CPU
+		{13685E8F-3D51-C405-652E-8361DB8A84C1}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{13685E8F-3D51-C405-652E-8361DB8A84C1}.Debug|x64.Build.0 = Debug|Any CPU
+		{13685E8F-3D51-C405-652E-8361DB8A84C1}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{13685E8F-3D51-C405-652E-8361DB8A84C1}.Debug|x86.Build.0 = Debug|Any CPU
+		{13685E8F-3D51-C405-652E-8361DB8A84C1}.Release|x64.ActiveCfg = Release|Any CPU
+		{13685E8F-3D51-C405-652E-8361DB8A84C1}.Release|x64.Build.0 = Release|Any CPU
+		{13685E8F-3D51-C405-652E-8361DB8A84C1}.Release|x86.ActiveCfg = Release|Any CPU
+		{13685E8F-3D51-C405-652E-8361DB8A84C1}.Release|x86.Build.0 = Release|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Debug|x64.Build.0 = Debug|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Debug|x86.Build.0 = Debug|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Release|Any CPU.Build.0 = Release|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Release|x64.ActiveCfg = Release|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Release|x64.Build.0 = Release|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Release|x86.ActiveCfg = Release|Any CPU
+		{1372D093-204C-4DCC-844F-D42929A6536B}.Release|x86.Build.0 = Release|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Debug|x64.Build.0 = Debug|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Debug|x86.Build.0 = Debug|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Release|Any CPU.Build.0 = Release|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Release|x64.ActiveCfg = Release|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Release|x64.Build.0 = Release|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Release|x86.ActiveCfg = Release|Any CPU
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB}.Release|x86.Build.0 = Release|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Debug|x64.Build.0 = Debug|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Debug|x86.Build.0 = Debug|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Release|x64.ActiveCfg = Release|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Release|x64.Build.0 = Release|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Release|x86.ActiveCfg = Release|Any CPU
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10}.Release|x86.Build.0 = Release|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Debug|x64.Build.0 = Debug|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Debug|x86.Build.0 = Debug|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Release|Any CPU.Build.0 = Release|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Release|x64.ActiveCfg = Release|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Release|x64.Build.0 = Release|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Release|x86.ActiveCfg = Release|Any CPU
+		{61C7AFDF-725C-4833-8332-D812162E64AF}.Release|x86.Build.0 = Release|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Debug|x64.Build.0 = Debug|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Debug|x86.Build.0 = Debug|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Release|Any CPU.Build.0 = Release|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Release|x64.ActiveCfg = Release|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Release|x64.Build.0 = Release|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Release|x86.ActiveCfg = Release|Any CPU
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF}.Release|x86.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{1372D093-204C-4DCC-844F-D42929A6536B} = {FBF56CC3-7AE6-AD2D-3F14-7F97FD322CD6}
+		{E4D925BB-EB21-135E-07FA-7558DA769730} = {324791A1-5798-203D-0CA6-A8E0DAEC81C8}
+		{1028A9B4-B31B-4ACC-95C6-8B0E456401FB} = {E4D925BB-EB21-135E-07FA-7558DA769730}
+		{5A24DBFA-C605-72AB-2DAB-0CDF0C553B09} = {324791A1-5798-203D-0CA6-A8E0DAEC81C8}
+		{B69DE357-216C-4FDA-BC53-7EB5C9AD1A10} = {5A24DBFA-C605-72AB-2DAB-0CDF0C553B09}
+		{C12F4581-1215-E9D3-7920-679DE6ABBC05} = {324791A1-5798-203D-0CA6-A8E0DAEC81C8}
+		{61C7AFDF-725C-4833-8332-D812162E64AF} = {C12F4581-1215-E9D3-7920-679DE6ABBC05}
+		{3260BC3A-D039-20BF-4861-22673C64F5D4} = {324791A1-5798-203D-0CA6-A8E0DAEC81C8}
+		{92C8095D-B85D-4C5F-A535-D5837C047EDF} = {3260BC3A-D039-20BF-4861-22673C64F5D4}
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {ED22F9EB-1F92-41E7-962D-E43F82AC6E57}
+	EndGlobalSection
+EndGlobal

+ 0 - 89
Flocking/Main.cs

@@ -1,89 +0,0 @@
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-#if MONOMAC
-using MonoMac.AppKit;
-using MonoMac.Foundation;
-#elif IPHONE
-using MonoTouch.Foundation;
-using MonoTouch.UIKit;
-#endif
-
-namespace Flocking
-{
-#if MONOMAC
-	class Program
-	{
-		static void Main (string[] args)
-		{
-			NSApplication.Init ();
-
-			using (var p = new NSAutoreleasePool ()) {
-				NSApplication.SharedApplication.Delegate = new AppDelegate ();
-
-				// Set our Application Icon
-				NSImage appIcon = NSImage.ImageNamed ("monogameicon.png");
-				NSApplication.SharedApplication.ApplicationIconImage = appIcon;
-				
-				NSApplication.Main (args);
-			}
-		}
-	}
-
-	class AppDelegate : NSApplicationDelegate
-	{
-		private FlockingSample game;
-
-		public override void FinishedLaunching (MonoMac.Foundation.NSObject notification)
-		{
-			game = new FlockingSample();
-			game.Run();
-		}
-
-		public override bool ApplicationShouldTerminateAfterLastWindowClosed (NSApplication sender)
-		{
-			return true;
-		}
-	}
-#elif IPHONE
-	[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");
-		}
-	} 
-#else
-	static class Program
-	{
-		private static FlockingSample game;
-
-		/// <summary>
-		/// The main entry point for the application.
-		/// </summary>
-		[STAThread]
-		static void Main()
-		{
-			game = new FlockingSample();
-			game.Run();
-		}
-	}
-#endif
-}
-
-

二进制
Flocking/Microsoft Permissive License.rtf


+ 34 - 0
Flocking/Platforms/Android/Activity1.cs

@@ -0,0 +1,34 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+using Android.Views;
+using Microsoft.Xna.Framework;
+
+namespace Flocking.Android
+{
+    [Activity(
+        Label = "Flocking",
+        MainLauncher = true,
+        Icon = "@drawable/icon",
+        AlwaysRetainTaskState = true,
+        LaunchMode = LaunchMode.SingleInstance,
+        ScreenOrientation = ScreenOrientation.Landscape,
+        ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.ScreenSize
+    )]
+    public class Activity1 : AndroidGameActivity
+    {
+        private FlockingSample _game;
+        private View _view;
+
+        protected override void OnCreate(Bundle bundle)
+        {
+            base.OnCreate(bundle);
+
+            _game = new FlockingSample();
+            _view = _game.Services.GetService(typeof(View)) as View;
+
+            SetContentView(_view);
+            _game.Run();
+        }
+    }
+}

+ 29 - 0
Flocking/Platforms/Android/AndroidManifest.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
+          android:versionCode="1" 
+          android:versionName="1.0" 
+          package="com.monogame.flocking">
+    
+    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
+    
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    
+    <application android:label="Flocking" 
+                 android:icon="@drawable/icon"
+                 android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+        
+        <activity android:name="Microsoft.Xna.Framework.AndroidGameActivity"
+                  android:label="Flocking"
+                  android:exported="true"
+                  android:launchMode="singleInstance"
+                  android:screenOrientation="landscape"
+                  android:configChanges="orientation|keyboardHidden|keyboard">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+    </application>
+    
+</manifest>

+ 30 - 0
Flocking/Platforms/Android/Flocking.Android.csproj

@@ -0,0 +1,30 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0-android</TargetFramework>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Flocking.Android</RootNamespace>
+    <AssemblyName>Flocking.Android</AssemblyName>
+    <AndroidApplication>true</AndroidApplication>
+    <ApplicationId>com.monogame.flocking</ApplicationId>
+    <AndroidManifest>AndroidManifest.xml</AndroidManifest>
+  </PropertyGroup>
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+    <DefineConstants>DEBUG;TRACE;ANDROID;MOBILE</DefineConstants>
+  </PropertyGroup>
+
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+    <DefineConstants>TRACE;ANDROID;MOBILE</DefineConstants>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\Flocking.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.Android" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <AndroidAsset Include="..\..\Core\Content\**\*.xnb" />
+  </ItemGroup>
+
+</Project>

二进制
Flocking/Platforms/Android/Resources/drawable/icon.png


+ 4 - 0
Flocking/Platforms/Android/Resources/values/strings.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Flocking</string>
+</resources>

+ 21 - 0
Flocking/Platforms/Desktop/Flocking.DesktopGL.csproj

@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>Flocking.DesktopGL</RootNamespace>
+    <AssemblyName>Flocking.DesktopGL</AssemblyName>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\Flocking.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**\*.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
+</Project>

+ 14 - 0
Flocking/Platforms/Desktop/Program.cs

@@ -0,0 +1,14 @@
+using System;
+
+namespace Flocking.DesktopGL
+{
+    public static class Program
+    {
+        [STAThread]
+        static void Main()
+        {
+            using (var game = new FlockingSample())
+                game.Run();
+        }
+    }
+}

+ 0 - 0
Flocking/Info.plist → Flocking/Platforms/Info.plist


+ 22 - 0
Flocking/Platforms/Windows/Flocking.Windows.csproj

@@ -0,0 +1,22 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>net8.0-windows</TargetFramework>
+    <RootNamespace>Flocking.Windows</RootNamespace>
+    <AssemblyName>Flocking.Windows</AssemblyName>
+    <UseAppHost>true</UseAppHost>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\Flocking.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.WindowsDX" Version="3.8.*" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="..\..\Core\Content\**\*.xnb">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
+</Project>

+ 14 - 0
Flocking/Platforms/Windows/Program.cs

@@ -0,0 +1,14 @@
+using System;
+
+namespace Flocking.Windows
+{
+    public static class Program
+    {
+        [STAThread]
+        static void Main()
+        {
+            using (var game = new FlockingSample())
+                game.Run();
+        }
+    }
+}

+ 34 - 0
Flocking/Platforms/iOS/AppDelegate.cs

@@ -0,0 +1,34 @@
+using Foundation;
+using UIKit;
+
+namespace Flocking.iOS
+{
+    [Register("AppDelegate")]
+    public partial class AppDelegate : UIApplicationDelegate
+    {
+        private FlockingSample game;
+
+        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
+        {
+            game = new FlockingSample();
+            game.Run();
+
+            return true;
+        }
+
+        public override void OnActivated(UIApplication application)
+        {
+            // Handle when your app is activated
+        }
+
+        public override void WillEnterForeground(UIApplication application)
+        {
+            // Handle when your app returns to the foreground
+        }
+
+        public override void DidEnterBackground(UIApplication application)
+        {
+            // Handle when your app goes to background
+        }
+    }
+}

+ 16 - 0
Flocking/Platforms/iOS/Flocking.iOS.csproj

@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0-ios</TargetFramework>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Flocking.iOS</RootNamespace>
+    <AssemblyName>Flocking.iOS</AssemblyName>
+    <ApplicationId>com.monogame.flocking</ApplicationId>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\Flocking.Core.csproj" />
+    <PackageReference Include="MonoGame.Framework.iOS" Version="3.8.*" />
+  </ItemGroup>
+
+</Project>

+ 39 - 0
Flocking/Platforms/iOS/Info.plist

@@ -0,0 +1,39 @@
+<?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>CFBundleIdentifier</key>
+    <string>com.monogame.flocking</string>
+    <key>CFBundleShortVersionString</key>
+    <string>1.0</string>
+    <key>CFBundleVersion</key>
+    <string>1.0</string>
+    <key>LSRequiresIPhoneOS</key>
+    <true/>
+    <key>MinimumOSVersion</key>
+    <string>11.0</string>
+    <key>UIDeviceFamily</key>
+    <array>
+        <integer>1</integer>
+        <integer>2</integer>
+    </array>
+    <key>UIRequiredDeviceCapabilities</key>
+    <array>
+        <string>armv7</string>
+    </array>
+    <key>UISupportedInterfaceOrientations</key>
+    <array>
+        <string>UIInterfaceOrientationLandscapeLeft</string>
+        <string>UIInterfaceOrientationLandscapeRight</string>
+    </array>
+    <key>UISupportedInterfaceOrientations~ipad</key>
+    <array>
+        <string>UIInterfaceOrientationLandscapeLeft</string>
+        <string>UIInterfaceOrientationLandscapeRight</string>
+    </array>
+    <key>UIStatusBarHidden</key>
+    <true/>
+</dict>
+</plist>

+ 15 - 0
Flocking/Platforms/iOS/Program.cs

@@ -0,0 +1,15 @@
+using UIKit;
+
+namespace Flocking.iOS
+{
+    public class Application
+    {
+        // This is the main entry point of the application.
+        static void Main(string[] args)
+        {
+            // if you want to use a different Application Delegate class from "AppDelegate"
+            // you can specify it here.
+            UIApplication.Main(args, null, typeof(AppDelegate));
+        }
+    }
+}

+ 0 - 32
Flocking/Program.cs

@@ -1,32 +0,0 @@
-#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
-}
-

+ 0 - 6
Flocking/Properties/AppManifest.xml

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

+ 0 - 34
Flocking/Properties/AssemblyInfo.cs

@@ -1,34 +0,0 @@
-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")]

+ 0 - 30
Flocking/Properties/WMAppManifest.xml

@@ -1,30 +0,0 @@
-<?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>
-

+ 72 - 0
Flocking/README.md

@@ -0,0 +1,72 @@
+# Flocking Sample
+
+This sample demonstrates how AIs can use simple rules to move together and create complex behaviors.
+
+## Sample Overview
+
+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.
+
+## Building and Running
+
+This project supports the following platforms:
+
+- **Windows** (`Platforms/Windows`)
+- **DesktopGL** (`Platforms/Desktop`)
+- **Android** (`Platforms/Android`)
+- **iOS** (`Platforms/iOS`)
+
+### Prerequisites
+
+- [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
+- [MonoGame 3.8.*](https://www.monogame.net/)
+- For Android/iOS: Visual Studio 2022+ with Xamarin/MAUI workloads, or JetBrains Rider
+
+### Build and Run (VS Code)
+
+1. Open the root folder in VS Code.
+2. Use the built-in tasks (Ctrl+Shift+B or `Terminal > Run Task...`) to build or run:
+   - `build-windows`, `run-windows`
+   - `build-desktopgl`, `run-desktopgl`
+   - `build-android`, `run-android`
+   - `build-ios`
+3. Use the launch configurations in `.vscode/launch.json` to debug Windows or DesktopGL.
+
+### Build and Run (Visual Studio)
+
+1. Open `Flocking.sln` in Visual Studio.
+2. Set the desired platform project as the startup project.
+3. Build and run as usual.
+
+#### Notes
+- Android and iOS require appropriate emulators or devices and platform SDKs.
+- Content is pre-built as `.xnb` files and does not require a content pipeline build step.
+
+### Controls
+
+| Action                                 | Windows Phone                        | Windows - Keyboard Control | Windows/Xbox - Gamepad Control         |
+|----------------------------------------|--------------------------------------|---------------------------|----------------------------------------|
+| Select the tuning parameter.           | **DRAG** tuning bar                  | UP ARROW, DOWN ARROW      | D-Pad Up and Down                      |
+| Increase/decrease the tuning parameter.| **DRAG** tuning bar                  | LEFT ARROW, RIGHT ARROW   | D-Pad Left and Right, Left/Right Triggers |
+| Reset the bird flock.                  | **TAP** "Reset Flock" button         | X                        | X                                      |
+| Reset the tuning parameters.           | **TAP** "Reset Distance" button      | B                        | B                                      |
+| Add/remove the cat                     | **TAP** "Add/Remove Cat" button      | Y                        | Y                                      |
+| Move the cat.                          | **TAP** or **DRAG** on screen        | W, S, A, D                | Left Thumbstick                        |
+| Exit the game.                         | **BACK**                             | ESC or ALT+F4             | **BACK**                               |
+
+## How the Sample Works
+
+### Flocking Behavior
+
+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.
+
+- **Cohesion**: Each bird flies towards others it can see. For each other bird inside its `detectionDist` value, the bird changes its `direction` towards the other bird in proportion to its `moveInFlockDirInfluence` setting and according to how close it is to the midpoint between its `detectionDist` and `separationDist` values.
+
+- **Alignment**: Each bird flies in the general direction of others it can see. For each other bird inside its `detectionDist` value, the bird adds the `direction` the other bird is facing to its own `direction` in proportion to its `moveInFlockDirInfluence` setting.
+
+- **Separation**: Each bird flies away from others that are too close. For each other bird inside both its `detectionDist` *and* its `separationDist` 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's direction to its `direction` in proportion to its `moveInFlockDirInfluence` setting and according to the ratio of how close the other bird is relative to its `separationDist` value.
+
+- **Flee**: Each bird flies away from the cat if the bird can see the cat. If the cat is inside the bird's `detectionDist` and the bird isn't already moving away from the cat, the bird adds the opposite of the direction towards the cat to its `direction` value.

+ 0 - 10
Flocking/app.xml

@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<application project_name="*" version="1.00" default_locale="en-US">
-	<runtime_config>
-		<memory managed_heap_size="32768" resource_heap_size="65536" />
-	</runtime_config>
-	<feature_list>
-		<feature value="GamePad" />
-		<feature value="Touch" />
-	</feature_list>
-</application>