X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fcarfire;a=blobdiff_plain;f=CarFire%2FCarFire%2FCarFire%2FMap.cs;fp=CarFire%2FCarFire%2FCarFire%2FMap.cs;h=b61f2bbcb1eef2f8e0e556efdcff645b3daf5d63;hp=ed8c39fd1957986f0014a404d44c702ed982bfe3;hb=1393586d1e5639ac8f1e9fc8183644050dd54165;hpb=2eb9216eac3321adc2f897068396e7fb1f126089 diff --git a/CarFire/CarFire/CarFire/Map.cs b/CarFire/CarFire/CarFire/Map.cs index ed8c39f..b61f2bb 100644 --- a/CarFire/CarFire/CarFire/Map.cs +++ b/CarFire/CarFire/CarFire/Map.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Microsoft.Xna.Framework; using System.IO; -using System.Text.RegularExpressions; using System.Runtime.Serialization; using System.Diagnostics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; namespace CarFire { @@ -18,20 +18,21 @@ namespace CarFire /// public class Map { - #region Types + // DEBUG: Tilesets not implemented at all. + public static Texture2D DefaultTile; - public class Data - { - public string Author; - public string Name; - public int MinNumPlayers; - public int MaxNumPlayers; - public Point Dimensions; - public string Tileset; // TODO: this should be a tilemap object - public Type Type; - public char[,] Grid; - } - + #region Public Constants + + public const float PixelsToUnitSquares = 64.0f; + + #endregion + + + #region Public Types + + /// + /// The type of a map helps determine how the map is intended to be used. + /// public enum Type { None, @@ -39,12 +40,301 @@ namespace CarFire Battle } + /// + /// The container class for map metadata. + /// + public class Metadata + { + public string Name; + public Type Type; + public string Author; + public HashSet NumPlayers = new HashSet(); + public string Tileset; + public int GridWidth; + public int GridHeight; + } + + #endregion + + + #region Public Attributes + + /// + /// Get the name of the map. + /// + public string Name { get { return mData.Metadata.Name; } } + + /// + /// Get the type of the map. + /// + //public Type Type { get { return mData.mMetadata.Type; } } + + /// + /// Get the author of the map. + /// + public string Author { get { return mData.Metadata.Author; } } + + /// + /// Get a set of integers containing each allowable number of players. + /// + public HashSet NumPlayers { get { return mData.Metadata.NumPlayers; } } + + /// + /// Get the width of the map, in grid units. + /// + public int Width { get { return mData.Metadata.GridWidth; } } + + /// + /// Get the height of the map, in grid units. + /// + public int Height { get { return mData.Metadata.GridHeight; } } + + // TODO: This should return whatever object we end up using for tilesets. + public string Tileset { get { return mData.Metadata.Tileset; } } + + + public Vector2 CenterCell + { + get { return mView.CenterCell; } + set { mView.CenterCell = value; } + } + + #endregion + + + #region Public Methods + + /// + /// Construct a map with the provided map data. + /// + /// Map data. + public Map(Metadata metadata, char[,] grid, Dictionary> entities) + { + mData = new Modal(metadata, grid, entities); + mView = new View(mData); + } + + + /// + /// Draw a representation of the map to the screen. + /// + /// The jeewiz. + public void Draw(SpriteBatch spriteBatch) + { + mView.Draw(spriteBatch); + } + + + /// + /// Get a point in screen-space from a coordinate in gridspace. + /// + /// X-coordinate. + /// Y-coordinate. + /// Transformed point. + public Point GetPointFromCoordinates(float x, float y) + { + return mView.GetPointFromCoordinates(x, y); + } + + /// + /// Get a point in screen-space from a coordinate in gridspace. + /// + /// X,Y-coordinates. + /// Transformed point. + public Point GetPointFromCoordinates(Vector2 point) + { + return mView.GetPointFromCoordinates(point.X, point.Y); + } + + /// + /// Get a rectangle in screen-space centered around a coordinate in gridspace. + /// + /// X-coordinate. + /// Y-coordinate. + /// Transformed rectangle. + public Rectangle GetRectangleFromCoordinates(float x, float y) + { + return mView.GetRectangleFromCoordinates(x, y); + } + + /// + /// Get a rectangle in screen-space centered around a coordinate in gridspace. + /// + /// X,Y-coordinates. + /// Transformed rectangle. + public Rectangle GetRectangleFromCoordinates(Vector2 point) + { + return mView.GetRectangleFromCoordinates(point.X, point.Y); + } + + + /// + /// Determine whether or not a cell can be occupied by a game entity. + /// + /// X-coordinate. + /// Y-coordinate. + /// True if cell can be occupied, false otherwise. + public bool IsCellOpen(int x, int y) + { + return mData.IsCellOpen(x, y); + } + + /// + /// Determine whether or not a cell can be occupied by a game entity. + /// + /// X,Y-coordinates. + /// True if cell can be occupied, false otherwise. + public bool IsCellOpen(Point point) + { + return mData.IsCellOpen(point.X, point.Y); + } + + + /// + /// Get the entities loaded from the map file. + /// + /// 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() + { + return mData.Entities; + } + #endregion - public Map(Data data) + #region Private Types + + class Modal + { + Metadata mMetadata; + char[,] mGrid; + Dictionary> mEntities; + + public Modal(Metadata metadata, char[,] grid, Dictionary> entities) + { + Debug.Assert(metadata != null); + Debug.Assert(grid != null); + Debug.Assert(entities != null); + Debug.Assert(metadata.GridWidth * metadata.GridHeight == grid.Length); + + mMetadata = metadata; + mGrid = grid; + mEntities = entities; + +#if DEBUG + Console.WriteLine("Loaded map {0} of type {1} written by {2}.", + metadata.Name, + metadata.Type, + metadata.Author); +#endif + } + + + public Metadata Metadata { get { return mMetadata; } } + public Dictionary> Entities { get { return mEntities; } } + + + public bool IsCellOpen(int x, int y) + { + // TODO: Still need to define characters for types of scenery. + return mGrid[x, y] == ' '; + } + } + + class View { - Console.WriteLine("Read map " + data.Name + " of type " + data.Type + " written by " + data.Author); + Modal mData; + + public Vector2 CenterCell; + Viewport mViewport; + + + public View(Modal data) + { + Debug.Assert(data != null); + mData = data; + } + + public void Draw(SpriteBatch spriteBatch) + { + mViewport = spriteBatch.GraphicsDevice.Viewport; + + // TODO: There is no culling yet, but it runs so fast that it probably won't ever need it. + for (int y = 0; y < mData.Metadata.GridHeight; y++) + { + for (int x = 0; x < mData.Metadata.GridWidth; x++) + { + if (mData.IsCellOpen(x, y)) + { + spriteBatch.Draw(Map.DefaultTile, GetRectangleFromCoordinates(x, y), Color.White); + } + else + { + spriteBatch.Draw(Map.DefaultTile, GetRectangleFromCoordinates(x, y), Color.DarkBlue); + } + } + } + } + + /// + /// Get a matrix to transform a point from grid-space to screen coordinates. This + /// method uses the viewport to bound the edges of the map such that the camera + /// will not show anything outside of the grid. + /// + /// The point to put in the center. + /// The transformation matrix. + Matrix GetTransformation(Vector2 center) + { + float halfRatio = PixelsToUnitSquares * 0.5f; + Matrix transform = Matrix.CreateTranslation(-center.X, -center.Y, 0.0f); + transform *= Matrix.CreateScale(PixelsToUnitSquares); + transform *= Matrix.CreateTranslation(mViewport.Width * 0.5f - halfRatio, + mViewport.Height * 0.5f - halfRatio, 0.0f); + + Vector2 topLeft = Vector2.Transform(new Vector2(0.0f, 0.0f), transform); + topLeft.X = Math.Max(mViewport.X, topLeft.X); + topLeft.Y = Math.Max(mViewport.Y, topLeft.Y); + transform *= Matrix.CreateTranslation(-topLeft.X, -topLeft.Y, 0.0f); + + Vector2 bottomRight = Vector2.Transform(new Vector2((float)mData.Metadata.GridWidth, + (float)mData.Metadata.GridHeight), transform); + float right = mViewport.X + mViewport.Width; + float bottom = mViewport.Y + mViewport.Height; + bottomRight.X = Math.Min(right, bottomRight.X) - right; + bottomRight.Y = Math.Min(bottom, bottomRight.Y) - bottom; + transform *= Matrix.CreateTranslation(-bottomRight.X, -bottomRight.Y, 0.0f); + + return transform; + } + + + public Point GetPointFromCoordinates(float x, float y) + { + Matrix transform = GetTransformation(CenterCell); + Vector2 point = Vector2.Transform(new Vector2(x, y), transform); + + return new Point((int)point.X, (int)point.Y); + } + + public Rectangle GetRectangleFromCoordinates(float x, float y) + { + Matrix transform = GetTransformation(CenterCell); + Vector2 point = Vector2.Transform(new Vector2(x, y), transform); + + return new Rectangle((int)point.X, (int)point.Y, (int)PixelsToUnitSquares, (int)PixelsToUnitSquares); + } } + + #endregion + + + #region Private Variables + + Modal mData; + View mView; + + #endregion } }