<Name>sandbox</Name>\r
</Compile>\r
</ItemGroup>\r
+ <ItemGroup>\r
+ <Compile Include="default.png">\r
+ <Name>default</Name>\r
+ <Importer>TextureImporter</Importer>\r
+ <Processor>TextureProcessor</Processor>\r
+ </Compile>\r
+ </ItemGroup>\r
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\v3.0\Microsoft.Xna.GameStudio.ContentPipeline.targets" />\r
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
Other similar extension points exist, see Microsoft.Common.targets.\r
using System.Collections.Generic;\r
using System.Linq;\r
using System.Text;\r
-using Microsoft.Xna.Framework;\r
using System.IO;\r
-using System.Text.RegularExpressions;\r
using System.Runtime.Serialization;\r
using System.Diagnostics;\r
+using Microsoft.Xna.Framework;\r
+using Microsoft.Xna.Framework.Graphics;\r
\r
namespace CarFire\r
{\r
/// </summary>\r
public class Map\r
{\r
- #region Types\r
+ // DEBUG: Tilesets not implemented at all.\r
+ public static Texture2D DefaultTile;\r
\r
- public class Data\r
- {\r
- public string Author;\r
- public string Name;\r
- public int MinNumPlayers;\r
- public int MaxNumPlayers;\r
- public Point Dimensions;\r
- public string Tileset; // TODO: this should be a tilemap object\r
- public Type Type;\r
- public char[,] Grid;\r
- }\r
- \r
+ #region Public Constants\r
+\r
+ public const float PixelsToUnitSquares = 64.0f;\r
+\r
+ #endregion\r
+\r
+\r
+ #region Public Types\r
+\r
+ /// <summary>\r
+ /// The type of a map helps determine how the map is intended to be used.\r
+ /// </summary>\r
public enum Type\r
{\r
None,\r
Battle\r
}\r
\r
+ /// <summary>\r
+ /// The container class for map metadata.\r
+ /// </summary>\r
+ public class Metadata\r
+ {\r
+ public string Name;\r
+ public Type Type;\r
+ public string Author;\r
+ public HashSet<int> NumPlayers = new HashSet<int>();\r
+ public string Tileset;\r
+ public int GridWidth;\r
+ public int GridHeight;\r
+ }\r
+\r
+ #endregion\r
+\r
+\r
+ #region Public Attributes\r
+\r
+ /// <summary>\r
+ /// Get the name of the map.\r
+ /// </summary>\r
+ public string Name { get { return mData.Metadata.Name; } }\r
+\r
+ /// <summary>\r
+ /// Get the type of the map.\r
+ /// </summary>\r
+ //public Type Type { get { return mData.mMetadata.Type; } }\r
+\r
+ /// <summary>\r
+ /// Get the author of the map.\r
+ /// </summary>\r
+ public string Author { get { return mData.Metadata.Author; } }\r
+\r
+ /// <summary>\r
+ /// Get a set of integers containing each allowable number of players.\r
+ /// </summary>\r
+ public HashSet<int> NumPlayers { get { return mData.Metadata.NumPlayers; } }\r
+\r
+ /// <summary>\r
+ /// Get the width of the map, in grid units.\r
+ /// </summary>\r
+ public int Width { get { return mData.Metadata.GridWidth; } }\r
+\r
+ /// <summary>\r
+ /// Get the height of the map, in grid units.\r
+ /// </summary>\r
+ public int Height { get { return mData.Metadata.GridHeight; } }\r
+\r
+ // TODO: This should return whatever object we end up using for tilesets.\r
+ public string Tileset { get { return mData.Metadata.Tileset; } }\r
+\r
+\r
+ public Vector2 CenterCell\r
+ {\r
+ get { return mView.CenterCell; }\r
+ set { mView.CenterCell = value; }\r
+ }\r
+\r
+ #endregion\r
+\r
+\r
+ #region Public Methods\r
+\r
+ /// <summary>\r
+ /// Construct a map with the provided map data.\r
+ /// </summary>\r
+ /// <param name="data">Map data.</param>\r
+ public Map(Metadata metadata, char[,] grid, Dictionary<char, Dictionary<string, string>> entities)\r
+ {\r
+ mData = new Modal(metadata, grid, entities);\r
+ mView = new View(mData);\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Draw a representation of the map to the screen.\r
+ /// </summary>\r
+ /// <param name="spriteBatch">The jeewiz.</param>\r
+ public void Draw(SpriteBatch spriteBatch)\r
+ {\r
+ mView.Draw(spriteBatch);\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Get a point in screen-space from a coordinate in gridspace.\r
+ /// </summary>\r
+ /// <param name="x">X-coordinate.</param>\r
+ /// <param name="y">Y-coordinate.</param>\r
+ /// <returns>Transformed point.</returns>\r
+ public Point GetPointFromCoordinates(float x, float y)\r
+ {\r
+ return mView.GetPointFromCoordinates(x, y);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Get a point in screen-space from a coordinate in gridspace.\r
+ /// </summary>\r
+ /// <param name="point">X,Y-coordinates.</param>\r
+ /// <returns>Transformed point.</returns>\r
+ public Point GetPointFromCoordinates(Vector2 point)\r
+ {\r
+ return mView.GetPointFromCoordinates(point.X, point.Y);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Get a rectangle in screen-space centered around a coordinate in gridspace.\r
+ /// </summary>\r
+ /// <param name="x">X-coordinate.</param>\r
+ /// <param name="y">Y-coordinate.</param>\r
+ /// <returns>Transformed rectangle.</returns>\r
+ public Rectangle GetRectangleFromCoordinates(float x, float y)\r
+ {\r
+ return mView.GetRectangleFromCoordinates(x, y);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Get a rectangle in screen-space centered around a coordinate in gridspace.\r
+ /// </summary>\r
+ /// <param name="point">X,Y-coordinates.</param>\r
+ /// <returns>Transformed rectangle.</returns>\r
+ public Rectangle GetRectangleFromCoordinates(Vector2 point)\r
+ {\r
+ return mView.GetRectangleFromCoordinates(point.X, point.Y);\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Determine whether or not a cell can be occupied by a game entity.\r
+ /// </summary>\r
+ /// <param name="x">X-coordinate.</param>\r
+ /// <param name="y">Y-coordinate.</param>\r
+ /// <returns>True if cell can be occupied, false otherwise.</returns>\r
+ public bool IsCellOpen(int x, int y)\r
+ {\r
+ return mData.IsCellOpen(x, y);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Determine whether or not a cell can be occupied by a game entity.\r
+ /// </summary>\r
+ /// <param name="x">X,Y-coordinates.</param>\r
+ /// <returns>True if cell can be occupied, false otherwise.</returns>\r
+ public bool IsCellOpen(Point point)\r
+ {\r
+ return mData.IsCellOpen(point.X, point.Y);\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Get the entities loaded from the map file.\r
+ /// </summary>\r
+ /// <returns>Dictionary of entities. The keys are the entity\r
+ /// identifiers and the value is a dictionary of key-value pairs\r
+ /// associated with that entity.</returns>\r
+ public Dictionary<char, Dictionary<string, string>> GetEntities()\r
+ {\r
+ return mData.Entities;\r
+ }\r
+\r
#endregion\r
\r
\r
- public Map(Data data)\r
+ #region Private Types\r
+\r
+ class Modal\r
+ {\r
+ Metadata mMetadata;\r
+ char[,] mGrid;\r
+ Dictionary<char, Dictionary<string, string>> mEntities;\r
+\r
+ public Modal(Metadata metadata, char[,] grid, Dictionary<char, Dictionary<string, string>> entities)\r
+ {\r
+ Debug.Assert(metadata != null);\r
+ Debug.Assert(grid != null);\r
+ Debug.Assert(entities != null);\r
+ Debug.Assert(metadata.GridWidth * metadata.GridHeight == grid.Length);\r
+\r
+ mMetadata = metadata;\r
+ mGrid = grid;\r
+ mEntities = entities;\r
+\r
+#if DEBUG\r
+ Console.WriteLine("Loaded map {0} of type {1} written by {2}.",\r
+ metadata.Name,\r
+ metadata.Type,\r
+ metadata.Author);\r
+#endif\r
+ }\r
+\r
+\r
+ public Metadata Metadata { get { return mMetadata; } }\r
+ public Dictionary<char, Dictionary<string, string>> Entities { get { return mEntities; } }\r
+\r
+\r
+ public bool IsCellOpen(int x, int y)\r
+ {\r
+ // TODO: Still need to define characters for types of scenery.\r
+ return mGrid[x, y] == ' ';\r
+ }\r
+ }\r
+\r
+ class View\r
{\r
- Console.WriteLine("Read map " + data.Name + " of type " + data.Type + " written by " + data.Author);\r
+ Modal mData;\r
+\r
+ public Vector2 CenterCell;\r
+ Viewport mViewport;\r
+\r
+\r
+ public View(Modal data)\r
+ {\r
+ Debug.Assert(data != null);\r
+ mData = data;\r
+ }\r
+\r
+ public void Draw(SpriteBatch spriteBatch)\r
+ {\r
+ mViewport = spriteBatch.GraphicsDevice.Viewport;\r
+\r
+ // TODO: There is no culling yet, but it runs so fast that it probably won't ever need it.\r
+ for (int y = 0; y < mData.Metadata.GridHeight; y++)\r
+ {\r
+ for (int x = 0; x < mData.Metadata.GridWidth; x++)\r
+ {\r
+ if (mData.IsCellOpen(x, y))\r
+ {\r
+ spriteBatch.Draw(Map.DefaultTile, GetRectangleFromCoordinates(x, y), Color.White);\r
+ }\r
+ else\r
+ {\r
+ spriteBatch.Draw(Map.DefaultTile, GetRectangleFromCoordinates(x, y), Color.DarkBlue);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Get a matrix to transform a point from grid-space to screen coordinates. This\r
+ /// method uses the viewport to bound the edges of the map such that the camera\r
+ /// will not show anything outside of the grid.\r
+ /// </summary>\r
+ /// <param name="center">The point to put in the center.</param>\r
+ /// <returns>The transformation matrix.</returns>\r
+ Matrix GetTransformation(Vector2 center)\r
+ {\r
+ float halfRatio = PixelsToUnitSquares * 0.5f;\r
+ Matrix transform = Matrix.CreateTranslation(-center.X, -center.Y, 0.0f);\r
+ transform *= Matrix.CreateScale(PixelsToUnitSquares);\r
+ transform *= Matrix.CreateTranslation(mViewport.Width * 0.5f - halfRatio,\r
+ mViewport.Height * 0.5f - halfRatio, 0.0f);\r
+\r
+ Vector2 topLeft = Vector2.Transform(new Vector2(0.0f, 0.0f), transform);\r
+ topLeft.X = Math.Max(mViewport.X, topLeft.X);\r
+ topLeft.Y = Math.Max(mViewport.Y, topLeft.Y);\r
+ transform *= Matrix.CreateTranslation(-topLeft.X, -topLeft.Y, 0.0f);\r
+\r
+ Vector2 bottomRight = Vector2.Transform(new Vector2((float)mData.Metadata.GridWidth,\r
+ (float)mData.Metadata.GridHeight), transform);\r
+ float right = mViewport.X + mViewport.Width;\r
+ float bottom = mViewport.Y + mViewport.Height;\r
+ bottomRight.X = Math.Min(right, bottomRight.X) - right;\r
+ bottomRight.Y = Math.Min(bottom, bottomRight.Y) - bottom;\r
+ transform *= Matrix.CreateTranslation(-bottomRight.X, -bottomRight.Y, 0.0f);\r
+\r
+ return transform;\r
+ }\r
+\r
+\r
+ public Point GetPointFromCoordinates(float x, float y)\r
+ {\r
+ Matrix transform = GetTransformation(CenterCell);\r
+ Vector2 point = Vector2.Transform(new Vector2(x, y), transform);\r
+\r
+ return new Point((int)point.X, (int)point.Y);\r
+ }\r
+\r
+ public Rectangle GetRectangleFromCoordinates(float x, float y)\r
+ {\r
+ Matrix transform = GetTransformation(CenterCell);\r
+ Vector2 point = Vector2.Transform(new Vector2(x, y), transform);\r
+ \r
+ return new Rectangle((int)point.X, (int)point.Y, (int)PixelsToUnitSquares, (int)PixelsToUnitSquares);\r
+ }\r
}\r
+\r
+ #endregion\r
+\r
+\r
+ #region Private Variables\r
+\r
+ Modal mData;\r
+ View mView;\r
+\r
+ #endregion\r
}\r
}\r
using System.Collections.Generic;\r
using System.Linq;\r
using System.Runtime.Serialization;\r
-using System.Text.RegularExpressions;\r
using Microsoft.Xna.Framework;\r
using Microsoft.Xna.Framework.Content;\r
using Microsoft.Xna.Framework.Graphics;\r
/// </summary>\r
public class MapReader : ContentTypeReader<Map>\r
{\r
+ #region Public Exceptions\r
+\r
+ /// <summary>\r
+ /// This exception is thrown during the loading of a map if any\r
+ /// part of the map file is inconsistent with the expected format\r
+ /// and order.\r
+ /// </summary>\r
public class ParserException : System.ApplicationException\r
{\r
- public ParserException()\r
- {\r
- }\r
+ public ParserException() {}\r
\r
public ParserException(string message) :\r
- base(message)\r
- {\r
- }\r
+ base(message) {}\r
\r
public ParserException(string message, System.Exception inner) :\r
- base(message, inner)\r
- {\r
- }\r
+ base(message, inner) {}\r
\r
protected ParserException(SerializationInfo info, StreamingContext context) :\r
- base(info, context)\r
- {\r
- }\r
+ base(info, context) {}\r
}\r
\r
- ContentReader mInput;\r
- int mLineNumber = 0;\r
- int mExpectedNumberOfLines;\r
+ #endregion\r
\r
- Map.Data mData;\r
\r
+ #region Protected Methods\r
\r
protected override Map Read(ContentReader input, Map existingInstance)\r
{\r
- mInput = input;\r
- mExpectedNumberOfLines = mInput.ReadInt32();\r
-\r
- ReadData();\r
-\r
- return new Map(mData);\r
+ mInput = new LineReader(input);\r
+ ReadSectionHeaders();\r
+ return new Map(mMetadata, mGrid, mEntities);\r
}\r
\r
+ #endregion\r
\r
- #region Private Reading Methods\r
- \r
- string ReadLine()\r
- {\r
- return mInput.ReadString();\r
- }\r
\r
- void ReadData()\r
+ #region Private Methods\r
+\r
+ void ReadSectionHeaders()\r
{\r
- mData = new Map.Data();\r
+ mMetadata = new Map.Metadata();\r
\r
- while (mLineNumber < mExpectedNumberOfLines)\r
+ while (!mInput.End)\r
{\r
- string line = ReadLine();\r
- mLineNumber++;\r
+ string line = mInput.ReadLine();\r
\r
while (line != null)\r
{\r
}\r
else\r
{\r
- ThrowException("Unknown section", section);\r
+ throw new ParserException("Unexpected section on line " + mInput.LineNumber + ": " + section);\r
}\r
}\r
else\r
{\r
- ThrowException("Unexpected text", line);\r
+ throw new ParserException("Unexpected text on line " + mInput.LineNumber + ": " + line);\r
}\r
}\r
}\r
\r
string ReadMetadataSection()\r
{\r
- while (mLineNumber < mExpectedNumberOfLines)\r
+ while (!mInput.End)\r
{\r
- string line = ReadLine();\r
- mLineNumber++;\r
-\r
+ string line = mInput.ReadLine();\r
if (!IsLineSignificant(line)) continue;\r
\r
string[] pair = Parse.KeyValuePair(line);\r
{\r
if (pair[0] == "type")\r
{\r
- object type = Parse.Constant<Map.Type>(pair[1]);\r
- if (type != null)\r
+ Map.Type type = Parse.Constant<Map.Type>(pair[1]);\r
+ if (type != default(Map.Type))\r
{\r
- mData.Type = (Map.Type)type;\r
+ mMetadata.Type = type;\r
}\r
else\r
{\r
- ThrowException("Invalid type", pair[1]);\r
+ throw new ParserException("Unexpected type on line " + mInput.LineNumber + ": " + pair[1]);\r
}\r
}\r
else if (pair[0] == "dimensions")\r
Point? dimensions = Parse.Coordinates(pair[1]);\r
if (dimensions != null)\r
{\r
- mData.Dimensions = dimensions.Value;\r
- if (mData.Dimensions.X <= 0 || mData.Dimensions.Y <= 0)\r
+ mMetadata.GridWidth = dimensions.Value.X;\r
+ mMetadata.GridHeight = dimensions.Value.Y;\r
+ if (mMetadata.GridWidth <= 0 || mMetadata.GridHeight <= 0)\r
{\r
- ThrowException("Invalid dimensions", pair[1]);\r
+ throw new ParserException("Invalid dimensions on line " + mInput.LineNumber + ": " + pair[1]);\r
}\r
}\r
else\r
{\r
- ThrowException("Invalid value", pair[1]);\r
+ throw new ParserException("Unexpected value on line " + mInput.LineNumber + ": " + pair[1]);\r
}\r
}\r
else if (pair[0] == "tileset")\r
string tileset = Parse.String(pair[1]);\r
if (tileset != null)\r
{\r
- mData.Tileset = tileset;\r
+ mMetadata.Tileset = tileset;\r
}\r
else\r
{\r
- ThrowException("Invalid tileset", pair[1]);\r
+ throw new ParserException("Unexpected tileset on line " + mInput.LineNumber + ": " + pair[1]);\r
}\r
}\r
else if (pair[0] == "numplayers")\r
{\r
- int[] numPlayers = Parse.Range(pair[1]);\r
- if (numPlayers != null)\r
+ string[] list = Parse.List(pair[1]);\r
+ if (list != null)\r
{\r
- mData.MinNumPlayers = numPlayers[0];\r
- mData.MaxNumPlayers = numPlayers[1];\r
- if (mData.MinNumPlayers <= 0 || mData.MaxNumPlayers <= 0 ||\r
- mData.MinNumPlayers > mData.MaxNumPlayers)\r
+ foreach (string atom in list)\r
+ {\r
+ int[] range = Parse.Range(atom);\r
+ if (range != null)\r
+ {\r
+ for (int i = range[0]; i <= range[1]; i++)\r
+ {\r
+ mMetadata.NumPlayers.Add(i);\r
+ }\r
+ continue;\r
+ }\r
+ int? integer = Parse.Integer(atom);\r
+ if (integer != null)\r
+ {\r
+ mMetadata.NumPlayers.Add(integer.Value);\r
+ continue;\r
+ }\r
+\r
+ throw new ParserException("Unexpected atom on line " + mInput.LineNumber + ": " + atom);\r
+ }\r
+ if (mMetadata.NumPlayers.Count == 0)\r
{\r
- ThrowException("Invalid range", pair[1]);\r
+ throw new ParserException("No numbers given on line " + mInput.LineNumber + ": " + pair[1]);\r
}\r
}\r
else\r
{\r
- ThrowException("Invalid value", pair[1]);\r
+ throw new ParserException("Unexpected value on line " + mInput.LineNumber + ": " + pair[1]);\r
}\r
}\r
else if (pair[0] == "author")\r
string author = Parse.String(pair[1]);\r
if (author != null)\r
{\r
- mData.Author = author;\r
+ mMetadata.Author = author;\r
}\r
else\r
{\r
- ThrowException("Invalid value", pair[1]);\r
+ throw new ParserException("Unexpected value on line " + mInput.LineNumber + ": " + pair[1]);\r
}\r
}\r
else if (pair[0] == "levelname")\r
string level = Parse.String(pair[1]);\r
if (level != null)\r
{\r
- mData.Name = level;\r
+ mMetadata.Name = level;\r
}\r
else\r
{\r
- ThrowException("Invalid value", pair[1]);\r
+ throw new ParserException("Unexpected value on line " + mInput.LineNumber + ": " + pair[1]);\r
}\r
}\r
else\r
{\r
- Console.WriteLine("Unimplemented key: " + pair[0]);\r
+ throw new ParserException("Unexpected key on line " + mInput.LineNumber + ": " + pair[0]);\r
}\r
}\r
else\r
\r
string ReadMapTableSection()\r
{\r
- if (mData.Dimensions.X == 0 || mData.Dimensions.Y == 0)\r
+ if (mMetadata == null || mMetadata.GridWidth == 0 || mMetadata.GridHeight == 0)\r
{\r
- ThrowException("Unexpected section", "You must define the map dimensions before this section.");\r
+ throw new ParserException("Unexpected section on line " + mInput.LineNumber +\r
+ ": You must define the map dimensions before this section.");\r
}\r
\r
- mData.Grid = new char[mData.Dimensions.X, mData.Dimensions.Y];\r
+ mGrid = new char[mMetadata.GridWidth, mMetadata.GridHeight];\r
\r
int y;\r
- for (y = 0; y < mData.Dimensions.Y && mLineNumber < mExpectedNumberOfLines; y++)\r
+ for (y = 0; y < mMetadata.GridHeight && !mInput.End; y++)\r
{\r
- string line = ReadLine();\r
- mLineNumber++;\r
+ string line = mInput.ReadLine();\r
\r
- if (line.Length < mData.Dimensions.X)\r
+ if (line.Length < mMetadata.GridWidth)\r
{\r
- ThrowException("Not enough characters", "Expecting " + mData.Dimensions.X + " characters.");\r
+ throw new ParserException("Unexpected EOL on line " + mInput.LineNumber +\r
+ ": The number of characters should match the width dimension (" + mMetadata.GridWidth + ").");\r
}\r
\r
- for (int x = 0; x < mData.Dimensions.X; x++)\r
+ for (int x = 0; x < mMetadata.GridWidth; x++)\r
{\r
- mData.Grid[x, y] = line[x];\r
+ mGrid[x, y] = line[x];\r
}\r
}\r
\r
- if (y < mData.Dimensions.Y)\r
+ if (y < mMetadata.GridHeight)\r
{\r
- ThrowException("Unexpected ", "");\r
+ throw new ParserException("Unexpected EOF on line " + mInput.LineNumber +\r
+ ": The number of lines in this section should match the height dimension (" + mMetadata.GridHeight + ").");\r
}\r
\r
return null;\r
\r
string ReadEntitySection(char entity)\r
{\r
- while (mLineNumber < mExpectedNumberOfLines)\r
+ Dictionary<string, string> pairs = new Dictionary<string, string>();\r
+ mEntities[entity] = pairs;\r
+\r
+ while (!mInput.End)\r
{\r
- string line = ReadLine();\r
- mLineNumber++;\r
+ string line = mInput.ReadLine();\r
\r
string[] pair = Parse.KeyValuePair(line);\r
if (pair != null)\r
{\r
- // TODO\r
+ pairs[pair[0]] = pair[1];\r
}\r
else\r
{\r
return null;\r
}\r
\r
- #endregion\r
-\r
-\r
- #region Private Methods\r
\r
bool IsLineSignificant(string line)\r
{\r
- if (line.Length == 0 || Regex.IsMatch(line, @"^;|^\s*$")) return false;\r
+ if (line.Trim().Length == 0 || Parse.IniComment(line) != null) return false;\r
return true;\r
}\r
\r
- void ThrowException(string problem, string text)\r
+ #endregion\r
+\r
+\r
+ #region Private Types\r
+\r
+ /// <summary>\r
+ /// This private class wraps around ContentReader to make it more\r
+ /// convenient to use it as an input stream reader.\r
+ /// </summary>\r
+ class LineReader\r
{\r
- throw new ParserException(problem + " on line " + mLineNumber + ": " + text);\r
+ ContentReader mInput;\r
+ int mLineNumber = 0;\r
+ int mExpectedNumberOfLines;\r
+\r
+ public LineReader(ContentReader input)\r
+ {\r
+ mInput = input;\r
+ mExpectedNumberOfLines = mInput.ReadInt32();\r
+ }\r
+\r
+ public string ReadLine()\r
+ {\r
+ mLineNumber++;\r
+ return mInput.ReadString();\r
+ }\r
+\r
+ public int LineNumber { get { return mLineNumber; } }\r
+\r
+ public bool End { get { return mLineNumber >= mExpectedNumberOfLines; } }\r
}\r
\r
#endregion\r
+\r
+\r
+ #region Private Variables\r
+\r
+ Map.Metadata mMetadata;\r
+ char[,] mGrid;\r
+ Dictionary<char, Dictionary<string, string>> mEntities = new Dictionary<char, Dictionary<string, string>>();\r
+\r
+ LineReader mInput;\r
+\r
+ #endregion\r
}\r
}\r
return null;\r
}\r
\r
+ /// <summary>\r
+ /// Parses a comment of an INI file.\r
+ /// </summary>\r
+ /// <param name="line">Text.</param>\r
+ /// <returns>The comment.</returns>\r
+ public static string IniComment(string line)\r
+ {\r
+ Match match = Regex.Match(line, @"^;\s*(.*)\s*$");\r
+ if (match.Success) return match.Groups[1].Value;\r
+ return null;\r
+ }\r
+\r
/// <summary>\r
/// Parses a key-value pair.\r
/// </summary>\r
// FIXME: This may barf all over itself if there are nested parentheses, doublequotes, brackets, etc.\r
foreach (Match match in matches)\r
{\r
- Console.WriteLine("matched: " + match.Value);\r
list.Add(match.Value);\r
}\r
\r
+\r
+// DEBUG: for map testing\r
+//#define MAP_TESTING\r
+\r
using System;\r
using System.Collections.Generic;\r
using System.Linq;\r
IScreenManager screenManager;\r
IDeterministicGame deterministicGame;\r
\r
+#if MAP_TESTING\r
+ Map map;\r
+#endif\r
+\r
public XnaGame()\r
{\r
graphics = new GraphicsDeviceManager(this);\r
\r
screenManager.LoadContent(Content, graphics);\r
deterministicGame.LoadContent(Content);\r
+\r
+#if MAP_TESTING\r
+ map = Content.Load<Map>("Maps/sandbox");\r
+ Map.DefaultTile = Content.Load<Texture2D>("default");\r
+ map.CenterCell = new Vector2(7, 7);\r
+#endif\r
}\r
\r
/// <summary>\r
\r
spriteBatch.Begin();\r
networkGame.Draw(gameTime, spriteBatch);\r
+#if MAP_TESTING\r
+ map.Draw(spriteBatch);\r
+#endif\r
spriteBatch.End();\r
\r
base.Draw(gameTime);\r