tileset = FuturisticBuilding\r
numplayers = <1,4>\r
\r
+[a]\r
+ type = SaberMonster\r
+ path = [5,5] [7,3] [25,30]\r
+ speed = 7\r
+ create = [20,20] [31,31] [2,34] [22,4] [5,7] [18,18] [34,34] [4,20] [37,4] [6,37] [21,21] [21,30] [35,20]\r
+\r
+[b]\r
+ type = SaberMonster\r
+ path = [0,0] [40,0] [40,40] [0,40]\r
+ speed = 23\r
+ create = [0,4] [4,0]\r
+\r
+[e]\r
+ type = SaberMonster\r
+ path = [0,0] [40,0] [40,40] [0,40]\r
+ speed = 16\r
+ create = [40,4]\r
+\r
+[c]\r
+ type = SaberMonster\r
+ path = [5,7] [18,18] [34,34] [4,20] [37,4] [6,37] [21,21] [21,30] [35,20]\r
+ speed = 5\r
+ create = [2,2] [20,20] [5,35] [21,34] [34,37] [37,15] [31,31] [2,34] [22,4]\r
+\r
+[d]\r
+ type = SaberMonster\r
+ path = [2,6] [6,6]\r
+\r
[maptable]\r
\r
+-------------------------------------+ \r
- | /\ | \r
- | 1 / \ 2 | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \ | \r
- | / \| \r
- |/ /| \r
- |\ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | \ / | \r
- | 4 \ / 3 | \r
- | \/ | \r
+ |""" __ """| \r
+ |"1" _ _ "2"| \r
+ |""" _ _ """| \r
+ | """"""""" _ _ " | \r
+ |d " _ " | \r
+ | " _ " | \r
+ | " _ " | \r
+ | _ " _ " | \r
+ | _ " _ " | \r
+ | _ " _ " | \r
+ | _ " " | \r
+ | _ " " | \r
+ | _ " " | \r
+ | _ " " _ | \r
+ | _ " " _ | \r
+ | _ " " _ | \r
+ | _ "" _ | \r
+ | _ " _| \r
+ |_ " _| \r
+ |_ " _ | \r
+ | _ "" _ | \r
+ | _ " " _ | \r
+ | """"""""""""""" " _ | \r
+ | " " _ | \r
+ | " " _ | \r
+ | " _ " | \r
+ | " _ " | \r
+ | " _ " | \r
+ | " _ _ " | \r
+ | " _ _ " | \r
+ | " _ _ " | \r
+ | " _ _ " | \r
+ | " _ _ " | \r
+ | " _ _ " | \r
+ |""" _ _ """| \r
+ |"4" _ _ "3"| \r
+ |""" __ """| \r
+-------------------------------------+ \r
\r
; vi:ft=dosini\r
options = Once\r
\r
[maptable]\r
-+------------------------------------------------------------------------------+\r
-| |\r
-| 1 2 |\r
-| ... |\r
-| 3 4 .L. +---- |\r
-| ... | M |\r
-| k | |\r
+`~~*!@@)#@`(~#!=@`#=`~~*!@@)#@`(~#!=@`#@`~~#!@@`#@`~~#!@@`#@`~~#!@@`#@`~~#!@@`#@\r
+$ ? ? ? ? ? ? ? ? ? ? |\r
+$ 1 2 |\r
+$ |\r
+$ 3 4 +---- |\r
+$ | |\r
+`~~*!@@)#@`(~#!=@`#| |\r
| |------------------------------------------ |\r
| | | |\r
| | | |\r
+-------------+----+ | \ / |\r
| | | \ / |\r
-| M | | \ / |\r
+| | | \ / |\r
| | | \ / |\r
| | \ @ # $ % ^ & * ( ) | | |\r
| +-------+ | / \ |\r
| | / \ |\r
| / \ |\r
| / \ |\r
-| |\r
-+------------------------------------------------------------------------------+\r
+:;::'""..<> |\r
+=(&**(&(&&*&(*((((&&*&(*&*&(&(*&**&*&(&(*&*&*&*&(*&(&**&*(&(&(&*&*&*&&*(*((*&*((\r
\r
; vi:ft=dosini\r
{\r
get\r
{\r
- bool[,] grid = State.Map.Grid;\r
+ bool[,] grid = (bool[,])State.Map.Grid.Clone();\r
foreach (IEntity entity in State.Entities)\r
{\r
Point coordinates = entity.Coordinates;\r
- if (State.Map.IsCellOpen(coordinates)) grid[coordinates.X, coordinates.Y] = false;\r
+ grid[coordinates.X, coordinates.Y] = false;\r
+ }\r
+ foreach (Player player in State.mCharacters)\r
+ {\r
+ if (player == null) continue;\r
+ Point coordinates = player.Coordinates;\r
+ grid[coordinates.X, coordinates.Y] = false;\r
}\r
return grid;\r
}\r
if (!State.Map.IsCellOpen(point)) return false;\r
IEntity entity = GetEntityAtCoordinates(point);\r
if (entity != null && entity.IsCollidable) return false;\r
+ Player player = GetPlayerAtCoordinates(point);\r
+ if (player != null) return false;\r
return true;\r
}\r
\r
// Load the tilemap.\r
Texture2D mapTiles = mContentManager.Load<Texture2D>("graphics/wallAndFloorTilesNoEdgeScale");\r
Tilemap tilemap = new Tilemap(mapTiles, 10, 7);\r
- tilemap.SetTile(' ', new Point(4, 5), TileFlags.Default);\r
- tilemap.SetTile('`', new Point(0, 1), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('~', new Point(1, 1), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('!', new Point(3, 1), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('@', new Point(4, 1), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('#', new Point(5, 1), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('$', new Point(6, 1), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('%', new Point(8, 1), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('^', new Point(9, 1), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('&', new Point(0, 2), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('=', new Point(1, 2), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('*', new Point(2, 2), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('(', new Point(4, 2), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile(')', new Point(0, 3), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('_', new Point(2, 3), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile('-', new Point(9, 3), TileFlags.Closed | TileFlags.Wall);\r
- tilemap.SetTile(',', new Point(1, 4), TileFlags.Default);\r
- tilemap.SetTile('+', new Point(2, 4), TileFlags.Default);\r
- tilemap.SetTile('[', new Point(3, 4), TileFlags.Default);\r
- tilemap.SetTile(']', new Point(4, 4), TileFlags.Default);\r
- tilemap.SetTile('{', new Point(5, 4), TileFlags.Default);\r
- tilemap.SetTile('}', new Point(6, 4), TileFlags.Default);\r
- tilemap.SetTile('\\', new Point(8, 4), TileFlags.Default);\r
- tilemap.SetTile('|', new Point(9, 4), TileFlags.Default);\r
- tilemap.SetTile(';', new Point(0, 5), TileFlags.Default);\r
- tilemap.SetTile(':', new Point(1, 5), TileFlags.Default);\r
+ tilemap.SetTile('`', new Point(0, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('~', new Point(1, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('!', new Point(2, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('@', new Point(3, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('#', new Point(4, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('$', new Point(5, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('%', new Point(6, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('^', new Point(8, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('&', new Point(9, 2), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('*', new Point(0, 3), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('(', new Point(1, 3), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile(')', new Point(2, 3), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('-', new Point(3, 3), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('=', new Point(4, 3), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('_', new Point(5, 3), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('+', new Point(6, 3), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('|', new Point(8, 3), TileFlags.Closed | TileFlags.Wall);\r
+ tilemap.SetTile('[', new Point(0, 4), TileFlags.Default);\r
+ tilemap.SetTile(']', new Point(1, 4), TileFlags.Default);\r
+ tilemap.SetTile('{', new Point(2, 4), TileFlags.Default);\r
+ tilemap.SetTile('}', new Point(3, 4), TileFlags.Default);\r
+ tilemap.SetTile('?', new Point(4, 4), TileFlags.Default);\r
+ tilemap.SetTile(',', new Point(7, 4), TileFlags.Default);\r
+ tilemap.SetTile('.', new Point(8, 4), TileFlags.Default);\r
+ tilemap.SetTile('\\', new Point(9, 4), TileFlags.Default);\r
+ tilemap.SetTile(';', new Point(0, 5), TileFlags.Default);\r
+ tilemap.SetTile(':', new Point(1, 5), TileFlags.Default);\r
tilemap.SetTile('\'', new Point(2, 5), TileFlags.Default);\r
- tilemap.SetTile('"', new Point(3, 5), TileFlags.Default);\r
- tilemap.SetTile('.', new Point(5, 5), TileFlags.Default);\r
- tilemap.SetTile('<', new Point(6, 5), TileFlags.Default);\r
- tilemap.SetTile('>', new Point(7, 5), TileFlags.Default);\r
- tilemap.SetTile('/', new Point(8, 5), TileFlags.Default);\r
- tilemap.SetTile('?', new Point(9, 5), TileFlags.Default);\r
+ tilemap.SetTile('"', new Point(3, 5), TileFlags.Default);\r
+ tilemap.SetTile(' ', new Point(4, 5), TileFlags.Default);\r
+ tilemap.SetTile('<', new Point(7, 5), TileFlags.Default);\r
+ tilemap.SetTile('>', new Point(8, 5), TileFlags.Default);\r
+ tilemap.SetTile('/', new Point(9, 5), TileFlags.Default);\r
Map.Tilemap = tilemap;\r
\r
// Load the first map.\r
- State.Map = mContentManager.Load<Map>("Maps/level1");\r
+ State.Map = mContentManager.Load<Map>("Maps/colosseum");\r
State.Entities = State.Map.GetAllEntities(this);\r
\r
//State.AIData = new AI(this);\r
\r
\r
/// <summary>\r
- /// Helper method to get neighbor cells from a point and directions.\r
+ /// Helper method to get a neighbor cell from a point and directions.\r
/// </summary>\r
/// <param name="point">The point.</param>\r
/// <param name="left">To the left.</param>\r
return point;\r
}\r
\r
+ /// <summary>\r
+ /// Helper method to get a neighbor cell from a point and a direction.\r
+ /// </summary>\r
+ /// <param name="point">The point.</param>\r
+ /// <param name="direction">The direction.</param>\r
+ /// <returns>The neighbor cell coordinates.</returns>\r
+ public static Point GetNeighbor(Point point, Direction direction)\r
+ {\r
+ switch (direction)\r
+ {\r
+ case Direction.Left: return new Point(point.X - 1, point.Y);\r
+ case Direction.UpperLeft: return new Point(point.X - 1, point.Y - 1);\r
+ case Direction.Up: return new Point(point.X, point.Y - 1);\r
+ case Direction.UpperRight: return new Point(point.X + 1, point.Y - 1);\r
+ case Direction.Right: return new Point(point.X + 1, point.Y);\r
+ case Direction.LowerRight: return new Point(point.X + 1, point.Y + 1);\r
+ case Direction.Down: return new Point(point.X, point.Y + 1);\r
+ case Direction.LowerLeft: return new Point(point.X - 1, point.Y + 1);\r
+ }\r
+ return point;\r
+ }\r
+\r
/// <summary>\r
/// Helper method to get the two neighbor cells of two nearby cells.\r
/// </summary>\r
/// <param name="start">The cell to start at.</param>\r
/// <param name="finish">The desired destination.</param>\r
/// <returns>A list of points representing the path through the grid,\r
- /// ends points not included, or null if no path could be found.</return>\r
+ /// starting point not included, or null if no path could be found.</return>\r
public List<Point> GetPath(Point start, Point finish)\r
{\r
return GetPath(start, finish, GetManhattanDistance, GetCost);\r
/// <param name="finish">The desired destination.</param>\r
/// <param name="heuristic">The heuristic function.</param>\r
/// <returns>A list of points representing the path through the grid,\r
- /// ends points not included, or null if no path could be found.</return>\r
+ /// starting point not included, or null if no path could be found.</return>\r
public List<Point> GetPath(Point start, Point finish, Heuristic heuristic)\r
{\r
return GetPath(start, finish, heuristic, GetCost);\r
/// <param name="finish">The desired destination.</param>\r
/// <param name="costFunction">The cost function</param>\r
/// <returns>A list of points representing the path through the grid,\r
- /// ends points not included, or null if no path could be found.</return>\r
+ /// starting point not included, or null if no path could be found.</return>\r
public List<Point> GetPath(Point start, Point finish, CostFunction costFunction)\r
{\r
return GetPath(start, finish, GetManhattanDistance, costFunction);\r
/// <param name="heuristic">The heuristic function.</param>\r
/// <param name="costFunction">The cost function.</param>\r
/// <returns>A list of points representing the path through the grid,\r
- /// ends points not included, or null if no path could be found.</return>\r
+ /// starting point not included, or null if no path could be found.</return>\r
public List<Point> GetPath(Point start, Point finish, Heuristic heuristic, CostFunction costFunction)\r
{\r
mFringe = new BinaryHeap<Cell>();\r
if (cell.Point == finish)\r
{\r
List<Point> list = new List<Point>();\r
+ list.Add(cell.Point);\r
\r
cell = cell.Parent;\r
- while (cell != null && cell.Point != start)\r
- {\r
- list.Add(cell.Point);\r
- cell = cell.Parent;\r
- }\r
+ if (cell != null) for (; cell.Point != start; cell = cell.Parent) list.Add(cell.Point);\r
\r
list.Reverse();\r
return list;\r
mPlayerIndex = playerIndex;\r
\r
// Speed is the number of grid cells you can move through per second.\r
- mMotion = new MovementManager(position, 4.0f);\r
+ mMotion = new MovementManager(position, 25.0f);\r
}\r
public void causeDamageTo(int amount)\r
{\r
bool moveUp = keysPressed.Contains(Keys.Up);\r
bool moveDown = keysPressed.Contains(Keys.Down);\r
\r
- List<Point> possibleDestinations = new List<Point>();\r
+ List<Point> possibleDestinations = new List<Point>(3);\r
possibleDestinations.Add(MovementManager.GetNeighbor(mMotion.Coordinates, moveLeft, moveRight, moveUp, moveDown));\r
possibleDestinations.AddRange(MovementManager.GetNeighbors(mMotion.Coordinates, possibleDestinations[0]));\r
\r
{\r
mId = identifier;\r
mMotion = new MovementManager(position);\r
+ mRetryInterval = 20 + (position.X * 25789 + position.Y * 259) % 30;\r
\r
// We need to keep the game reference in order to get the grid when we\r
// need to find paths.\r
foreach (string pathPoint in idlePathPoints)\r
{\r
Point? point = Parse.Coordinates(pathPoint);\r
- if (point != null) mIdlePath.Add(point.Value);\r
+ if (point != null) mWaypoints.Add(point.Value);\r
}\r
}\r
\r
/// </summary>\r
public void StartPacing()\r
{\r
- mState = AiState.Pacing;\r
+ if (mWaypoints.Count == 0) return;\r
\r
- if (mIdlePath.Count == 0) return;\r
+ mState = AiState.Pacing;\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
+ mWaypointIndex = 0;\r
int closest = int.MaxValue;\r
- for (int i = 0; i < mIdlePath.Count; i++)\r
+ for (int i = 0; i < mWaypoints.Count; i++)\r
{\r
- int distance = PathFinder.GetManhattanDistance(Coordinates, mIdlePath[i]);\r
+ int distance = PathFinder.GetManhattanDistance(Coordinates, mWaypoints[i]);\r
if (distance < closest)\r
{\r
- mIdlePathIndex = i;\r
+ mWaypointIndex = 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
+ ChartPath();\r
}\r
\r
Direction GetDirectionToNextCell()\r
{\r
// We're done with the current path, so find the path to\r
// the next waypoint... forever.\r
- mIdlePathIndex++;\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 % mIdlePath.Count]);\r
- if (path != null)\r
- {\r
- mPath.AddRange(path);\r
- mPath.Add(mIdlePath[mIdlePathIndex % mIdlePath.Count]);\r
- }\r
- mPathIndex = 0;\r
+ mWaypointIndex++;\r
+ ChartPath();\r
}\r
\r
- // We need to make sure out direction is set to the next cell\r
+ // We need to make sure our 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
+ if (mPathIndex < mPath.Count && mPath[mPathIndex] == mMotion.Coordinates)\r
{\r
mPathIndex++;\r
mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex % mPath.Count]);\r
return mPathDirection;\r
}\r
\r
+ void ChartPath()\r
+ {\r
+ mPath = new List<Point>(32);\r
+\r
+ Point waypoint = mWaypoints[mWaypointIndex % mWaypoints.Count];\r
+ PathFinder pathFinder = new PathFinder(mGame.Grid);\r
+ List<Point> path = pathFinder.GetPath(mMotion.Coordinates, waypoint);\r
+ if (path != null) mPath.AddRange(path);\r
+\r
+ mPathIndex = 0;\r
+ if (mPathIndex < mPath.Count) mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex]);\r
+ else mPathDirection = Direction.None;\r
+ }\r
+\r
\r
#region IMonster Members\r
\r
/// <param name="contentManager">The zaphnod.</param>\r
public void LoadContent(ContentManager contentManager)\r
{\r
- mTexture = contentManager.Load<Texture2D>("menuItem");\r
+ mTexture = contentManager.Load<Texture2D>("default");\r
}\r
\r
/// <summary>\r
/// <param name="timeSpan"></param>\r
public void Update(TimeSpan timeSpan)\r
{\r
- if (mState == AiState.Pacing)\r
+ switch (mState)\r
{\r
- mMotion.Update(timeSpan, GetDirectionToNextCell());\r
+ case AiState.Pacing:\r
+\r
+ Direction direction = GetDirectionToNextCell();\r
+ Point destination = MovementManager.GetNeighbor(Coordinates, direction);\r
+\r
+ if (mGame.IsCellOpen(destination))\r
+ {\r
+ mMotion.Update(timeSpan, direction);\r
+ }\r
+ else\r
+ {\r
+ if (mGame.CurrentFrameNumber % mRetryInterval == 0)\r
+ {\r
+ // Something is in our way, so let's chart a new course.\r
+ ChartPath();\r
+\r
+ direction = GetDirectionToNextCell();\r
+ /*if (direction == Direction.None)\r
+ {\r
+ // If we still can't chart a course, just stand there\r
+ // and try to chart again later.\r
+ mState = AiState.Standing;\r
+ }*/\r
+\r
+ mMotion.Update(timeSpan, direction);\r
+ }\r
+ else mMotion.Update(timeSpan);\r
+ }\r
+\r
+ break;\r
+\r
+ case AiState.Standing:\r
+\r
+ mMotion.Update(timeSpan);\r
+ break;\r
}\r
}\r
\r
char mId;\r
MovementManager mMotion;\r
\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
+ List<Point> mWaypoints = new List<Point>(); // List of waypoints that we got from the map.\r
+ int mWaypointIndex; // 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
+ int mRetryInterval;\r
\r
AiState mState; // What is the monster doing?\r
\r