]> Dogcows Code - chaz/carfire/blobdiff - CarFire/CarFire/CarFire/SaberMonster2.cs
Adding AI to monsters. AI still has some bugs to be worked out. Put it should compile...
[chaz/carfire] / CarFire / CarFire / CarFire / SaberMonster2.cs
diff --git a/CarFire/CarFire/CarFire/SaberMonster2.cs b/CarFire/CarFire/CarFire/SaberMonster2.cs
new file mode 100644 (file)
index 0000000..f522ab4
--- /dev/null
@@ -0,0 +1,305 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using Microsoft.Xna.Framework;\r
+using Microsoft.Xna.Framework.Content;\r
+using Microsoft.Xna.Framework.Graphics;\r
+\r
+namespace CarFire\r
+{\r
+    /// <summary>\r
+    /// A type for the states of an artificually intelligent entity.\r
+    /// </summary>\r
+    public enum AiState\r
+    {\r
+        Standing,\r
+        Pacing,\r
+        Chasing,\r
+        Dazed,\r
+        Fighting,\r
+        Retreating\r
+    }\r
+\r
+\r
+    /// <summary>\r
+    /// An example monster.  This can serve as a starting place for\r
+    /// creating other monsters.  This one just follows a path.\r
+    /// </summary>\r
+    public class SaberMonster2 : IMonster\r
+    {\r
+        //starting health\r
+        int health = 100;\r
+        /// <summary>\r
+        /// Construct this type of monster.  This constructor is called\r
+        /// by the map when the game requests entities.\r
+        /// </summary>\r
+        /// <param name="identifier">The single character ID.</param>\r
+        /// <param name="position">The initial position on the map.</param>\r
+        /// <param name="info">More parameters.</param>\r
+        /// <param name="game">The game object reference.</param>\r
+        public SaberMonster2(char identifier, Point position, Dictionary<string, string> info, Game game)\r
+        {\r
+            mId = identifier;\r
+            mMotion = new MovementManager(position);\r
+\r
+            // We need to keep the game reference in order to get the grid when we\r
+            // need to find paths.\r
+            mGame = game;\r
+\r
+            pathFinder = null;\r
+\r
+            // Get the speed of the monster.  If not set in the map, it defaults to\r
+            // whatever the default of MovementManager is... 1 I think.\r
+            string speedString;\r
+            if (info.TryGetValue("speed", out speedString))\r
+            {\r
+                int? speed = Parse.Integer(speedString);\r
+                if (speed != null) mMotion.Speed = speed.Value;\r
+            }\r
+\r
+            // Get the "idle path" coordinates loaded from the map.\r
+            string idlePath;\r
+            if (info.TryGetValue("path", out idlePath))\r
+            {\r
+                string[] idlePathPoints = Parse.List(idlePath);\r
+                foreach (string pathPoint in idlePathPoints)\r
+                {\r
+                    Point? point = Parse.Coordinates(pathPoint);\r
+                    if (point != null) mIdlePath.Add(point.Value);\r
+                }\r
+            }\r
+            // Start doing something...\r
+            //StartPacing();\r
+        }\r
+\r
+        public void DefaultAction()\r
+        {\r
+            mState = AiState.Standing;\r
+        }\r
+\r
+        public void Chasing(Point Chase)\r
+        {\r
+            Chasing(Chase.X, Chase.Y);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Call this to switch the monster AI state to Chasing and set up\r
+        /// the initial paths.  A path to .\r
+        /// </summary>\r
+        public void Chasing(int X, int Y)\r
+        {\r
+            mState = AiState.Chasing;\r
+\r
+            // Determine the best (closest) waypoint to start at.\r
+            // We may not be on the path, so we have to walk to get on it.\r
+            /*\r
+            mIdlePathIndex = 0;\r
+            int closest = int.MaxValue;\r
+            for (int i = 0; i < mIdlePath.Count; i++)\r
+            {\r
+                int distance = PathFinder.GetManhattanDistance(Coordinates, mIdlePath[i]);\r
+                if (distance < closest)\r
+                {\r
+                    mIdlePathIndex = i;\r
+                    closest = distance;\r
+                }\r
+            }\r
+             */\r
+\r
+            // Find the path to get to the closest waypoint.\r
+            if (pathFinder == null)\r
+                pathFinder = new PathFinder(mGame.Grid);\r
+\r
+            mPath = new List<Point>(32);\r
+            mPath.Add(Coordinates);\r
+            List<Point> path = pathFinder.GetPath(mMotion.Coordinates, new Point(X,Y));\r
+            if (path != null)\r
+            {\r
+                mPath.AddRange(path);\r
+                //mPath.Add(mIdlePath[mIdlePathIndex]);\r
+            }\r
+            mPathIndex = 0;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Call this to switch the monster AI state to pacing and set up\r
+        /// the initial paths.  The monster will start following the path it\r
+        /// was defined with in the map file.\r
+        /// </summary>\r
+        public void StartPacing()\r
+        {\r
+            mState = AiState.Pacing;\r
+\r
+            if (mIdlePath.Count == 0) return;\r
+\r
+            // Determine the best (closest) waypoint to start at.\r
+            // We may not be on the path, so we have to walk to get on it.\r
+            mIdlePathIndex = 0;\r
+            int closest = int.MaxValue;\r
+            for (int i = 0; i < mIdlePath.Count; i++)\r
+            {\r
+                int distance = PathFinder.GetManhattanDistance(Coordinates, mIdlePath[i]);\r
+                if (distance < closest)\r
+                {\r
+                    mIdlePathIndex = i;\r
+                    closest = distance;\r
+                }\r
+            }\r
+\r
+            // Find the path to get to the closest waypoint.\r
+            PathFinder pathFinder = new PathFinder(mGame.Grid);\r
+            mPath = new List<Point>(32);\r
+            mPath.Add(Coordinates);\r
+            List<Point> path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex]);\r
+            if (path != null)\r
+            {\r
+                mPath.AddRange(path);\r
+                mPath.Add(mIdlePath[mIdlePathIndex]);\r
+            }\r
+            mPathIndex = 0;\r
+        }\r
+\r
+        Direction GetDirectionToNextCell()\r
+        {\r
+            if (mPathIndex >= mPath.Count)\r
+            {\r
+                mState = AiState.Standing;\r
+            }\r
+\r
+            // We need to make sure out direction is set to the next cell\r
+            // we want to be.  If our current coordinates match that, we need\r
+            // to change our direction to get to the next cell.\r
+            if (mPath[mPathIndex % mPath.Count] == mMotion.Coordinates)\r
+            {\r
+                mPathIndex++;\r
+                mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex % mPath.Count]);\r
+            }\r
+\r
+            return mPathDirection;\r
+        }\r
+\r
+\r
+        #region IMonster Members\r
+\r
+        /// <summary>\r
+        /// I don't know what this is for.\r
+        /// </summary>\r
+        public bool visible\r
+        {\r
+            get { throw new NotImplementedException(); }\r
+        }\r
+\r
+        #endregion\r
+\r
+\r
+        #region ICharacter Members\r
+\r
+        /// <summary>\r
+        /// Load the monster's content.  This is called by the map when\r
+        /// the game requests the entities.\r
+        /// </summary>\r
+        /// <param name="contentManager">The zaphnod.</param>\r
+        public void LoadContent(ContentManager contentManager)\r
+        {\r
+            mTexture = contentManager.Load<Texture2D>("menuItem");\r
+        }\r
+\r
+        /// <summary>\r
+        /// Update the monster's state.  This should be called by the game\r
+        /// every "frame" (whenever the game is updating its state).  In this\r
+        /// simple monster, all we need to do is update the motion manager.\r
+        /// </summary>\r
+        /// <param name="timeSpan"></param>\r
+        public void Update(TimeSpan timeSpan)\r
+        {\r
+            switch (mState)\r
+            {\r
+                case AiState.Pacing:\r
+                case AiState.Chasing:\r
+                    mMotion.Update(timeSpan, GetDirectionToNextCell());\r
+                    break;\r
+                case AiState.Standing:\r
+                case AiState.Dazed:\r
+                case AiState.Fighting:\r
+                case AiState.Retreating:\r
+                    break;\r
+                    \r
+            }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Draw the monster.  We just ask the map for our screen position,\r
+        /// passing it the position which the motion manager keeps track of.\r
+        /// </summary>\r
+        /// <param name="spriteBatch">The </param>\r
+        public void Draw(SpriteBatch spriteBatch)\r
+        {\r
+            Rectangle position = mGame.State.Map.GetRectangleFromCoordinates(mMotion.Position);\r
+            spriteBatch.Draw(mTexture, position, Color.White);\r
+        }\r
+\r
+        /// <summary>\r
+        /// A monster should keep track of its health.  This one doesn't.\r
+        /// </summary>\r
+        public int Health\r
+        {\r
+            get { return this.health; }\r
+            \r
+        }\r
+\r
+        /// <summary>\r
+        /// This monster is invincible.\r
+        /// </summary>\r
+        /// <param name="amount"></param>\r
+        public void causeDamageTo(int amount)\r
+        {\r
+            this.health -= amount;\r
+        }\r
+\r
+        public bool IsCollidable { get { return true; } }\r
+\r
+        /// <summary>\r
+        /// Get the smoothed position.\r
+        /// </summary>\r
+        public Vector2 Position { get { return mMotion.Position; } }\r
+\r
+        /// <summary>\r
+        /// Get the grid coordinates.\r
+        /// </summary>\r
+        public Point Coordinates {\r
+            get { return mMotion.Coordinates; }\r
+            set { mMotion = new MovementManager(value, mMotion.Speed); }\r
+        }\r
+\r
+        /// <summary>\r
+        /// Get the entity identifier.\r
+        /// </summary>\r
+        public char Identifier { get { return mId; } }\r
+\r
+        #endregion\r
+\r
+\r
+        #region Private Variables\r
+\r
+        Game mGame;\r
+\r
+        char mId;\r
+        MovementManager mMotion;\r
+\r
+        PathFinder pathFinder;\r
+        List<Point> mIdlePath = new List<Point>();      // List of waypoints that we got from the map.\r
+        int mIdlePathIndex;                             // Index to the waypoint we're heading for.\r
+\r
+        List<Point> mPath;              // List of cells in the path between the position between where\r
+                                        // we started and the waypoint we're heading for.\r
+        int mPathIndex;                 // Index to the cell we're heading for.\r
+        Direction mPathDirection;       // The direction between our current position and the place we're going.\r
+\r
+        AiState mState;                 // What is the monster doing?\r
+\r
+        Texture2D mTexture;             // Obvious.\r
+\r
+        #endregion\r
+    }\r
+}\r
This page took 0.024836 seconds and 4 git commands to generate.