From: Charles Date: Tue, 27 Apr 2010 04:35:32 +0000 (+0000) Subject: colosseum is now crowded with monsters; made the SaberMonster moving code more robust... X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fcarfire;a=commitdiff_plain;h=122c062297acac44673e947b666c1d72cd23fb1b colosseum is now crowded with monsters; made the SaberMonster moving code more robust so they will now chart new paths around obstacles; *Important* PathFinder.GetPath now will include the destination point in the returned list. git-svn-id: https://bd85.net/svn/cs3505_group@156 92bb83a3-7c8f-8a45-bc97-515c4e399668 --- diff --git a/CarFire/CarFire/CarFire/Content/Maps/colosseum.cfmap b/CarFire/CarFire/CarFire/Content/Maps/colosseum.cfmap index 54c9faa..6c58825 100644 --- a/CarFire/CarFire/CarFire/Content/Maps/colosseum.cfmap +++ b/CarFire/CarFire/CarFire/Content/Maps/colosseum.cfmap @@ -8,46 +8,74 @@ tileset = FuturisticBuilding numplayers = <1,4> +[a] + type = SaberMonster + path = [5,5] [7,3] [25,30] + speed = 7 + 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] + +[b] + type = SaberMonster + path = [0,0] [40,0] [40,40] [0,40] + speed = 23 + create = [0,4] [4,0] + +[e] + type = SaberMonster + path = [0,0] [40,0] [40,40] [0,40] + speed = 16 + create = [40,4] + +[c] + type = SaberMonster + path = [5,7] [18,18] [34,34] [4,20] [37,4] [6,37] [21,21] [21,30] [35,20] + speed = 5 + create = [2,2] [20,20] [5,35] [21,34] [34,37] [37,15] [31,31] [2,34] [22,4] + +[d] + type = SaberMonster + path = [2,6] [6,6] + [maptable] +-------------------------------------+ - | /\ | - | 1 / \ 2 | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \ | - | / \| - |/ /| - |\ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | \ / | - | 4 \ / 3 | - | \/ | + |""" __ """| + |"1" _ _ "2"| + |""" _ _ """| + | """"""""" _ _ " | + |d " _ " | + | " _ " | + | " _ " | + | _ " _ " | + | _ " _ " | + | _ " _ " | + | _ " " | + | _ " " | + | _ " " | + | _ " " _ | + | _ " " _ | + | _ " " _ | + | _ "" _ | + | _ " _| + |_ " _| + |_ " _ | + | _ "" _ | + | _ " " _ | + | """"""""""""""" " _ | + | " " _ | + | " " _ | + | " _ " | + | " _ " | + | " _ " | + | " _ _ " | + | " _ _ " | + | " _ _ " | + | " _ _ " | + | " _ _ " | + | " _ _ " | + |""" _ _ """| + |"4" _ _ "3"| + |""" __ """| +-------------------------------------+ ; vi:ft=dosini diff --git a/CarFire/CarFire/CarFire/Content/Maps/level1.cfmap b/CarFire/CarFire/CarFire/Content/Maps/level1.cfmap index 20e1da9..3adce98 100644 --- a/CarFire/CarFire/CarFire/Content/Maps/level1.cfmap +++ b/CarFire/CarFire/CarFire/Content/Maps/level1.cfmap @@ -23,26 +23,26 @@ options = Once [maptable] -+------------------------------------------------------------------------------+ -| | -| 1 2 | -| ... | -| 3 4 .L. +---- | -| ... | M | -| k | | +`~~*!@@)#@`(~#!=@`#=`~~*!@@)#@`(~#!=@`#@`~~#!@@`#@`~~#!@@`#@`~~#!@@`#@`~~#!@@`#@ +$ ? ? ? ? ? ? ? ? ? ? | +$ 1 2 | +$ | +$ 3 4 +---- | +$ | | +`~~*!@@)#@`(~#!=@`#| | | |------------------------------------------ | | | | | | | | | +-------------+----+ | \ / | | | | \ / | -| M | | \ / | +| | | \ / | | | | \ / | | | \ @ # $ % ^ & * ( ) | | | | +-------+ | / \ | | | / \ | | / \ | | / \ | -| | -+------------------------------------------------------------------------------+ +:;::'""..<> | +=(&**(&(&&*&(*((((&&*&(*&*&(&(*&**&*&(&(*&*&*&*&(*&(&**&*(&(&(&*&*&*&&*(*((*&*(( ; vi:ft=dosini diff --git a/CarFire/CarFire/CarFire/Game.cs b/CarFire/CarFire/CarFire/Game.cs index f78945b..5650711 100644 --- a/CarFire/CarFire/CarFire/Game.cs +++ b/CarFire/CarFire/CarFire/Game.cs @@ -225,11 +225,17 @@ namespace CarFire { get { - bool[,] grid = State.Map.Grid; + bool[,] grid = (bool[,])State.Map.Grid.Clone(); foreach (IEntity entity in State.Entities) { Point coordinates = entity.Coordinates; - if (State.Map.IsCellOpen(coordinates)) grid[coordinates.X, coordinates.Y] = false; + grid[coordinates.X, coordinates.Y] = false; + } + foreach (Player player in State.mCharacters) + { + if (player == null) continue; + Point coordinates = player.Coordinates; + grid[coordinates.X, coordinates.Y] = false; } return grid; } @@ -279,6 +285,8 @@ namespace CarFire if (!State.Map.IsCellOpen(point)) return false; IEntity entity = GetEntityAtCoordinates(point); if (entity != null && entity.IsCollidable) return false; + Player player = GetPlayerAtCoordinates(point); + if (player != null) return false; return true; } @@ -384,43 +392,43 @@ namespace CarFire // Load the tilemap. Texture2D mapTiles = mContentManager.Load("graphics/wallAndFloorTilesNoEdgeScale"); Tilemap tilemap = new Tilemap(mapTiles, 10, 7); - tilemap.SetTile(' ', new Point(4, 5), TileFlags.Default); - tilemap.SetTile('`', new Point(0, 1), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('~', new Point(1, 1), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('!', new Point(3, 1), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('@', new Point(4, 1), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('#', new Point(5, 1), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('$', new Point(6, 1), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('%', new Point(8, 1), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('^', new Point(9, 1), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('&', new Point(0, 2), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('=', new Point(1, 2), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('*', new Point(2, 2), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('(', new Point(4, 2), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile(')', new Point(0, 3), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('_', new Point(2, 3), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile('-', new Point(9, 3), TileFlags.Closed | TileFlags.Wall); - tilemap.SetTile(',', new Point(1, 4), TileFlags.Default); - tilemap.SetTile('+', new Point(2, 4), TileFlags.Default); - tilemap.SetTile('[', new Point(3, 4), TileFlags.Default); - tilemap.SetTile(']', new Point(4, 4), TileFlags.Default); - tilemap.SetTile('{', new Point(5, 4), TileFlags.Default); - tilemap.SetTile('}', new Point(6, 4), TileFlags.Default); - tilemap.SetTile('\\', new Point(8, 4), TileFlags.Default); - tilemap.SetTile('|', new Point(9, 4), TileFlags.Default); - tilemap.SetTile(';', new Point(0, 5), TileFlags.Default); - tilemap.SetTile(':', new Point(1, 5), TileFlags.Default); + tilemap.SetTile('`', new Point(0, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('~', new Point(1, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('!', new Point(2, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('@', new Point(3, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('#', new Point(4, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('$', new Point(5, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('%', new Point(6, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('^', new Point(8, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('&', new Point(9, 2), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('*', new Point(0, 3), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('(', new Point(1, 3), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile(')', new Point(2, 3), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('-', new Point(3, 3), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('=', new Point(4, 3), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('_', new Point(5, 3), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('+', new Point(6, 3), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('|', new Point(8, 3), TileFlags.Closed | TileFlags.Wall); + tilemap.SetTile('[', new Point(0, 4), TileFlags.Default); + tilemap.SetTile(']', new Point(1, 4), TileFlags.Default); + tilemap.SetTile('{', new Point(2, 4), TileFlags.Default); + tilemap.SetTile('}', new Point(3, 4), TileFlags.Default); + tilemap.SetTile('?', new Point(4, 4), TileFlags.Default); + tilemap.SetTile(',', new Point(7, 4), TileFlags.Default); + tilemap.SetTile('.', new Point(8, 4), TileFlags.Default); + tilemap.SetTile('\\', new Point(9, 4), TileFlags.Default); + tilemap.SetTile(';', new Point(0, 5), TileFlags.Default); + tilemap.SetTile(':', new Point(1, 5), TileFlags.Default); tilemap.SetTile('\'', new Point(2, 5), TileFlags.Default); - tilemap.SetTile('"', new Point(3, 5), TileFlags.Default); - tilemap.SetTile('.', new Point(5, 5), TileFlags.Default); - tilemap.SetTile('<', new Point(6, 5), TileFlags.Default); - tilemap.SetTile('>', new Point(7, 5), TileFlags.Default); - tilemap.SetTile('/', new Point(8, 5), TileFlags.Default); - tilemap.SetTile('?', new Point(9, 5), TileFlags.Default); + tilemap.SetTile('"', new Point(3, 5), TileFlags.Default); + tilemap.SetTile(' ', new Point(4, 5), TileFlags.Default); + tilemap.SetTile('<', new Point(7, 5), TileFlags.Default); + tilemap.SetTile('>', new Point(8, 5), TileFlags.Default); + tilemap.SetTile('/', new Point(9, 5), TileFlags.Default); Map.Tilemap = tilemap; // Load the first map. - State.Map = mContentManager.Load("Maps/level1"); + State.Map = mContentManager.Load("Maps/colosseum"); State.Entities = State.Map.GetAllEntities(this); //State.AIData = new AI(this); diff --git a/CarFire/CarFire/CarFire/MovementManager.cs b/CarFire/CarFire/CarFire/MovementManager.cs index 73caa57..7d81868 100644 --- a/CarFire/CarFire/CarFire/MovementManager.cs +++ b/CarFire/CarFire/CarFire/MovementManager.cs @@ -195,7 +195,7 @@ namespace CarFire /// - /// Helper method to get neighbor cells from a point and directions. + /// Helper method to get a neighbor cell from a point and directions. /// /// The point. /// To the left. @@ -212,6 +212,28 @@ namespace CarFire return point; } + /// + /// Helper method to get a neighbor cell from a point and a direction. + /// + /// The point. + /// The direction. + /// The neighbor cell coordinates. + public static Point GetNeighbor(Point point, Direction direction) + { + switch (direction) + { + case Direction.Left: return new Point(point.X - 1, point.Y); + case Direction.UpperLeft: return new Point(point.X - 1, point.Y - 1); + case Direction.Up: return new Point(point.X, point.Y - 1); + case Direction.UpperRight: return new Point(point.X + 1, point.Y - 1); + case Direction.Right: return new Point(point.X + 1, point.Y); + case Direction.LowerRight: return new Point(point.X + 1, point.Y + 1); + case Direction.Down: return new Point(point.X, point.Y + 1); + case Direction.LowerLeft: return new Point(point.X - 1, point.Y + 1); + } + return point; + } + /// /// Helper method to get the two neighbor cells of two nearby cells. /// diff --git a/CarFire/CarFire/CarFire/PathFinder.cs b/CarFire/CarFire/CarFire/PathFinder.cs index 02c645c..ef41370 100644 --- a/CarFire/CarFire/CarFire/PathFinder.cs +++ b/CarFire/CarFire/CarFire/PathFinder.cs @@ -68,7 +68,7 @@ namespace CarFire /// The cell to start at. /// The desired destination. /// A list of points representing the path through the grid, - /// ends points not included, or null if no path could be found. + /// starting point not included, or null if no path could be found. public List GetPath(Point start, Point finish) { return GetPath(start, finish, GetManhattanDistance, GetCost); @@ -82,7 +82,7 @@ namespace CarFire /// The desired destination. /// The heuristic function. /// A list of points representing the path through the grid, - /// ends points not included, or null if no path could be found. + /// starting point not included, or null if no path could be found. public List GetPath(Point start, Point finish, Heuristic heuristic) { return GetPath(start, finish, heuristic, GetCost); @@ -96,7 +96,7 @@ namespace CarFire /// The desired destination. /// The cost function /// A list of points representing the path through the grid, - /// ends points not included, or null if no path could be found. + /// starting point not included, or null if no path could be found. public List GetPath(Point start, Point finish, CostFunction costFunction) { return GetPath(start, finish, GetManhattanDistance, costFunction); @@ -110,7 +110,7 @@ namespace CarFire /// The heuristic function. /// The cost function. /// A list of points representing the path through the grid, - /// ends points not included, or null if no path could be found. + /// starting point not included, or null if no path could be found. public List GetPath(Point start, Point finish, Heuristic heuristic, CostFunction costFunction) { mFringe = new BinaryHeap(); @@ -127,13 +127,10 @@ namespace CarFire if (cell.Point == finish) { List list = new List(); + list.Add(cell.Point); cell = cell.Parent; - while (cell != null && cell.Point != start) - { - list.Add(cell.Point); - cell = cell.Parent; - } + if (cell != null) for (; cell.Point != start; cell = cell.Parent) list.Add(cell.Point); list.Reverse(); return list; diff --git a/CarFire/CarFire/CarFire/Player.cs b/CarFire/CarFire/CarFire/Player.cs index 124851c..e89b284 100644 --- a/CarFire/CarFire/CarFire/Player.cs +++ b/CarFire/CarFire/CarFire/Player.cs @@ -57,7 +57,7 @@ namespace CarFire mPlayerIndex = playerIndex; // Speed is the number of grid cells you can move through per second. - mMotion = new MovementManager(position, 4.0f); + mMotion = new MovementManager(position, 25.0f); } public void causeDamageTo(int amount) { @@ -89,7 +89,7 @@ namespace CarFire bool moveUp = keysPressed.Contains(Keys.Up); bool moveDown = keysPressed.Contains(Keys.Down); - List possibleDestinations = new List(); + List possibleDestinations = new List(3); possibleDestinations.Add(MovementManager.GetNeighbor(mMotion.Coordinates, moveLeft, moveRight, moveUp, moveDown)); possibleDestinations.AddRange(MovementManager.GetNeighbors(mMotion.Coordinates, possibleDestinations[0])); diff --git a/CarFire/CarFire/CarFire/SaberMonster.cs b/CarFire/CarFire/CarFire/SaberMonster.cs index f417d52..69b42ca 100644 --- a/CarFire/CarFire/CarFire/SaberMonster.cs +++ b/CarFire/CarFire/CarFire/SaberMonster.cs @@ -42,6 +42,7 @@ namespace CarFire { mId = identifier; mMotion = new MovementManager(position); + mRetryInterval = 20 + (position.X * 25789 + position.Y * 259) % 30; // We need to keep the game reference in order to get the grid when we // need to find paths. @@ -64,7 +65,7 @@ namespace CarFire foreach (string pathPoint in idlePathPoints) { Point? point = Parse.Coordinates(pathPoint); - if (point != null) mIdlePath.Add(point.Value); + if (point != null) mWaypoints.Add(point.Value); } } @@ -80,35 +81,26 @@ namespace CarFire /// public void StartPacing() { - mState = AiState.Pacing; + if (mWaypoints.Count == 0) return; - if (mIdlePath.Count == 0) return; + mState = AiState.Pacing; // Determine the best (closest) waypoint to start at. // We may not be on the path, so we have to walk to get on it. - mIdlePathIndex = 0; + mWaypointIndex = 0; int closest = int.MaxValue; - for (int i = 0; i < mIdlePath.Count; i++) + for (int i = 0; i < mWaypoints.Count; i++) { - int distance = PathFinder.GetManhattanDistance(Coordinates, mIdlePath[i]); + int distance = PathFinder.GetManhattanDistance(Coordinates, mWaypoints[i]); if (distance < closest) { - mIdlePathIndex = i; + mWaypointIndex = i; closest = distance; } } // Find the path to get to the closest waypoint. - PathFinder pathFinder = new PathFinder(mGame.Grid); - mPath = new List(32); - mPath.Add(Coordinates); - List path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex]); - if (path != null) - { - mPath.AddRange(path); - mPath.Add(mIdlePath[mIdlePathIndex]); - } - mPathIndex = 0; + ChartPath(); } Direction GetDirectionToNextCell() @@ -117,23 +109,14 @@ namespace CarFire { // We're done with the current path, so find the path to // the next waypoint... forever. - mIdlePathIndex++; - PathFinder pathFinder = new PathFinder(mGame.Grid); - mPath = new List(32); - mPath.Add(Coordinates); - List path = pathFinder.GetPath(mMotion.Coordinates, mIdlePath[mIdlePathIndex % mIdlePath.Count]); - if (path != null) - { - mPath.AddRange(path); - mPath.Add(mIdlePath[mIdlePathIndex % mIdlePath.Count]); - } - mPathIndex = 0; + mWaypointIndex++; + ChartPath(); } - // We need to make sure out direction is set to the next cell + // We need to make sure our direction is set to the next cell // we want to be. If our current coordinates match that, we need // to change our direction to get to the next cell. - if (mPath[mPathIndex % mPath.Count] == mMotion.Coordinates) + if (mPathIndex < mPath.Count && mPath[mPathIndex] == mMotion.Coordinates) { mPathIndex++; mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex % mPath.Count]); @@ -142,6 +125,20 @@ namespace CarFire return mPathDirection; } + void ChartPath() + { + mPath = new List(32); + + Point waypoint = mWaypoints[mWaypointIndex % mWaypoints.Count]; + PathFinder pathFinder = new PathFinder(mGame.Grid); + List path = pathFinder.GetPath(mMotion.Coordinates, waypoint); + if (path != null) mPath.AddRange(path); + + mPathIndex = 0; + if (mPathIndex < mPath.Count) mPathDirection = MovementManager.GetDirection(mMotion.Coordinates, mPath[mPathIndex]); + else mPathDirection = Direction.None; + } + #region IMonster Members @@ -165,7 +162,7 @@ namespace CarFire /// The zaphnod. public void LoadContent(ContentManager contentManager) { - mTexture = contentManager.Load("menuItem"); + mTexture = contentManager.Load("default"); } /// @@ -176,9 +173,43 @@ namespace CarFire /// public void Update(TimeSpan timeSpan) { - if (mState == AiState.Pacing) + switch (mState) { - mMotion.Update(timeSpan, GetDirectionToNextCell()); + case AiState.Pacing: + + Direction direction = GetDirectionToNextCell(); + Point destination = MovementManager.GetNeighbor(Coordinates, direction); + + if (mGame.IsCellOpen(destination)) + { + mMotion.Update(timeSpan, direction); + } + else + { + if (mGame.CurrentFrameNumber % mRetryInterval == 0) + { + // Something is in our way, so let's chart a new course. + ChartPath(); + + direction = GetDirectionToNextCell(); + /*if (direction == Direction.None) + { + // If we still can't chart a course, just stand there + // and try to chart again later. + mState = AiState.Standing; + }*/ + + mMotion.Update(timeSpan, direction); + } + else mMotion.Update(timeSpan); + } + + break; + + case AiState.Standing: + + mMotion.Update(timeSpan); + break; } } @@ -241,13 +272,14 @@ namespace CarFire char mId; MovementManager mMotion; - List mIdlePath = new List(); // List of waypoints that we got from the map. - int mIdlePathIndex; // Index to the waypoint we're heading for. + List mWaypoints = new List(); // List of waypoints that we got from the map. + int mWaypointIndex; // Index to the waypoint we're heading for. List mPath; // List of cells in the path between the position between where // we started and the waypoint we're heading for. int mPathIndex; // Index to the cell we're heading for. Direction mPathDirection; // The direction between our current position and the place we're going. + int mRetryInterval; AiState mState; // What is the monster doing?