/// <summary> /// Adds edge noise to next to a give tile position /// </summary> /// <param name="row">Tile row index</param> /// <param name="column">Tile column index</param> /// <param name="rowCount">Number of rows per grid</param> /// <param name="columnCount">Number of columns per grid</param> /// <param name="tileIdValue">Edge noise tile id value</param> /// <param name="tileFlags">Tile flags</param> /// <param name="percentage">Percentage to add edge noise</param> /// <param name="allowedDirection">Direction of free tiles</param> /// <param name="map">A Representation of a grid</param> private void AddEdgeNoise(int row, int column, int rowCount, int columnCount, ushort tileIdValue, byte tileFlags, float percentage, List <Direction> allowedDirection, Tile[] map) { if (allowedDirection.Count > 0) { float calculatedPercentage = random.Next(0, 100) / 100f; while (allowedDirection.Count > 0 && percentage >= calculatedPercentage) { //replace allowedDirections int result = random.Next(0, allowedDirection.Count); if (allowedDirection[result].Axis == DirectionAxis.Horizontal) { column += allowedDirection[result].Value; } else { row += allowedDirection[result].Value; } if (TileMathHelper.IsOutOfRange(row, column, rowCount, columnCount)) { return; } allowedDirection = CheckDirections(row, column, rowCount, columnCount, map); int id = TileMathHelper.ToIndex(row, column, columnCount); if (map[id].Id == 0) { map[id] = new Tile(tileIdValue, tileFlags); } percentage -= 0.01f; calculatedPercentage = random.Next(0, 100) / 100f; } } }
/// <summary> /// Converts a pixel position into a tile index /// </summary> /// <param name="x">X position</param> /// <param name="y">Y position</param> /// <returns>Returns a tile index from flatten map array</returns> public int GetTileIndex(int x, int y) { int column = x / tileSize; int row = y / tileSize; return(TileMathHelper.ToIndex(row, column, GridColumnCount)); }
/// <summary> /// Checks whenther a tile position is free or out of range /// </summary> /// <param name="row">Row index of the tile</param> /// <param name="column">Column index of the tile</param> /// <param name="columnCount">Number of column per grid</param> /// <param name="rowCount">Number of rows per grid</param> /// <param name="map">A representation of a grid</param> /// <returns>Retruns 0 if the tile is out of range or has already a flag, otherwise 1</returns> private int CheckDirection(int row, int column, int columnCount, int rowCount, Tile[] map) { if (TileMathHelper.IsOutOfRange(row, column, rowCount, columnCount)) { return(0); } return(map[TileMathHelper.ToIndex(row, column, columnCount)].Id == 0 ? 1 : 0); }
/// <summary> /// Returns a grid position of a given tile position /// </summary> /// <param name="row">Tile row index</param> /// <param name="column">Tile column index</param> /// <param name="gridRow">Returns the grid row index</param> /// <param name="gridColumn">Returns the grid column index</param> public void ConvertTileToGridPosition(int row, int column, out int gridRow, out int gridColumn) { gridRow = (int)Math.Floor((double)row / (double)TileRowCount); gridColumn = (int)Math.Floor((double)column / (double)TileColumnCount); if (TileMathHelper.IsOutOfRange(gridRow, gridColumn, GridRowCount, GridColumnCount)) { gridRow = TileMathHelper.FixTileIndex(gridRow, GridRowCount); gridColumn = TileMathHelper.FixTileIndex(gridColumn, GridColumnCount); } }
/// <summary> /// Determine all tiles on screen based on the given viewport /// </summary> /// <param name="viewportWidth">Viewport width in pixel</param> /// <param name="viewportHeight">Viewport height in pixel</param> /// <returns>Returns a flatten byte array which represants the tiles</returns> public Tile[] GetTileMapInScreen(int viewportWidth, int viewportHeight) { ScreenWidth = viewportWidth; ScreenHeight = viewportHeight; int screenColumnCount = (viewportWidth / tileSize); int screenRowCount = (viewportHeight / tileSize); Tile[] tilesInScreen = new Tile[screenRowCount * screenColumnCount]; int posRow = tileRow + (screenRowCount / 2); int negRow = tileRow - (screenRowCount / 2); int posColumn = tileColumn + (screenColumnCount / 2); int negColumn = tileColumn - (screenColumnCount / 2); int rowIndex = 0; for (int r = negRow; r < posRow; r++) { int columnIndex = 0; for (int c = negColumn; c < posColumn; c++) { int newMapIndex = CurrentMapIndex; int realRow = r; int realColumn = c; if (TileMathHelper.IsOutOfRange(r, c, TileRowCount, TileColumnCount)) { newMapIndex = TileMathHelper.GetMapIndex(r, c, TileRowCount, TileColumnCount, newMapIndex); realRow = TileMathHelper.FixTileIndex(r, TileRowCount); realColumn = TileMathHelper.FixTileIndex(c, TileColumnCount); } //GetValues and merge if (newMapIndex < 0) { tilesInScreen[TileMathHelper.ToIndex(rowIndex, columnIndex++, screenColumnCount)] = new Tile(ushort.MaxValue, 255); int newGridRow = (int)Math.Floor((double)r / (double)TileRowCount); int newGridColumn = (int)Math.Floor((double)c / (double)TileColumnCount); GridGenerationIsSlow?.Invoke(this, new GridEventArgs(newGridRow, newGridColumn, GridRow, GridColumn, false)); } else { tilesInScreen[TileMathHelper.ToIndex(rowIndex, columnIndex++, screenColumnCount)] = maps[newMapIndex].MapSurface[TileMathHelper.ToIndex(realRow, realColumn, TileColumnCount)]; } } rowIndex++; } return(tilesInScreen); }
/// <summary> /// Initzializes a new streamed tile map /// </summary> /// <param name="spawnTileRow">Tile row index</param> /// <param name="spawnTileColumn">Tile column index</param> /// <param name="gridColumnCount">Number of grid columns</param> /// <param name="gridRowCount">Number of grid rows</param> /// <param name="tileRowCount">Number of tile rows per grid</param> /// <param name="tileColumnCount">Number of tile columns per grid</param> /// <param name="tileSize">Tile size in pixel</param> /// <param name="maps">Loaded grids</param> public StreamedTileMap(int spawnTileRow, int spawnTileColumn, int gridColumnCount, int gridRowCount, int tileRowCount, int tileColumnCount, int tileSize, List <TileMapPart> maps) { this.maps = maps; this.gridColumnCount = gridColumnCount; this.gridRowCount = gridRowCount; this.tileSize = tileSize; this.tileRowCount = tileRowCount; this.tileColumnCount = tileColumnCount; currentMapIndex = 4; tileRow = spawnTileRow; tileColumn = spawnTileColumn; gridRow = (int)Math.Floor((double)spawnTileRow / (double)tileRowCount); gridColumn = (int)Math.Floor((double)spawnTileColumn / (double)tileColumnCount); gridRow = TileMathHelper.FixTileIndex(gridRow, gridRowCount); gridColumn = TileMathHelper.FixTileIndex(gridColumn, gridColumnCount); }
/// <summary> /// Calculate all surrounding grid id's /// </summary> /// <param name="gridCount">Number of grids</param> /// <param name="gridColumn">Grid column index</param> /// <param name="gridRow">Grid row index</param> /// <param name="gridsPerRow">Number of grids per row</param> /// <returns>Returns grid id's of all surrounding grids</returns> private int[] CreateSuroundings(int gridCount, int gridColumn, int gridRow, int gridsPerRow) { int[] suroundingGrids = new int[gridCount]; //Line 1 suroundingGrids[0] = TileMathHelper.CalculateGridTranslation(-1, -1, gridColumn, gridRow, gridsPerRow, gridsPerRow); suroundingGrids[1] = TileMathHelper.CalculateGridTranslation(0, -1, gridColumn, gridRow, gridsPerRow, gridsPerRow); suroundingGrids[2] = TileMathHelper.CalculateGridTranslation(1, -1, gridColumn, gridRow, gridsPerRow, gridsPerRow); //Line 2 suroundingGrids[3] = TileMathHelper.CalculateGridTranslation(-1, 0, gridColumn, gridRow, gridsPerRow, gridsPerRow); suroundingGrids[4] = TileMathHelper.CalculateGridTranslation(0, 0, gridColumn, gridRow, gridsPerRow, gridsPerRow); //Center suroundingGrids[5] = TileMathHelper.CalculateGridTranslation(1, 0, gridColumn, gridRow, gridsPerRow, gridsPerRow); //Line 3 suroundingGrids[6] = TileMathHelper.CalculateGridTranslation(-1, 1, gridColumn, gridRow, gridsPerRow, gridsPerRow); suroundingGrids[7] = TileMathHelper.CalculateGridTranslation(0, 1, gridColumn, gridRow, gridsPerRow, gridsPerRow); suroundingGrids[8] = TileMathHelper.CalculateGridTranslation(1, 1, gridColumn, gridRow, gridsPerRow, gridsPerRow); return(suroundingGrids); }
/// <summary> /// Create the StreamedTileMap from the generated grids /// </summary> /// <param name="maps">Current grid with all it's surrounding grids</param> /// <param name="suroundingGrids">Ids of all surrounding grids</param> /// <param name="gridsPerRow">Number grids per row</param> /// <param name="streamedTileMap">A reference to a streamedTileMap</param> private void CreateTileMapParts(Tile[][] maps, List <ObjectTile>[] objectTiles, int[] suroundingGrids, int gridsPerRow, StreamedTileMap streamedTileMap) { //create TileMapPart for (int i = 0; i < maps.Length; i++) { int gridId = suroundingGrids[i]; int gridRow; int gridColumn; TileMathHelper.ToPosition(gridId, gridsPerRow, out gridRow, out gridColumn); gridRow = TileMathHelper.FixTileIndex(gridRow, gridsPerRow); gridColumn = TileMathHelper.FixTileIndex(gridColumn, gridsPerRow); TileMapPart part = new TileMapPart(gridId, maps[i], null, objectTiles[i].ToArray(), gridColumn, gridRow); streamedTileMap.Add(part); } }
/// <summary> /// Initzializes a new streamed tile map /// </summary> /// <param name="generator">Tile map generator</param> /// <param name="spawnTileRow">Tile row index</param> /// <param name="spawnTileColumn">Tile column index</param> /// <param name="gridColumnCount">Number of grid columns</param> /// <param name="gridRowCount">Number of grid rows</param> /// <param name="tileRowCount">Number of tile rows per grid</param> /// <param name="tileColumnCount">Number of tile columns per grid</param> /// <param name="tileSize">Tile size in pixel</param> public StreamedTileMap(TileMapGenerator generator, int spawnTileRow, int spawnTileColumn, int gridColumnCount, int gridRowCount, int tileRowCount, int tileColumnCount, int tileSize) { maps = new List <TileMapPart>(); this.gridColumnCount = gridColumnCount; this.gridRowCount = gridRowCount; this.tileSize = tileSize; this.tileRowCount = tileRowCount; this.tileColumnCount = tileColumnCount; this.generator = generator; currentMapIndex = 4; tileRow = spawnTileRow; tileColumn = spawnTileColumn; gridRow = (int)Math.Floor((double)spawnTileRow / (double)tileRowCount); gridColumn = (int)Math.Floor((double)spawnTileColumn / (double)tileColumnCount); gridRow = TileMathHelper.FixTileIndex(gridRow, gridRowCount); gridColumn = TileMathHelper.FixTileIndex(gridColumn, gridColumnCount); }
/// <summary> /// Create a circular area to a given map /// </summary> /// <param name="map">The map where the area should be placed on</param> /// <param name="rowIndex">Tile row index</param> /// <param name="columnIndex">Tile column index</param> /// <param name="rowCount">Number of rows per grid</param> /// <param name="columnCount">Number of columns per grid</param> /// <param name="radius">Radius of the circle</param> /// <param name="tileSize">Size of a tile in pixel</param> /// <param name="metersPerTile">Size of a tile in meter</param> /// <param name="tileIdValue">Tile id value for the circular area</param> /// <param name="tileFlag">Tile flag</param> /// <param name="allowEdgeManipulation">Allows areas to overlap tiles from other maps</param> /// <returns>Returns the number of changed tiles</returns> private int CreateCircleArea(Tile[] map, int rowIndex, int columnIndex, int rowCount, int columnCount, int radius, int tileSize, float metersPerTile, ushort tileIdValue, byte tileFlag, bool allowEdgeManipulation) { int modified = 0; int minRadiusTile = (int)Math.Ceiling(radius / metersPerTile); int minRadiusPx = minRadiusTile * tileSize; int x = columnIndex * tileSize; int y = rowIndex * tileSize; for (int r = rowIndex - minRadiusTile; r < rowIndex + minRadiusTile; r++) { for (int c = columnIndex - minRadiusTile; c < columnIndex + minRadiusTile; c++) { int realRow = r; int realColumn = c; if (TileMathHelper.IsOutOfRange(r, c, rowCount, columnCount)) { if (allowEdgeManipulation) { realRow = TileMathHelper.FixTileIndex(r, rowCount); realColumn = TileMathHelper.FixTileIndex(c, columnCount); } else { continue; } } int distance = TileMathHelper.GetDistance(x, y, c * tileSize, r * tileSize); if (distance <= minRadiusPx) { int id = TileMathHelper.ToIndex(realRow, realColumn, columnCount); if (map[id].Id == 0) { map[id] = new Tile(tileIdValue, tileFlag); modified++; } } } } return(modified); }
/// <summary> /// Sets a tile value /// </summary> /// <param name="row">Tile row index</param> /// <param name="column">Tile column index</param> /// <param name="value">New tile value</param> public bool SetTileValue(int row, int column, Tile value) { int newGridRow; int newGridColumn; ConvertTileToGridPosition(row, column, out newGridRow, out newGridColumn); int tileMapId = TileMathHelper.ToIndex(newGridRow, newGridColumn, GridColumnCount); int tileRow = TileMathHelper.FixTileIndex(row, TileRowCount); int tileColumn = TileMathHelper.FixTileIndex(column, TileColumnCount); int currentMapIndex = maps.FindIndex(m => m.Id == tileMapId); if (currentMapIndex != -1) { maps[currentMapIndex].MapSurface[TileMathHelper.ToIndex(tileRow, tileColumn, TileColumnCount)] = value; return(true); } return(false); }
private ObjectTile[] CreateObjectLayer(Tile[] map, AreaSpread area, int rowCount, int columnCount) { List <ObjectTile> tiles = new List <ObjectTile>(); float tilesChanged = 0; float tileCount = rowCount * columnCount; while (tilesChanged / tileCount < area.Percentage) { int row = random.Next(0, rowCount); int column = random.Next(0, columnCount); int fieldIndex = TileMathHelper.ToIndex(row, column, columnCount); if (map[fieldIndex].Id == 0) { ObjectTile tile = new ObjectTile(fieldIndex, area.Id); tiles.Add(tile); tilesChanged++; } } return(tiles.ToArray()); }
/// <summary> /// Create the first (height) layer with circular areas /// </summary> /// <param name="map">The map where the area should be placed on</param> /// <param name="rowCount">Number of rows per grid</param> /// <param name="columnCount">Number of columns per grid</param> /// <param name="tileSize">Size of a tile in pixel</param> /// <param name="meterPerTile">Size of a tile in meter</param> /// <param name="area">Area that should be generated and placed on the given map</param> /// <param name="allowEdgeManipulation">Allows areas to overlap tiles from other maps</param> private void CreateLayerOne(Tile[] map, int rowCount, int columnCount, int tileSize, float meterPerTiles, AreaSpread area, bool allowEdgeManipulation) { float tilesChanged = 0; float tileCount = rowCount * columnCount; while (tilesChanged / tileCount < area.Percentage) { int row = random.Next(0, rowCount); int column = random.Next(0, columnCount); int fieldIndex = TileMathHelper.ToIndex(row, column, columnCount); int minRadius = random.Next(area.MinSizeInMeter, area.MaxSizeInMeter + 1); if (map[fieldIndex].Id == 0 || map[fieldIndex].Id == area.Id) { if (area.SpreadType == SpreadOption.Circle) { tilesChanged += CreateCircleArea(map, row, column, rowCount, columnCount, minRadius, tileSize, meterPerTiles, area.Id, area.Flag, allowEdgeManipulation); } } } }
/// <summary> /// Create the first (height) layer with circular areas /// </summary> /// <param name="mapIndex">Index of the map</param> /// <param name="maps">Current grids</param> /// <param name="edgeOverrides">Current edge override maps</param> /// <param name="rowCount">Number of rows per grid</param> /// <param name="columnCount">Number of columns per grid</param> /// <param name="tileSize">Size of a tile in pixel</param> /// <param name="meterPerTile">Size of a tile in meter</param> /// <param name="area">Area that should be generated and placed on the given map</param> /// <param name="allowEdgeOverflow">Allows areas to overlap tiles from other maps</param> private void CreateLayerOne(int mapIndex, Tile[][] maps, Tile[][] edgeOverrides, int rowCount, int columnCount, int tileSize, float meterPerTiles, AreaSpread area, bool allowEdgeOverflow) { int tilesChanged = 0; int tileCount = rowCount * columnCount; while (((float)tilesChanged) / ((float)tileCount) < area.Percentage) { int row = random.Next(0, rowCount); int column = random.Next(0, columnCount); int fieldIndex = TileMathHelper.ToIndex(row, column, columnCount); int minRadius = random.Next(area.MinSizeInMeter, area.MaxSizeInMeter + 1); if (maps[mapIndex][fieldIndex].Id == 0 || maps[mapIndex][fieldIndex].Id == area.Id) { if (area.SpreadType == SpreadOption.Circle) { tilesChanged += CreateCircleArea(mapIndex, maps, edgeOverrides, row, column, rowCount, columnCount, minRadius, tileSize, meterPerTiles, area.Id, area.Flag, allowEdgeOverflow, area.UseEdgeNoise); } } } }
/// <summary> /// Updates the grids based one the given tile location /// </summary> /// <param name="currentTileRow">Tile row index</param> /// <param name="currentTileColumn">Tile column index</param> public void Update(int currentTileRow, int currentTileColumn) { int newGridRow; int newGridColumn; ConvertTileToGridPosition(currentTileRow, currentTileColumn, out newGridRow, out newGridColumn); currentMapId = TileMathHelper.ToIndex(newGridRow, newGridColumn, GridColumnCount); tileRow = TileMathHelper.FixTileIndex(currentTileRow, TileRowCount); tileColumn = TileMathHelper.FixTileIndex(currentTileColumn, TileColumnCount); TryMapUpdate(newGridRow, newGridColumn); CurrentMapIndex = maps.FindIndex(m => m.Id == currentMapId); if ((newGridRow != GridRow || newGridColumn != GridColumn) && !newMapRequested) { GridChangeRequested?.Invoke(this, new GridEventArgs(GridRow, GridColumn, maps[4].GridRow, maps[4].GridColumn, false)); gridRow = newGridRow; gridColumn = newGridColumn; Resize(currentTileRow, currentTileColumn); } }
/// <summary> /// Deframgment maps and adds edge noise /// </summary> /// <param name="maps">Current gird and it's surrounding grids</param> /// <param name="areas">Area spread information to add edge noise if neccessary</param> /// <param name="suroundingGrids">Grid ids of all surrounding grids</param> /// <param name="rowCount">Number of row per grid</param> /// <param name="columnCount">Number of columns per grid</param> private void DefragmentMaps(Tile[][] maps, AreaSpread[] areas, int[] suroundingGrids, int rowCount, int columnCount) { for (int i = 0; i < maps.Length; i++) { random = new Random(suroundingGrids[i] * settings.Seed); for (int r = 0; r < rowCount; r++) { for (int c = 0; c < columnCount; c++) { ushort id = maps[i][TileMathHelper.ToIndex(r, c, columnCount)].Id; if (id != 0) { for (int j = 0; j < areas.Length; j++) { if (id == areas[j].Id) { //EdgeNoise if (areas[j].UseEdgeNoise) { List <Direction> allowedDirections = CheckDirections(r, c, rowCount, columnCount, maps[i]); AddEdgeNoise(r, c, rowCount, columnCount, areas[j].Id, areas[j].Flag, 0.3f, allowedDirections, maps[i]); } if (areas[j].ConnectEqualFlags) { TryConnect(r, c, rowCount, columnCount, maps[i], id, areas[j].Flag, areas[j].ConnectDistance, DirectionAxis.Vertical); TryConnect(r, c, rowCount, columnCount, maps[i], id, areas[j].Flag, areas[j].ConnectDistance, DirectionAxis.Horizontal); } } } } } } } }
/// <summary> /// Tries to connects close areas with the same flag /// </summary> /// <param name="row">Tile row index</param> /// <param name="column">Tile column index</param> /// <param name="rowCount">Grid row count</param> /// <param name="columnCount">Grid column count</param> /// <param name="map">Current map as flatten array</param> /// <param name="tileIdValue">Tile id value</param> /// <param name="tileFlags">Tile flags</param> /// <param name="distance">Maximum tile distance between areas</param> /// <param name="axis">Direction of connection</param> private void TryConnect(int row, int column, int rowCount, int columnCount, Tile[] map, ushort tileIdValue, byte tileFlags, int distance, DirectionAxis axis) { bool connectPos = false; bool connectNeg = false; int realRow = row; int realColumn = column; for (int i = distance; i > 0; i--) { if (axis == DirectionAxis.Horizontal) { realColumn = column + i; } else { realRow = row + i; } if (!TileMathHelper.IsOutOfRange(realRow, realColumn, rowCount, columnCount)) { int id = TileMathHelper.ToIndex(realRow, realColumn, columnCount); if (!connectPos) { if (map[id].Id == tileIdValue) { connectPos = true; } } else { if (map[id].Id == 0) { map[id] = new Tile(tileIdValue, tileFlags); } } } if (axis == DirectionAxis.Horizontal) { realColumn = column - i; } else { realRow = row - i; } if (!TileMathHelper.IsOutOfRange(realRow, realColumn, rowCount, columnCount)) { int id = TileMathHelper.ToIndex(realRow, realColumn, columnCount); if (!connectNeg) { if (map[id].Id == tileIdValue) { connectNeg = true; } } else { if (map[id].Id == 0) { map[id] = new Tile(tileIdValue, tileFlags); } } } } }
/// <summary> /// Create a circular area to a given map /// </summary> /// <param name="mapIndex">Index of the map</param> /// <param name="maps">Current grids</param> /// <param name="edgeOverrides">Current edge override maps</param> /// <param name="rowIndex">Tile row index</param> /// <param name="columnIndex">Tile column index</param> /// <param name="rowCount">Number of rows per grid</param> /// <param name="columnCount">Number of columns per grid</param> /// <param name="radius">Radius of the circle</param> /// <param name="tileSize">Size of a tile in pixel</param> /// <param name="metersPerTile">Size of a tile in meter</param> /// <param name="tileIdValue">Tile id value for the circular area</param> /// <param name="tileFlags">Tile flags</param> /// <param name="allowEdgeOverflow">Allows areas to overlap tiles from other maps</param> /// <param name="useEdgeNoise">Adds edge noise to the generated area</param> /// <returns>Returns the number of changed tiles</returns> private int CreateCircleArea(int mapIndex, Tile[][] maps, Tile[][] edgeOverrides, int rowIndex, int columnIndex, int rowCount, int columnCount, int radius, int tileSize, float metersPerTile, ushort tileIdValue, byte tileFlags, bool allowEdgeOverflow, bool useEdgeNoise) { int modified = 0; int minRadiusTile = (int)Math.Ceiling(radius / metersPerTile); int minRadiusPx = minRadiusTile * tileSize; int x = columnIndex * tileSize; int y = rowIndex * tileSize; for (int r = rowIndex - minRadiusTile; r < rowIndex + minRadiusTile; r++) { for (int c = columnIndex - minRadiusTile; c < columnIndex + minRadiusTile; c++) { int currentMapIndex = mapIndex; int realRow = r; int realColumn = c; if (TileMathHelper.IsOutOfRange(r, c, rowCount, columnCount)) { if (allowEdgeOverflow) { currentMapIndex = TileMathHelper.GetMapIndex(r, c, rowCount, columnCount, currentMapIndex); if (currentMapIndex >= 0) { realRow = TileMathHelper.FixTileIndex(r, rowCount); realColumn = TileMathHelper.FixTileIndex(c, columnCount); } else { continue; } } else { continue; } } int distance = TileMathHelper.GetDistance(x, y, c * tileSize, r * tileSize); if (distance <= minRadiusPx) { int id = TileMathHelper.ToIndex(realRow, realColumn, columnCount); if (mapIndex == currentMapIndex) { if (maps[currentMapIndex][id].Id == 0) { maps[currentMapIndex][id] = new Tile(tileIdValue, tileFlags); modified++; } } else { if (edgeOverrides[currentMapIndex][id].Id == 0) { edgeOverrides[currentMapIndex][id] = new Tile(tileIdValue, tileFlags); } } } } } return(modified); }
/// <summary> /// Generates a map based on the given tile location, generator settings and area spreads /// </summary> /// <param name="settings">Generator settings to modify the generation process</param> /// <param name="areas">Areas that should be placed on the map</param> /// <param name="tileColumn">Tile column index</param> /// <param name="tileRow">Tile row index</param> /// <returns>Returns a StreamedTileMap</returns> public StreamedTileMap GenerateMap(GeneratorSettings settings, AreaSpread[] areas, int tileColumn, int tileRow) { if (settings.Seed > 0) { random = new Random(settings.Seed); } else if (random == null) { throw new ArgumentOutOfRangeException(); } this.settings = settings; spreads = areas; double tilesPerGrid = Math.Round(settings.MeterPerGrid / settings.MeterPerTile); int tilesPerColumn = (int)tilesPerGrid; int size = tilesPerColumn * tilesPerColumn; int gridsPerRow = (int)Math.Ceiling(GetMapSize(settings) / tilesPerGrid); int gridColumn = (int)Math.Floor(tileColumn / tilesPerGrid); int gridRow = (int)Math.Floor(tileRow / tilesPerGrid); Tile[][] edgeOverrides = new Tile[9][]; Tile[][] maps = new Tile[9][]; List <ObjectTile>[] objectTiles = new List <ObjectTile> [9]; for (int i = 0; i < maps.Length; i++) { edgeOverrides[i] = new Tile[size]; maps[i] = new Tile[size]; objectTiles[i] = new List <ObjectTile>(); } int[] suroundingGrids = CreateSuroundings(maps.Length, gridColumn, gridRow, gridsPerRow); StreamedTileMap streamedTileMap = new StreamedTileMap(this, tileRow, tileColumn, gridsPerRow, gridsPerRow, tilesPerColumn, tilesPerColumn, settings.TileSize); //Create Map foreach (LayerType currentLayerType in Enum.GetValues(typeof(LayerType)).Cast <LayerType>().OrderBy(k => (int)k)) { for (int i = 0; i < suroundingGrids.Length; i++) { AreaSpread[] layerAreas = areas.Where(a => a.Layer == currentLayerType).ToArray(); random = new Random(suroundingGrids[i] * settings.Seed); for (int j = 0; j < layerAreas.Length; j++) { switch (layerAreas[j].Layer) { case LayerType.Height: { if (layerAreas[j].MaxSizeInMeter <= settings.MeterPerGrid / 2f) { CreateLayerOne(i, maps, edgeOverrides, (int)tilesPerGrid, (int)tilesPerGrid, settings.TileSize, settings.MeterPerTile, layerAreas[j], settings.RadiusOfCylinder); } else { throw new Exception("AreaSpread MaxSize must be smaller then (MetersPerGrid / 2)!"); } break; } case LayerType.Biome: CreateBiomeLayer(i, maps, layerAreas[j]); break; case LayerType.Paths: CreateLayerFour(); break; case LayerType.PointsOfInterest: { objectTiles[i].AddRange(CreateObjectLayer(maps[i], layerAreas[j], tilesPerColumn, tilesPerColumn)); } break; } } } if (currentLayerType == LayerType.Height) { //DefragementMap and add edgenoise DefragmentMaps(maps, areas, suroundingGrids, (int)tilesPerGrid, (int)tilesPerGrid); //Merge edgeOverrides for (int k = 0; k < maps.Length; k++) { maps[k] = TileMathHelper.MergeMaps(maps[k], edgeOverrides[k]); } } } CreateTileMapParts(maps, objectTiles, suroundingGrids, gridsPerRow, streamedTileMap); return(streamedTileMap); }