X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=CarFire%2FCarFire%2FCarFire%2FMap.cs;h=6727133bc79c1ee72471e67d8f30c0fd2fa7349e;hb=b92963913e205b5370c112dd5cbf96f91194bc50;hp=95a8c2c9b75253b17cc4debd169d312ca3cf43f5;hpb=c8f76edcbc66e1466db1cfef4bc314a7261670e8;p=chaz%2Fcarfire diff --git a/CarFire/CarFire/CarFire/Map.cs b/CarFire/CarFire/CarFire/Map.cs index 95a8c2c..6727133 100644 --- a/CarFire/CarFire/CarFire/Map.cs +++ b/CarFire/CarFire/CarFire/Map.cs @@ -7,6 +7,7 @@ using System.Runtime.Serialization; using System.Diagnostics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using System.Reflection; namespace CarFire { @@ -21,9 +22,33 @@ namespace CarFire // DEBUG: Tilesets not implemented at all. public static Texture2D DefaultTile; + #region Public Exceptions + + /// + /// This exception is thrown during the loading of a map if any + /// part of the map file is inconsistent with the expected format + /// and order. + /// + public class RuntimeException : System.ApplicationException + { + public RuntimeException() { } + + public RuntimeException(string message) : + base(message) { } + + public RuntimeException(string message, System.Exception inner) : + base(message, inner) { } + + protected RuntimeException(SerializationInfo info, StreamingContext context) : + base(info, context) { } + } + + #endregion + + #region Public Constants - public const float PixelsToUnitSquares = 64.0f; + public const float PixelsToUnitSquares = 60.0f; #endregion @@ -33,7 +58,7 @@ namespace CarFire /// /// The type of a map helps determine how the map is intended to be used. /// - public enum Type + public enum Mode { None, Campaign, @@ -46,7 +71,7 @@ namespace CarFire public class Metadata { public string Name; - public Type Type; + public Mode Type; public string Author; public HashSet NumPlayers = new HashSet(); public string Tileset; @@ -54,6 +79,16 @@ namespace CarFire public int GridHeight; } + /// + /// The container class for information about an entity defined in the map. + /// + public class RawEntity + { + public char Id; + public Point Position; + public Dictionary Attributes = new Dictionary(); + } + #endregion @@ -67,7 +102,7 @@ namespace CarFire /// /// Get the type of the map. /// - //public Type Type { get { return mData.mMetadata.Type; } } + public Mode Type { get { return mData.Metadata.Type; } } /// /// Get the author of the map. @@ -92,10 +127,28 @@ namespace CarFire // TODO: This should return whatever object we end up using for tilesets. public string Tileset { get { return mData.Metadata.Tileset; } } + /// + /// Get the current grid of open cells. On the grid, true means + /// the cell is open (i.e. an entity can occupy that cell), and false + /// means the cell is closed. Note that, just like Map.IsCellOpen, + /// only static scenery is considered; the grid cannot tell you + /// whether or not an entity is already occupying the cell. + /// + public bool[,] Grid { get { return mData.Grid; } } + + /// + /// Get a list of the raw entity containers loaded with the map. If you + /// want to get the actual entity objects, use Map.GetEntities and + /// Map.GetAllEntities instead. + /// + public List RawEntities { get { return mData.Entities; } } + /// /// Get and set the coordinate of the grid cell that should be in - /// the center of the screen when the map is drawn. + /// the center of the screen when the map is drawn. Setting this + /// will change the viewport of the map and will effect the return + /// values of Map.GetPointFromCoordinates and Map.GetRectangleFromCoordinates. /// public Vector2 CenterCell { @@ -111,10 +164,13 @@ namespace CarFire /// /// Construct a map with the provided map data. /// - /// Map data. - public Map(Metadata metadata, char[,] grid, Dictionary> entities) + /// The metadata. + /// The grid. + /// The entities. + public Map(Metadata metadata, char[,] grid, char defaultTile, + List entities, Point[] playerPositions) { - mData = new Modal(metadata, grid, entities); + mData = new Modal(metadata, grid, defaultTile, entities, playerPositions); mView = new View(mData); } @@ -186,7 +242,7 @@ namespace CarFire /// /// Determine whether or not a cell can be occupied by a game entity. /// - /// X,Y-coordinates. + /// X,Y-coordinates. /// True if cell can be occupied, false otherwise. public bool IsCellOpen(Point point) { @@ -195,14 +251,79 @@ namespace CarFire /// - /// Get the entities loaded from the map file. + /// Get the starting position of a player. + /// + /// The number of the player (i.e. 1-4). + /// This number must be a valid player number. + /// The starting position of the player. + public Point GetStartingPositionForPlayer(int playerNumber) + { + Debug.Assert(1 <= playerNumber && playerNumber <= NumPlayers.Max()); + return mData.PlayerPositions[playerNumber]; + } + + + /// + /// Get all the entities loaded from the map file. Exceptions could be + /// thrown if there are entities without associated classes. + /// + /// List of entity objects loaded. + public List GetAllEntities() + { + return mData.GetAllEntities(); + } + + /// + /// Get the entities of a certain type loaded from the map file. Exceptions + /// could be thrown if there are entities without associated classes. + /// + /// Type of the entity you want a list of. + /// List of entity objects loaded. + public List GetEntities() + { + return mData.GetEntities(); + } + + + /// + /// Set the tile of a cell. + /// + /// X-coordinate. + /// Y-coordinate. + /// The character representing the tile. + public void SetCell(int x, int y, char tile) + { + mData.SetCell(x, y, tile); + } + + /// + /// Set the tile of a cell. + /// + /// X,Y-coordinates. + /// The character representing the tile. + public void SetCell(Point point, char tile) + { + mData.SetCell(point.X, point.Y, tile); + } + + + /// + /// Clear a cell to the default tile. /// - /// Dictionary of entities. The keys are the entity - /// identifiers and the value is a dictionary of key-value pairs - /// associated with that entity. - public Dictionary> GetEntities() + /// X-coordinate. + /// Y-coordinate. + public void ClearCell(int x, int y) { - return mData.Entities; + mData.ClearCell(x, y); + } + + /// + /// Clear a cell to the default tile. + /// + /// X,Y-coordinates. + public void ClearCell(Point point) + { + mData.ClearCell(point.X, point.Y); } #endregion @@ -214,9 +335,13 @@ namespace CarFire { Metadata mMetadata; char[,] mGrid; - Dictionary> mEntities; + char mDefaultTile; + List mEntities; + Point[] mPlayerPositions; + bool[,] mBooleanGrid; - public Modal(Metadata metadata, char[,] grid, Dictionary> entities) + public Modal(Metadata metadata, char[,] grid, char defaultTile, + List entities, Point[] playerPositions) { Debug.Assert(metadata != null); Debug.Assert(grid != null); @@ -225,7 +350,18 @@ namespace CarFire mMetadata = metadata; mGrid = grid; + mDefaultTile = defaultTile; mEntities = entities; + mPlayerPositions = playerPositions; + + mBooleanGrid = new bool[mMetadata.GridWidth, mMetadata.GridHeight]; + for (int x = 0; x < mMetadata.GridWidth; x++) + { + for (int y = 0; y < mMetadata.GridHeight; y++) + { + mBooleanGrid[x, y] = IsCellOpen(x, y); + } + } #if DEBUG Console.WriteLine("Loaded map {0} of type {1} written by {2}.", @@ -237,7 +373,9 @@ namespace CarFire public Metadata Metadata { get { return mMetadata; } } - public Dictionary> Entities { get { return mEntities; } } + public List Entities { get { return mEntities; } } + public Point[] PlayerPositions { get { return mPlayerPositions; } } + public bool[,] Grid { get { return mBooleanGrid; } } public bool IsCellOpen(int x, int y) @@ -245,6 +383,80 @@ namespace CarFire // TODO: Still need to define characters for types of scenery. return mGrid[x, y] == ' '; } + + public void SetCell(int x, int y, char tile) + { + mGrid[x, y] = tile; + mBooleanGrid[x, y] = IsCellOpen(x, y); + } + + public void ClearCell(int x, int y) + { + SetCell(x, y, mDefaultTile); + } + + + public List GetAllEntities() + { + List list = new List(); + + foreach (RawEntity raw in mEntities) + { + if (raw.Attributes.ContainsKey("type")) + { + string typename = raw.Attributes["type"]; + + object[] args = new object[3]; + args[0] = raw.Id; + args[1] = raw.Position; + args[2] = raw.Attributes; + + try + { + + object entity = Activator.CreateInstance(System.Type.GetType("CarFire." + typename), args); + if (entity != null) list.Add(entity); + else throw new RuntimeException(); + } +#pragma warning disable 0168 + catch (System.Exception ex) +#pragma warning restore 0168 + { + throw new RuntimeException("Entity of type " + typename + " not loaded because an entity class can't be found."); + } + } + else + { + Console.WriteLine("Ignoring entity with identifier " + raw.Id + " since it has no type key."); + } + } + + return list; + } + + public List GetEntities() + { + System.Type type = typeof(T); + List list = new List(); + + string typename = typeof(T).Name; + foreach (RawEntity raw in mEntities) + { + if (raw.Attributes.ContainsKey("type") && typename == raw.Attributes["type"]) + { + object[] args = new object[3]; + args[0] = raw.Id; + args[1] = raw.Position; + args[2] = raw.Attributes; + + T entity = (T)Activator.CreateInstance(type, args); + if (entity != null) list.Add(entity); + else throw new RuntimeException("Entity of type " + typename + " not loaded because an entity class can't be found."); + } + } + + return list; + } } class View