/// <summary> /// Constructs a cell. /// </summary> /// <param name="map">The map that this cell belongs to.</param> /// <param name="quadCoords">The coordinates of this cell inside it's parent quadratic tile.</param> public Cell(MapStructure map, QuadTile quadTile, RCIntVector quadCoords) { if (map == null) { throw new ArgumentNullException("map"); } if (quadTile == null) { throw new ArgumentNullException("quadTile"); } if (quadCoords == RCIntVector.Undefined) { throw new ArgumentNullException("quadCoords"); } if (quadCoords.X < 0 || quadCoords.X >= MapStructure.NAVCELL_PER_QUAD || quadCoords.Y < 0 || quadCoords.Y >= MapStructure.NAVCELL_PER_QUAD) { throw new ArgumentOutOfRangeException("mapCoords"); } this.parentMap = map; this.parentQuadTile = quadTile; this.quadCoords = quadCoords; this.walkabilityFlag = new Stack <bool>(); this.buildabilityFlag = new Stack <bool>(); this.groundLevel = new Stack <int>(); this.isLocked = false; this.mapCoords = this.parentQuadTile.MapCoords * (new RCIntVector(MapStructure.NAVCELL_PER_QUAD, MapStructure.NAVCELL_PER_QUAD)) + this.quadCoords; this.neighbours = new Cell[8]; this.detachedNeighbours = new List <Tuple <Cell, MapDirection> >(); this.parentIsoTile = null; /// will be set later this.isoIndices = RCIntVector.Undefined; /// will be set later }
/// <summary> /// Sets the given quadratic tile as a cutting quadratic tile for this isometric tile. /// </summary> /// <param name="quadTile">The quadratic tile to set.</param> public void SetCuttingQuadTile(QuadTile quadTile) { if (quadTile == null) { throw new ArgumentNullException("quadTile"); } this.cuttingQuadTiles.Add(quadTile); }
/// <summary> /// Detaches the given terrain object from the map structure. /// </summary> /// <param name="terrainObj">The terrain object to be detached.</param> /// <exception cref="InvalidOperationException">If the given terrain object was not attached to this map.</exception> public void DetachTerrainObject(ITerrainObject terrainObj) { if (!this.terrainObjects.Remove(terrainObj)) { throw new InvalidOperationException("The given terrain object was not attached to this map!"); } for (int x = 0; x < terrainObj.Type.QuadraticSize.X; x++) { for (int y = 0; y < terrainObj.Type.QuadraticSize.Y; y++) { IQuadTile quadTile = terrainObj.GetQuadTile(new RCIntVector(x, y)); if (quadTile != null) { QuadTile quadTileObj = this.mapStructure.GetQuadTile(quadTile.MapCoords); quadTileObj.DetachTerrainObject(); } } } }
/// <summary> /// Sets the given quadratic tile as a neighbour of this quadratic tile in the given direction. /// </summary> /// <param name="neighbour">The quadratic tile to be set as a neighbour of this.</param> /// <param name="direction">The direction of the new neighbour.</param> public void SetNeighbour(QuadTile neighbour, MapDirection direction) { if (neighbour == null) { throw new ArgumentNullException("neighbour"); } if (neighbour.parentMap != this.parentMap) { throw new InvalidOperationException("Neighbour quadratic tiles must have the same parent map!"); } if (this.parentMap.Status != MapStructure.MapStatus.Initializing) { throw new InvalidOperationException(string.Format("Invalid operation! Map status: {0}", this.parentMap.Status)); } if (this.neighbours[(int)direction] != null) { throw new InvalidOperationException(string.Format("Neighbour in direction {0} already set!", direction)); } this.neighbours[(int)direction] = neighbour; }
/// <summary> /// Initializes the structure of this map. /// </summary> public void Initialize() { if (this.status != MapStatus.Initializing) { throw new InvalidOperationException(string.Format("Invalid operation! Map status: {0}", this.status)); } /// Create the quadratic and isometric tiles. RCIntVector navCellPerQuadVect = new RCIntVector(NAVCELL_PER_QUAD, NAVCELL_PER_QUAD); for (int col = 0; col < MAX_MAPSIZE; col++) { for (int row = 0; row < MAX_MAPSIZE; row++) { /// Calculate the coordinates of the isometric tiles that contain the corner cells of the current quadratic tile. /// Order of the cornerIsoCoords array: NorthWest, NorthEast, SouthEast, SouthWest. RCIntVector quadTileCoords = new RCIntVector(col, row); RCIntVector[] cornerIsoCoords = new RCIntVector[4] { MapStructure.NavCellIsoTransform.TransformAB(quadTileCoords * navCellPerQuadVect + new RCIntVector(0, 0)).Round(), MapStructure.NavCellIsoTransform.TransformAB(quadTileCoords * navCellPerQuadVect + new RCIntVector(NAVCELL_PER_QUAD - 1, 0)).Round(), MapStructure.NavCellIsoTransform.TransformAB(quadTileCoords * navCellPerQuadVect + new RCIntVector(NAVCELL_PER_QUAD - 1, NAVCELL_PER_QUAD - 1)).Round(), MapStructure.NavCellIsoTransform.TransformAB(quadTileCoords * navCellPerQuadVect + new RCIntVector(0, NAVCELL_PER_QUAD - 1)).Round() }; /// Create the isometric tiles. int isoTileACount = 0, isoTileBCount = 0; IsoTile isoTileA = null, isoTileB = null; for (int cornerIdx = 0; cornerIdx < 4; cornerIdx++) { if (isoTileA == null) { isoTileA = this.isometricTiles.ContainsKey(cornerIsoCoords[cornerIdx]) ? this.isometricTiles[cornerIsoCoords[cornerIdx]] : new IsoTile(this, cornerIsoCoords[cornerIdx]); this.isometricTiles[cornerIsoCoords[cornerIdx]] = isoTileA; isoTileACount++; } else if (cornerIsoCoords[cornerIdx] == isoTileA.MapCoords) { isoTileACount++; } else if (isoTileB == null) { isoTileB = this.isometricTiles.ContainsKey(cornerIsoCoords[cornerIdx]) ? this.isometricTiles[cornerIsoCoords[cornerIdx]] : new IsoTile(this, cornerIsoCoords[cornerIdx]); this.isometricTiles[cornerIsoCoords[cornerIdx]] = isoTileB; isoTileBCount++; } else if (cornerIsoCoords[cornerIdx] == isoTileB.MapCoords) { isoTileBCount++; } else { throw new InvalidOperationException("Unexpected case!"); } } QuadTile quadTile = new QuadTile(this, isoTileACount >= isoTileBCount ? isoTileA : isoTileB, isoTileACount < isoTileBCount ? isoTileA : isoTileB, quadTileCoords); this.quadTiles[quadTileCoords.X, quadTileCoords.Y] = quadTile; } } /// Buildup the structure of the map. this.SetIsoNeighbours(); this.SetQuadNeighbours(); this.SetNavCellNeighbours(); this.SetNavCellIsoIndices(); this.status = MapStatus.Closed; }