public DestructableTile(Tile tile, World world, int x, int y, float maxHealth, List<IDestructionEffect> destructionEffects) : base(tile) { this.world = world; this.x = x; this.y = y; this.maxHealth = maxHealth; this.destructionEffects = destructionEffects; }
public Tile(Tile other) { this.initialEdges = new bool[4]; other.InitialEdges.CopyTo(this.initialEdges, 0); this.edges = new bool[4]; this.initialEdges.CopyTo(this.edges, 0); this.textures = new SubTexture[other.Textures.GetLength(0), other.Textures.GetLength(1)]; for (int i = 0; i < other.Textures.GetLength(0); ++i) for (int j = 0; j < other.Textures.GetLength(1); ++j) this.textures[i,j] = other.Textures[i,j]; }
private XElement TileToXElement(Tile tile, Dictionary<string, int> sheetIndex) { // Empty tiles are represented as having -1 edges. (nonsense) if (tile == null) { return new XElement("T", new XAttribute("e", -1)); } // TODO: - add Type attribute (Solid, Empty, or Custom) // and Top/Bottom/Left/RighEdge attributes when Type="Custom" // - optimize for space/time so saving/loading isn't too slow. // perhaps return a binary string (base64 or the like) int power = 0; int edges = 0; // We save the InitialEdges and let the TileMap take care of the rest. foreach (bool edge in tile.InitialEdges) { if (edge) { edges |= (int)Math.Pow(2, power); } ++power; } XElement returnVal = new XElement("T", new XAttribute("e", edges)); int z = 0; // The index into the Tile.Textures array where this SubTexture belongs. foreach (SubTexture sub in tile.Textures) { // Note: Texture2D.Name is useless normally, but the TextureService will // automatically set the Name parameter to be the asset name so they can // easily be retrieved. // "z" attribute: the index into the tile's Textures[,] array. Converted to single int to save space. // "s" attribute: the SubTextureSheet number to use. Each tilemap keeps a list of these. // "i" attribute: the index into the SubTextureSheet representing a SubTexture of this tile. if (sub != null) { returnVal.Add(new XElement("x", new XAttribute("z", z), new XAttribute("s", sheetIndex[sub.Sheet.Name]), new XAttribute("i", sub.Index))); } ++z; } // Check for special types of tiles: if (tile is DestructableTile) returnVal.Add(new XAttribute("d", ((DestructableTile)tile).MaxHealth)); return returnVal; }
private Tile TileFromXElement(XElement xelement, SubTextureSheet[] sheets, int x, int y, World world) { if (xelement.Attribute("e").Value == "-1") { return null; } Tile returnVal; SubTexture[,] subTexturesArray = new SubTexture[layerCount, subLayerCount]; IEnumerable<XElement> subTextureElements = xelement.Descendants("x"); int i = 0, j = 0; //int index = 0; // Was needed when changing format. foreach( XElement subTextureElement in subTextureElements) { i = Int32.Parse(subTextureElement.Attribute("z").Value) / SubLayerCount; j = Int32.Parse(subTextureElement.Attribute("z").Value) % SubLayerCount; SubTexture subTex = new SubTexture(sheets[Int32.Parse(subTextureElement.Attribute("s").Value)], Int32.Parse(subTextureElement.Attribute("i").Value)); subTexturesArray[i, j] = subTex; } int edgeInt; edgeInt = Int32.Parse(xelement.Attribute("e").Value); bool[] edges = new bool[4]; for (int k = 0; k < 4; ++k) { edges[k] = (edgeInt & (int)Math.Pow(2, k)) != 0; } returnVal = new Tile(subTexturesArray, edges); // Check for special tile types: bool isDestructable = (from att in xelement.Attributes() where att.Name == "d" select att).Count() > 0; if (isDestructable) { List<IDestructionEffect> effects = new List<IDestructionEffect>(); effects.Add(new ExplosionEffect()); effects.Add(new ShatterEffect()); returnVal = new DestructableTile(returnVal, world, x, y, float.Parse(xelement.Attribute("d").Value), effects); } return returnVal; }
/// <summary> /// Sets the tile at given x,y. /// Automatically removes edges of adjacent tiles. /// </summary> public void SetTile(Tile tile, int x, int y) { // Prevent useless tiles from being added: if (tile != null && tile.IsEmpty()) tile = null; Tile above = y > 0 ? tiles[x, (y - 1)] : null; Tile left = x > 0 ? tiles[(x - 1), y] : null; Tile below = y < Height - 1 ? tiles[x, (y + 1)] : null; Tile right = x < Width - 1 ? tiles[(x + 1), y] : null; // We're "removing" a tile, so we restore // adjacent tiles' adjacent edges to their initial values. if (tile == null) { if (above != null) above.BottomEdge = above.InitialBottomEdge; if (left != null) left.RightEdge = left.InitialRightEdge; if (below != null) below.TopEdge = below.InitialTopEdge; if (right != null) right.LeftEdge = right.InitialLeftEdge; } else { // Special edge cases (no pun intended): if (x == 0) // left edge of the map { tile.LeftEdge = false; } else if (x == (Width - 1)) // right edge of the map { tile.RightEdge = false; } if (y == 0) // top edge of the map { tile.TopEdge = false; } else if (y == (Height - 1)) // bottom edge of the map { tile.BottomEdge = false; } // Else, we're adding a tile, so we clear all adjacent // edges that we have solid edges for. if (above != null) { if (tile.InitialTopEdge && above.InitialBottomEdge) { tile.TopEdge = false; above.BottomEdge = false; } else { above.BottomEdge = above.InitialBottomEdge; } } if (left != null) { if (tile.InitialLeftEdge && left.InitialRightEdge) { tile.LeftEdge = false; left.RightEdge = false; } else { left.RightEdge = left.InitialRightEdge; } } if (below != null) { if (tile.InitialBottomEdge && below.InitialTopEdge) { tile.BottomEdge = false; below.TopEdge = false; } else { below.TopEdge = below.InitialTopEdge; } } if (right != null) { if (tile.InitialRightEdge && right.InitialLeftEdge) { tile.RightEdge = false; right.LeftEdge = false; } else { right.LeftEdge = right.InitialLeftEdge; } } } tiles[x, y] = tile; }
public void SetSolid(bool solidOrNot, int x, int y) { if (tiles[x, y] != null) { tiles[x, y].SetSolid(solidOrNot); } else { tiles[x, y] = new Tile(layerCount, subLayerCount); } SetTile(tiles[x, y], x, y); }
/// <summary> /// Crop this tilemap down to the minimal size needed to contain all non-null tiles in it. /// </summary> /// <returns>A Rectangle which represents the cropping area, in tile-coordinates.</returns> public Rectangle Minimize() { int xMin, xMax, yMin, yMax; xMax = yMax = 0; xMin = Width - 1; yMin = Height - 1; // Find the minimal and maximal tiles that aren't null: for (int x = 0; x < Width; ++x) { for (int y = 0; y < Height; ++y) { if (tiles[x, y] != null) { if (x > xMax) xMax = x; if (x < xMin) xMin = x; if (y > yMax) yMax = y; if (y < yMin) yMin = y; } } } // Create a new tilemap that will fit all of them: Tile[,] newTiles = new Tile[xMax - xMin+1, yMax - yMin+1]; // And copy all tiles into the new array: // NOTE: SetTile doesn't need to be used here because each tile's // edge data should be the same since we're only cropping // out nulls, which have no effect on edges. for (int xOffset = 0; xOffset < newTiles.GetLength(0); ++xOffset) { for (int yOffset = 0; yOffset < newTiles.GetLength(1); ++yOffset) { newTiles[xOffset, yOffset] = this[xMin + xOffset, yMin + yOffset]; } } tiles = newTiles; return new Rectangle(xMin, yMin, Width, Height); }
/// <summary> /// Set Textures[layerIndex, subLayerIndex] of all selected tiles to the SubTexture passed in. /// </summary> /// <param name="subTexture">The SubTexture to set the tiles to (null will clear the texture).</param> /// <param name="layerIndex">The first index into each tile's Textures array; the layer index.</param> /// <param name="subLayerIndex">The second index into each tile's Textures array; the sub-layer index.</param> public void SetSubTexture(SubTexture subTexture, int layerIndex, int subLayerIndex) { foreach (int[] tileCoord in selectedTileCoordinates) { Tile tile = TileMap[tileCoord[0], tileCoord[1]]; if (tile == null) { // We have an empty tile... if (subTexture != null) { // We need to make a new one to hold this subTexture SubTexture[,] textures = new SubTexture[TileMap.LayerCount, TileMap.SubLayerCount]; textures[layerIndex, subLayerIndex] = subTexture; tile = new Tile(textures); // TODO: set the edges to what the edge toggler says the tile's edges should be? } // Otherwise we do nothing. } else { // We have a non-empty tile, so we simply set it's subTexture directly: tile.Textures[layerIndex, subLayerIndex] = subTexture; } // Finally, we set our tile so the tileMap's edges are properly updated. TileMap.SetTile(tile, tileCoord[0], tileCoord[1]); } notifyTilePropertyComponents(); }
/// <summary> /// Set all selected tile's edges to be the list of edges passed in. /// A copy will be made so their edges aren't actually linked. /// </summary> /// <param name="edges"></param> public void SetEdges(bool[] edges) { foreach (int[] tileCoord in selectedTileCoordinates) { Tile tile = TileMap[tileCoord[0], tileCoord[1]]; if (tile == null) { if (edges[0] || edges[1] || edges[2] || edges[3]) { tile = new Tile(new SubTexture[TileMap.LayerCount, TileMap.SubLayerCount], edges); } } else { edges.CopyTo(tile.InitialEdges, 0); edges.CopyTo(tile.Edges, 0); } TileMap.SetTile(tile, tileCoord[0], tileCoord[1]); } notifyTilePropertyComponents(); }
/// <summary> /// Set all selected tiles to being either destructable or non-destructable /// based on the bool passed in. /// </summary> /// <param name="destructable"> /// Whether or not the tile is destructable; true if so, false if not. Duh. /// </param> public void SetDestructable(bool destructable) { foreach (int[] tileCoord in selectedTileCoordinates) { int x, y; x = tileCoord[0]; y = tileCoord[1]; Tile tile = TileMap[x, y]; if (tile == null) { if (destructable) { tile = new Tile(new SubTexture[TileMap.LayerCount, TileMap.SubLayerCount], new bool[] { false, false, false, false }); tile = new DestructableTile(tile, EditorScreen.World, tileCoord[0], tileCoord[1], 10.0f); } } else if (tile is DestructableTile) { if (!destructable) { tile = new Tile(tile); // A plain-vanilla tile, we're only extracting the texture and edge data. } } else { if (destructable) { tile = new DestructableTile(tile, EditorScreen.World, tileCoord[0], tileCoord[1], 10.0f); } } TileMap.SetTile(tile, x, y); } notifyTilePropertyComponents(); }