]> Dogcows Code - chaz/carfire/blob - CarFire/CarFire/CarFire/SaberMonster.cs
91d82a093f495a666c07f9aa65c71f8dc3154fcc
[chaz/carfire] / CarFire / CarFire / CarFire / SaberMonster.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 SaberMonster : IMonster
30 {
31 /// <summary>
32 /// Construct this type of monster. This constructor is called
33 /// by the map when the game requests entities.
34 /// </summary>
35 /// <param name="identifier">The single character ID.</param>
36 /// <param name="position">The initial position on the map.</param>
37 /// <param name="info">More parameters.</param>
38 /// <param name="game">The game object reference.</param>
39 public SaberMonster(char identifier, Point position, Dictionary<string, string> info, Game game)
40 {
41 mId = identifier;
42 mMotion = new MovementManager(position);
43
44 // We need to keep the game reference in order to get the grid when we
45 // need to find paths.
46 mGame = game;
47
48 // Get the speed of the monster. If not set in the map, it defaults to
49 // whatever the default of MovementManager is... 1 I think.
50 string speedString;
51 if (info.TryGetValue("speed", out speedString))
52 {
53 int? speed = Parse.Integer(speedString);
54 if (speed != null) mMotion.Speed = speed.Value;
55 }
56
57 // Get the "idle path" coordinates loaded from the map.
58 string idlePath;
59 if (info.TryGetValue("path", out idlePath))
60 {
61 string[] idlePathPoints = Parse.List(idlePath);
62 foreach (string pathPoint in idlePathPoints)
63 {
64 Point? point = Parse.Coordinates(pathPoint);
65 if (point != null) mIdlePath.Add(point.Value);
66 }
67 }
68
69 // Start doing something...
70 StartPacing();
71 }
72
73
74 /// <summary>
75 /// Call this to switch the monster AI state to pacing and set up
76 /// the initial paths. The monster will start following the path it
77 /// was defined with in the map file.
78 /// </summary>
79 public void StartPacing()
80 {
81 mState = AiState.Pacing;
82
83 if (mIdlePath.Count == 0) return;
84
85 // Determine the best (closest) waypoint to start at.
86 // We may not be on the path, so we have to walk to get on it.
87 mIdlePathIndex = 0;
88 int closest = int.MaxValue;
89 for (int i = 0; i < mIdlePath.Count; i++)
90 {
91 int distance = PathFinder.GetManhattanDistance(Coordinates, mIdlePath[i]);
92 if (distance < closest)
93 {
94 mIdlePathIndex = i;
95 closest = distance;
96 }
97 }
98
99 // Find the path to get to the closest waypoint.
100 PathFinder pathFinder = new PathFinder(mGame.Grid);
101 mPath = new List<Point>(32);
102 mPath.Add(Coordinates);
103 List<Point> path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex]);
104 if (path != null)
105 {
106 mPath.AddRange(path);
107 mPath.Add(mIdlePath[mIdlePathIndex]);
108 }
109 mPathIndex = 0;
110 }
111
112 Direction GetDirectionToNextCell()
113 {
114 if (mPathIndex >= mPath.Count)
115 {
116 // We're done with the current path, so find the path to
117 // the next waypoint... forever.
118 mIdlePathIndex++;
119 PathFinder pathFinder = new PathFinder(mGame.Grid);
120 mPath = new List<Point>(32);
121 mPath.Add(Coordinates);
122 List<Point> path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex % mIdlePath.Count]);
123 if (path != null)
124 {
125 mPath.AddRange(path);
126 mPath.Add(mIdlePath[mIdlePathIndex % mIdlePath.Count]);
127 }
128 mPathIndex = 0;
129 }
130
131 // We need to make sure out direction is set to the next cell
132 // we want to be. If our current coordinates match that, we need
133 // to change our direction to get to the next cell.
134 if (mPath[mPathIndex % mPath.Count] == mMotion.Coordinates)
135 {
136 mPathIndex++;
137 mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex % mPath.Count]);
138 }
139
140 return mPathDirection;
141 }
142
143
144 #region IMonster Members
145
146 /// <summary>
147 /// I don't know what this is for.
148 /// </summary>
149 public bool visible
150 {
151 get { throw new NotImplementedException(); }
152 }
153
154 #endregion
155
156
157 #region ICharacter Members
158
159 /// <summary>
160 /// Load the monster's content. This is called by the map when
161 /// the game requests the entities.
162 /// </summary>
163 /// <param name="contentManager">The zaphnod.</param>
164 public void LoadContent(ContentManager contentManager)
165 {
166 mTexture = contentManager.Load<Texture2D>("menuItem");
167 }
168
169 /// <summary>
170 /// Update the monster's state. This should be called by the game
171 /// every "frame" (whenever the game is updating its state). In this
172 /// simple monster, all we need to do is update the motion manager.
173 /// </summary>
174 /// <param name="timeSpan"></param>
175 public void Update(TimeSpan timeSpan)
176 {
177 if (mState == AiState.Pacing)
178 {
179 mMotion.Update(timeSpan, GetDirectionToNextCell());
180 }
181 }
182
183 /// <summary>
184 /// Draw the monster. We just ask the map for our screen position,
185 /// passing it the position which the motion manager keeps track of.
186 /// </summary>
187 /// <param name="spriteBatch">The </param>
188 public void Draw(SpriteBatch spriteBatch)
189 {
190 Rectangle position = mGame.State.Map.GetRectangleFromCoordinates(mMotion.Position);
191 spriteBatch.Draw(mTexture, position, Color.White);
192 }
193
194 /// <summary>
195 /// A monster should keep track of its health. This one doesn't.
196 /// </summary>
197 public int Health
198 {
199 //TODO do this right
200 get { return 0; }
201 //get { throw new NotImplementedException(); }
202 }
203
204 /// <summary>
205 /// This monster is invincible.
206 /// </summary>
207 /// <param name="amount"></param>
208 public void causeDamageTo(int amount)
209 {
210 //TODO do this right
211 //throw new NotImplementedException();
212 }
213
214 /// <summary>
215 /// Get the smoothed position.
216 /// </summary>
217 public Vector2 Position { get { return mMotion.Position; } }
218
219 /// <summary>
220 /// Get the grid coordinates.
221 /// </summary>
222 public Point Coordinates { get { return mMotion.Coordinates; } }
223
224 #endregion
225
226
227 #region Private Variables
228
229 Game mGame;
230
231 char mId;
232 MovementManager mMotion;
233
234 List<Point> mIdlePath = new List<Point>(); // List of waypoints that we got from the map.
235 int mIdlePathIndex; // Index to the waypoint we're heading for.
236
237 List<Point> mPath; // List of cells in the path between the position between where
238 // we started and the waypoint we're heading for.
239 int mPathIndex; // Index to the cell we're heading for.
240 Direction mPathDirection; // The direction between our current position and the place we're going.
241
242 AiState mState; // What is the monster doing?
243
244 Texture2D mTexture; // Obvious.
245
246 #endregion
247 }
248 }
This page took 0.042277 seconds and 3 git commands to generate.