/// <summary> /// Draws a single layer of the map /// </summary> /// <param name="spriteBatch">The SpriteBatch to use to render the layer.</param> /// <param name="tileLayer">The layer to draw.</param> /// <param name="gameCamera">The camera to use for positioning.</param> /// <param name="offset">A pixel amount to offset the tile positioning by</param> /// <param name="alpha">Layer opacity.</param> /// <param name="color">The color to use when drawing.</param> public void DrawLayer(SpriteBatch spriteBatch, Layer layer, Camera gameCamera, Vector2 offset, float alpha, Color color) { if (!layer.Visible) return; TileLayer tileLayer = layer as TileLayer; if (tileLayer != null) { Rectangle worldArea = new Rectangle((int)gameCamera.Position.X - (gameCamera.Width+200), (int)gameCamera.Position.Y - (int)(gameCamera.Height*1.5), (gameCamera.Width *2)+400, gameCamera.Height*3); // figure out the min and max tile indices to draw int minX = Math.Max((int)Math.Floor((float)worldArea.Left / TileWidth), 0); int maxX = Math.Min((int)Math.Ceiling((float)worldArea.Right / TileWidth), Width); int minY = Math.Max((int)Math.Floor((float)worldArea.Top / TileHeight), 0); int maxY = Math.Min((int)Math.Ceiling((float)worldArea.Bottom / TileHeight), Height); for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { //if ((new Vector2((x * TileWidth) + (TileWidth/2), (y * TileHeight) + (TileHeight/2)) - new Vector2(worldArea.Center.X, worldArea.Center.Y)).Length() < gameCamera.Width * 3f) //{ Tile tile = tileLayer.Tiles[x, y]; if (tile == null) continue; // - tile.Source.Height + TileHeight; Rectangle r = new Rectangle(x * TileWidth, y * TileHeight, tile.Source.Width, tile.Source.Height); spriteBatch.Draw(tile.Texture, r, tile.Source, color); //} } } } }
/// <summary> /// Draws a single layer as shadows, by layer name /// </summary> /// <param name="spriteBatch">The SpriteBatch to use to render the layer.</param> /// <param name="layerName">The name of the layer to draw.</param> /// <param name="gameCamera">The camera to use for positioning.</param> /// <param name="shadowOffset">Pixel amount to offset the shadowing by.</param> /// <param name="alpha">Shadow opacity</param> //public void DrawLayer(SpriteBatch spriteBatch, string layerName, Camera gameCamera, Vector2 shadowOffset, float alpha) //{ // var l = GetLayer(layerName); // if (l == null) // return; // if (!l.Visible) // return; // TileLayer tileLayer = l as TileLayer; // if (tileLayer != null) // { // //for (float mult = 0f; mult < 1f; mult += 0.1f) // //{ // DrawLayer(spriteBatch, l, gameCamera, shadowOffset, alpha, Color.Black, false); // //DrawLayer(spriteBatch, l, gameCamera, shadowOffset, alpha, Color.Black); // //} // //DrawLayer(spriteBatch, l, gameCamera, shadowOffset * 0.5f, alpha * 0.75f, Color.Black); // //DrawLayer(spriteBatch, l, gameCamera, shadowOffset * 0.75f, alpha * 0.5f, Color.Black); // //DrawLayer(spriteBatch, l, gameCamera, shadowOffset, alpha *0.25f, Color.Black); // } //} /// <summary> /// Draws a single layer of the map /// </summary> /// <param name="spriteBatch">The SpriteBatch to use to render the layer.</param> /// <param name="tileLayer">The layer to draw.</param> /// <param name="gameCamera">The camera to use for positioning.</param> /// <param name="offset">A pixel amount to offset the tile positioning by</param> /// <param name="alpha">Layer opacity.</param> /// <param name="color">The color to use when drawing.</param> public void DrawLayer(SpriteBatch spriteBatch, Layer layer, Camera gameCamera, LightingEngine lightingEngine, Color color) { if (!layer.Visible) return; TileLayer tileLayer = layer as TileLayer; if (tileLayer != null) { Rectangle worldArea = new Rectangle((int)((gameCamera.Position.X - (int)(((float)gameCamera.Width)))), (int)((gameCamera.Position.Y - (int)(((float)gameCamera.Height)))), (int)((gameCamera.Width)*2), (int)((gameCamera.Height) *2)); //Rectangle worldArea = new Rectangle(0, (int)gameCamera.Position.Y - (int)(((float)gameCamera.Height) * (2f-scale)), TileWidth * Width, (int)(((float)gameCamera.Height*2 ) * (3f-(2f*scale)))); // figure out the min and max tile indices to draw worldArea.Inflate((int)((gameCamera.Width / gameCamera.Zoom) - gameCamera.Width), (int)((gameCamera.Height / gameCamera.Zoom) - gameCamera.Height)); int minX = Math.Max((int)Math.Floor((float)worldArea.Left / TileWidth), 0); int maxX = Math.Min((int)Math.Ceiling((float)worldArea.Right / TileWidth), Width); int minY = Math.Max((int)Math.Floor((float)worldArea.Top / TileHeight), 0); int maxY = Math.Min((int)Math.Ceiling((float)worldArea.Bottom / TileHeight), Height); //minX = 0; //maxX = 1000; //minY = 0; //maxY = 1000; for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { //if ((new Vector2((x * TileWidth) + (TileWidth / 2), (y * TileHeight) + (TileHeight / 2)) - new Vector2(worldArea.Center.X, worldArea.Center.Y)).Length() < gameCamera.Width * 0.75) //{ Tile tile = tileLayer.Tiles[x, y]; if (tile == null) continue; if (AnimFrame > 0 && tile.Properties.Contains("Anim")) { tile = TileSetDictionary["ts" + (AnimFrame + 1)][TileSetDictionary["ts1"].IndexOf(tile)]; } // if (tile.Properties.Contains("Anim")) tile = Tiles.Where(t => t!=null && t.Properties.Contains("Anim") && t.Properties["Anim"] == tile.Properties["Anim"] + AnimFrame).First(); // - tile.Source.Height + TileHeight; //Rectangle r = new Rectangle(x * TileWidth, y * TileHeight, tile.Source.Width, tile.Source.Height); spriteBatch.Draw(tile.Texture, new Vector2((x * TileWidth), (y * TileHeight)), tile.Source, color==Color.White?lightingEngine.CurrentSunColor:color); //if (!AStarWorld.PositionIsFree(new AStar.Point3D(x, y, 0))) // spriteBatch.Draw(tile.Texture, new Vector2((x * TileWidth), (y * TileHeight)), new Rectangle(0,0,100,100), Color.Red); //} } } } }
/// <summary> /// Draws a single layer as shadows, by layer name /// </summary> /// <param name="spriteBatch">The SpriteBatch to use to render the layer.</param> /// <param name="layerName">The name of the layer to draw.</param> /// <param name="gameCamera">The camera to use for positioning.</param> /// <param name="shadowOffset">Pixel amount to offset the shadowing by.</param> /// <param name="alpha">Shadow opacity</param> //public void DrawLayer(SpriteBatch spriteBatch, string layerName, Camera gameCamera, Vector2 shadowOffset, float alpha) //{ // var l = GetLayer(layerName); // if (l == null) // return; // if (!l.Visible) // return; // TileLayer tileLayer = l as TileLayer; // if (tileLayer != null) // { // //for (float mult = 0f; mult < 1f; mult += 0.1f) // //{ // DrawLayer(spriteBatch, l, gameCamera, shadowOffset, alpha, Color.Black, false); // //DrawLayer(spriteBatch, l, gameCamera, shadowOffset, alpha, Color.Black); // //} // //DrawLayer(spriteBatch, l, gameCamera, shadowOffset * 0.5f, alpha * 0.75f, Color.Black); // //DrawLayer(spriteBatch, l, gameCamera, shadowOffset * 0.75f, alpha * 0.5f, Color.Black); // //DrawLayer(spriteBatch, l, gameCamera, shadowOffset, alpha *0.25f, Color.Black); // } //} /// <summary> /// Draws a single layer of the map /// </summary> /// <param name="spriteBatch">The SpriteBatch to use to render the layer.</param> /// <param name="tileLayer">The layer to draw.</param> /// <param name="gameCamera">The camera to use for positioning.</param> /// <param name="offset">A pixel amount to offset the tile positioning by</param> /// <param name="alpha">Layer opacity.</param> /// <param name="color">The color to use when drawing.</param> public void DrawLayer(SpriteBatch spriteBatch, Layer layer, Camera gameCamera, Color color, bool silhouette, float scale, Vector2 offset) { if (!layer.Visible) return; TileLayer tileLayer = layer as TileLayer; if (tileLayer != null) { Rectangle worldArea = new Rectangle((int)gameCamera.Position.X - (int)(((float)gameCamera.Width *2f)/scale) - (int)offset.X, (int)gameCamera.Position.Y - (int)(((float)gameCamera.Height*2)/scale), (int)((gameCamera.Width * 4)/scale), (int)((gameCamera.Height*4)/scale)); //Rectangle worldArea = new Rectangle(0, (int)gameCamera.Position.Y - (int)(((float)gameCamera.Height) * (2f-scale)), TileWidth * Width, (int)(((float)gameCamera.Height*2 ) * (3f-(2f*scale)))); // figure out the min and max tile indices to draw int minX = Math.Max((int)Math.Floor((float)worldArea.Left / TileWidth), 0); int maxX = Math.Min((int)Math.Ceiling((float)worldArea.Right / TileWidth), Width); int minY = Math.Max((int)Math.Floor((float)worldArea.Top / TileHeight), 0); int maxY = Math.Min((int)Math.Ceiling((float)worldArea.Bottom / TileHeight), Height); for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { //if ((new Vector2((x * TileWidth) + (TileWidth / 2), (y * TileHeight) + (TileHeight / 2)) - new Vector2(worldArea.Center.X, worldArea.Center.Y)).Length() < gameCamera.Width * 0.75) //{ Tile tile = tileLayer.Tiles[x, y]; if (tile == null) continue; // - tile.Source.Height + TileHeight; Rectangle r = new Rectangle((int)(offset.X) + (x * TileWidth), y * TileHeight, tile.Source.Width, tile.Source.Height); spriteBatch.Draw(!silhouette ? tile.Texture : tile.WhiteTexture, r, tile.Source, color); //} } } } }
//private Layer collisionLayer; internal Map(ContentReader reader) { // read in the basic map information Version = new Version(reader.ReadString()); Orientation = (Orientation)reader.ReadByte(); Width = reader.ReadInt32(); Height = reader.ReadInt32(); TileWidth = reader.ReadInt32(); TileHeight = reader.ReadInt32(); Properties = new PropertyCollection(); Properties.Read(reader); // create a list for our tiles List <Tile> tiles = new List <Tile>(); Tiles = new Collection <Tile>(tiles); // read in each tile set int numTileSets = reader.ReadInt32(); for (int i = 0; i < numTileSets; i++) { // get the id and texture int firstId = reader.ReadInt32(); string tilesetName = reader.ReadString(); bool collisionSet = reader.ReadBoolean(); Texture2D texture = reader.ReadExternalReference <Texture2D>(); Texture2D whiteTexture = null;// reader.ReadExternalReference<Texture2D>(); // Read in color data for collision purposes // You'll probably want to limit this to just the tilesets that are used for collision // I'm checking for the name of my tileset that contains wall tiles // Color data takes up a fair bit of RAM Color[] collisionData = null; bool[] collisionBitData = null; if (collisionSet) { collisionData = new Color[texture.Width * texture.Height]; collisionBitData = new bool[texture.Width * texture.Height]; texture.GetData <Color>(collisionData); for (int col = 0; col < collisionData.Length; col++) { if (collisionData[col].A > 0) { collisionBitData[col] = true; } } collisionData = null; } // read in each individual tile int numTiles = reader.ReadInt32(); for (int j = 0; j < numTiles; j++) { int id = firstId + j; Rectangle source = reader.ReadObject <Rectangle>(); PropertyCollection props = new PropertyCollection(); props.Read(reader); Tile t = new Tile(texture, whiteTexture, source, props, collisionBitData, id); while (id >= tiles.Count) { tiles.Add(null); } tiles.Insert(id, t); } } // read in all the layers List <Layer> layers = new List <Layer>(); Layers = new ReadOnlyCollection <Layer>(layers); int numLayers = reader.ReadInt32(); for (int i = 0; i < numLayers; i++) { Layer layer = null; // read generic layer data string type = reader.ReadString(); string name = reader.ReadString(); int width = reader.ReadInt32(); int height = reader.ReadInt32(); bool visible = reader.ReadBoolean(); float opacity = reader.ReadSingle(); PropertyCollection props = new PropertyCollection(); props.Read(reader); // using the type, figure out which object to create if (type == "layer") { int[] data = reader.ReadObject <int[]>(); layer = new TileLayer(name, width, height, visible, opacity, props, this, data); } else if (type == "objectgroup") { List <MapObject> objects = new List <MapObject>(); // read in all of our objects int numObjects = reader.ReadInt32(); for (int j = 0; j < numObjects; j++) { string objName = reader.ReadString(); string objType = reader.ReadString(); Rectangle objLoc = reader.ReadObject <Rectangle>(); List <Point> objPoints = reader.ReadObject <List <Point> >(); PropertyCollection objProps = new PropertyCollection(); objProps.Read(reader); objects.Add(new MapObject(objName, objType, objLoc, objPoints, objProps)); } layer = new MapObjectLayer(name, width, height, visible, opacity, props, objects); } else { throw new Exception("Invalid type: " + type); } layers.Add(layer); namedLayers.Add(name, layer); } }
/// <summary> /// Draws a single layer of the map /// </summary> /// <param name="spriteBatch">The SpriteBatch to use to render the layer.</param> /// <param name="tileLayer">The layer to draw.</param> /// <param name="gameCamera">The camera to use for positioning.</param> /// <param name="offset">A pixel amount to offset the tile positioning by</param> /// <param name="alpha">Layer opacity.</param> /// <param name="color">The color to use when drawing.</param> public void DrawLayer(SpriteBatch spriteBatch, Layer layer, Camera gameCamera, Vector2 offset, float alpha, Color color) { if (!layer.Visible) return; TileLayer tileLayer = layer as TileLayer; if (tileLayer != null) { // Calculate scroll offset Vector2 scrollOffset = Vector2.One; if (tileLayer.Properties.Contains("ScrollOffsetX")) scrollOffset.X = float.Parse(tileLayer.Properties["ScrollOffsetX"]); if (tileLayer.Properties.Contains("ScrollOffsetY")) scrollOffset.Y = float.Parse(tileLayer.Properties["ScrollOffsetY"]); Vector2 drawPos = new Vector2(-TileWidth, -TileHeight); // Calculate remainders drawPos.X -= (int)(gameCamera.Position.X * scrollOffset.X) % TileWidth; drawPos.Y -= (int)(gameCamera.Position.Y * scrollOffset.Y) % TileHeight; // Add shadow offset drawPos += offset; // Convert the draw position to ints to avoid odd artifacting drawPos.X = (int)drawPos.X; drawPos.Y = (int)drawPos.Y; float originalX = drawPos.X; for (int y = (int)((gameCamera.Position.Y * scrollOffset.Y) / TileHeight)-1; y < (((gameCamera.Position.Y * scrollOffset.Y) + gameCamera.Height) / TileHeight)+1; y++) { for (int x = (int)((gameCamera.Position.X * scrollOffset.X) / TileWidth)-1; x < (((gameCamera.Position.X * scrollOffset.X) + gameCamera.Width) / TileWidth)+1; x++) { if (x >= 0 && x < tileLayer.Width && y >= 0 && y < tileLayer.Height) { Tile tile = tileLayer.Tiles[x, y]; if (tile != null && tile.Texture!=null) { spriteBatch.Draw(tile.Texture, drawPos, tile.Source, color * alpha); } } drawPos.X += TileWidth; } drawPos.X = originalX; drawPos.Y += TileHeight; } } }
/// <summary> /// Draws an area of the map defined in world space (pixel) coordinates. /// </summary> /// <param name="spriteBatch">The SpriteBatch to use to render the map.</param> /// <param name="worldArea">The area of the map to draw in world coordinates.</param> public void DrawLayer(SpriteBatch spriteBatch, Layer layer, Rectangle worldArea) { if (spriteBatch == null) throw new ArgumentNullException("spriteBatch"); if (Orientation == Orientation.Orthogonal) { // figure out the min and max tile indices to draw int minX = Math.Max((int)Math.Floor((float)worldArea.Left / TileWidth), 0); int maxX = Math.Min((int)Math.Ceiling((float)worldArea.Right / TileWidth), Width); int minY = Math.Max((int)Math.Floor((float)worldArea.Top / TileHeight), 0); int maxY = Math.Min((int)Math.Ceiling((float)worldArea.Bottom / TileHeight), Height); if (!layer.Visible) return; TileLayer tileLayer = layer as TileLayer; if (tileLayer != null) { for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { Tile tile = tileLayer.Tiles[x, y]; if (tile == null) continue; Rectangle r = new Rectangle(x * TileWidth, y * TileHeight - tile.Source.Height + TileHeight, tile.Source.Width, tile.Source.Height); tile.DrawOrthographic(spriteBatch, r, tileLayer.Opacity); } } } } else { throw new NotSupportedException("TiledLib does not have built in support for rendering isometric tile maps."); } }