Changed where AI is stored, adjusted to work with Multiplayer
[chaz/carfire] / CarFire / CarFire / CarFire / SaberMonster2.cs
1 ´╗┐using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using Microsoft.Xna.Framework;
6 using Microsoft.Xna.Framework.Content;
7 using Microsoft.Xna.Framework.Graphics;
8
9 namespace CarFire
10 {
11 /// <summary>
12 /// A type for the states of an artificually intelligent entity.
13 /// </summary>
14 public enum AiState
15 {
16 Standing,
17 Pacing,
18 Chasing,
19 Dazed,
20 Fighting,
21 Retreating
22 }
23
24
25 /// <summary>
26 /// An example monster. This can serve as a starting place for
27 /// creating other monsters. This one just follows a path.
28 /// </summary>
29 public class SaberMonster2 : IMonster
30 {
31 //starting health
32 int health = 100;
33 /// <summary>
34 /// Construct this type of monster. This constructor is called
35 /// by the map when the game requests entities.
36 /// </summary>
37 /// <param name="identifier">The single character ID.</param>
38 /// <param name="position">The initial position on the map.</param>
39 /// <param name="info">More parameters.</param>
40 /// <param name="game">The game object reference.</param>
41 public SaberMonster2(char identifier, Point position, Dictionary<string, string> info, Game game)
42 {
43 mId = identifier;
44 mMotion = new MovementManager(position);
45
46 // We need to keep the game reference in order to get the grid when we
47 // need to find paths.
48 mGame = game;
49
50 pathFinder = null;
51
52 // Get the speed of the monster. If not set in the map, it defaults to
53 // whatever the default of MovementManager is... 1 I think.
54 string speedString;
55 if (info.TryGetValue("speed", out speedString))
56 {
57 int? speed = Parse.Integer(speedString);
58 if (speed != null) mMotion.Speed = speed.Value;
59 }
60
61 // Get the "idle path" coordinates loaded from the map.
62 string idlePath;
63 if (info.TryGetValue("path", out idlePath))
64 {
65 string[] idlePathPoints = Parse.List(idlePath);
66 foreach (string pathPoint in idlePathPoints)
67 {
68 Point? point = Parse.Coordinates(pathPoint);
69 if (point != null) mIdlePath.Add(point.Value);
70 }
71 }
72 // Start doing something...
73 //StartPacing();
74 }
75
76 public void DefaultAction()
77 {
78 mState = AiState.Standing;
79 }
80
81 public void Chasing(Point Chase)
82 {
83 Chasing(Chase.X, Chase.Y);
84 }
85
86 /// <summary>
87 /// Call this to switch the monster AI state to Chasing and set up
88 /// the initial paths. A path to .
89 /// </summary>
90 public void Chasing(int X, int Y)
91 {
92 mState = AiState.Chasing;
93
94 // Determine the best (closest) waypoint to start at.
95 // We may not be on the path, so we have to walk to get on it.
96 /*
97 mIdlePathIndex = 0;
98 int closest = int.MaxValue;
99 for (int i = 0; i < mIdlePath.Count; i++)
100 {
101 int distance = PathFinder.GetManhattanDistance(Coordinates, mIdlePath[i]);
102 if (distance < closest)
103 {
104 mIdlePathIndex = i;
105 closest = distance;
106 }
107 }
108 */
109
110 // Find the path to get to the closest waypoint.
111 if (pathFinder == null)
112 pathFinder = new PathFinder(mGame.Grid);
113
114 mPath = new List<Point>(32);
115 mPath.Add(Coordinates);
116 List<Point> path = pathFinder.GetPath(mMotion.Coordinates, new Point(X,Y));
117 if (path != null)
118 {
119 mPath.AddRange(path);
120 //mPath.Add(mIdlePath[mIdlePathIndex]);
121 }
122 mPathIndex = 0;
123 }
124
125 /// <summary>
126 /// Call this to switch the monster AI state to pacing and set up
127 /// the initial paths. The monster will start following the path it
128 /// was defined with in the map file.
129 /// </summary>
130 public void StartPacing()
131 {
132 mState = AiState.Pacing;
133
134 if (mIdlePath.Count == 0) return;
135
136 // Determine the best (closest) waypoint to start at.
137 // We may not be on the path, so we have to walk to get on it.
138 mIdlePathIndex = 0;
139 int closest = int.MaxValue;
140 for (int i = 0; i < mIdlePath.Count; i++)
141 {
142 int distance = PathFinder.GetManhattanDistance(Coordinates, mIdlePath[i]);
143 if (distance < closest)
144 {
145 mIdlePathIndex = i;
146 closest = distance;
147 }
148 }
149
150 // Find the path to get to the closest waypoint.
151 PathFinder pathFinder = new PathFinder(mGame.Grid);
152 mPath = new List<Point>(32);
153 mPath.Add(Coordinates);
154 List<Point> path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex]);
155 if (path != null)
156 {
157 mPath.AddRange(path);
158 mPath.Add(mIdlePath[mIdlePathIndex]);
159 }
160 mPathIndex = 0;
161 }
162
163 Direction GetDirectionToNextCell()
164 {
165 if (mPathIndex >= mPath.Count)
166 {
167 mState = AiState.Standing;
168 }
169
170 // We need to make sure out direction is set to the next cell
171 // we want to be. If our current coordinates match that, we need
172 // to change our direction to get to the next cell.
173 if (mPath[mPathIndex % mPath.Count] == mMotion.Coordinates)
174 {
175 mPathIndex++;
176 mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex % mPath.Count]);
177 }
178
179 return mPathDirection;
180 }
181
182
183 #region IMonster Members
184
185 /// <summary>
186 /// I don't know what this is for.
187 /// </summary>
188 public bool visible
189 {
190 get { throw new NotImplementedException(); }
191 }
192
193 #endregion
194
195
196 #region ICharacter Members
197
198 /// <summary>
199 /// Load the monster's content. This is called by the map when
200 /// the game requests the entities.
201 /// </summary>
202 /// <param name="contentManager">The zaphnod.</param>
203 public void LoadContent(ContentManager contentManager)
204 {
205 mTexture = contentManager.Load<Texture2D>("menuItem");
206 }
207
208 /// <summary>
209 /// Update the monster's state. This should be called by the game
210 /// every "frame" (whenever the game is updating its state). In this
211 /// simple monster, all we need to do is update the motion manager.
212 /// </summary>
213 /// <param name="timeSpan"></param>
214 public void Update(TimeSpan timeSpan)
215 {
216 int closestChar = 0;
217 int closestCharDist = 1000;
218 for (int c = 0; c < mGame.State.mCharacters.Length; c++)
219 {
220 if (mGame.State.mCharacters[c] != null && mGame.AIData.spaceVisible(Coordinates, mGame.State.mCharacters[c].Coordinates))
221 {
222 if (PathFinder.GetManhattanDistance(Coordinates, mGame.State.mCharacters[c].Coordinates) < closestCharDist)
223 {
224 closestCharDist = PathFinder.GetManhattanDistance(Coordinates, mGame.State.mCharacters[c].Coordinates);
225 closestChar = c;
226 }
227 }
228 }
229
230 if (mGame.State.mCharacters[closestChar] != null && mGame.AIData.spaceVisible(Coordinates, mGame.State.mCharacters[closestChar].Coordinates))
231 {
232 Chasing(mGame.State.mCharacters[0].Coordinates);
233 }
234 else
235 {
236 DefaultAction();
237 }
238
239 switch (mState)
240 {
241 case AiState.Pacing:
242 case AiState.Chasing:
243 mMotion.Update(timeSpan, GetDirectionToNextCell());
244 break;
245 case AiState.Standing:
246 case AiState.Dazed:
247 case AiState.Fighting:
248 case AiState.Retreating:
249 break;
250
251 }
252 }
253
254 /// <summary>
255 /// Draw the monster. We just ask the map for our screen position,
256 /// passing it the position which the motion manager keeps track of.
257 /// </summary>
258 /// <param name="spriteBatch">The </param>
259 public void Draw(SpriteBatch spriteBatch)
260 {
261 Rectangle position = mGame.State.Map.GetRectangleFromCoordinates(mMotion.Position);
262 spriteBatch.Draw(mTexture, position, Color.White);
263 }
264
265 /// <summary>
266 /// A monster should keep track of its health. This one doesn't.
267 /// </summary>
268 public int Health
269 {
270 get { return this.health; }
271
272 }
273
274 /// <summary>
275 /// This monster is invincible.
276 /// </summary>
277 /// <param name="amount"></param>
278 public void causeDamageTo(int amount)
279 {
280 this.health -= amount;
281 }
282
283 public bool IsCollidable { get { return true; } }
284
285 /// <summary>
286 /// Get the smoothed position.
287 /// </summary>
288 public Vector2 Position { get { return mMotion.Position; } }
289
290 /// <summary>
291 /// Get the grid coordinates.
292 /// </summary>
293 public Point Coordinates {
294 get { return mMotion.Coordinates; }
295 set { mMotion = new MovementManager(value, mMotion.Speed); }
296 }
297
298 /// <summary>
299 /// Get the entity identifier.
300 /// </summary>
301 public char Identifier { get { return mId; } }
302
303 #endregion
304
305
306 #region Private Variables
307
308 Game mGame;
309
310 char mId;
311 MovementManager mMotion;
312 AI mAI;
313 PathFinder pathFinder;
314 List<Point> mIdlePath = new List<Point>(); // List of waypoints that we got from the map.
315 int mIdlePathIndex; // Index to the waypoint we're heading for.
316
317 List<Point> mPath; // List of cells in the path between the position between where
318 // we started and the waypoint we're heading for.
319 int mPathIndex; // Index to the cell we're heading for.
320 Direction mPathDirection; // The direction between our current position and the place we're going.
321
322 AiState mState; // What is the monster doing?
323
324 Texture2D mTexture; // Obvious.
325
326 #endregion
327 }
328 }
This page took 0.05943 seconds and 4 git commands to generate.