public bool TraversableTo(MapSection mapSection) { if (XPos == mapSection.XPos - 1 && YPos == mapSection.YPos && HasOpenRight && mapSection.HasOpenLeft) { return(true); } if (XPos == mapSection.XPos + 1 && YPos == mapSection.YPos && HasOpenLeft && mapSection.HasOpenRight) { return(true); } if (XPos == mapSection.XPos && YPos == mapSection.YPos - 1 && HasOpenBottom && mapSection.HasOpenTop) { return(true); } if (XPos == mapSection.XPos && YPos == mapSection.YPos + 1 && HasOpenTop && mapSection.HasOpenBottom) { return(true); } return(false); }
public void InitializeMap(GraphicsDevice graphicsDevice, Rectangle clientBounds, MapSectionTypes?type = null) { _texture = TextureCacheFactory.GetOnce("Maps/Tiles.png"); _textureLocations = new Dictionary <TileTypes, Rectangle> { [TileTypes.Floor] = new Rectangle(128, 256, 64, 64), [TileTypes.Wall] = new Rectangle(0, 32, 64, 64), [TileTypes.SingleWall] = new Rectangle(320, 32, 64, 64) }; _mapSectionWidth = _textureLocations[TileTypes.Floor].Width * GameConstants.MapSectionSizeInTiles; _mapSectionHeight = _textureLocations[TileTypes.Floor].Height * GameConstants.MapSectionSizeInTiles; MapSection startSection = null; _sections = new MapSection[MapNumSectionsWide, MapNumSectionsTall]; if (type.HasValue) { for (var x = 0; x < MapNumSectionsWide; x++) { for (var y = 0; y < MapNumSectionsTall; y++) { _sections[x, y] = new MapSection(type.Value, new Rectangle(_mapSectionWidth * x, _mapSectionHeight * y, _mapSectionWidth, _mapSectionHeight), x, y); } } } else { // First surround the map in wall sections for (var x = 0; x < MapNumSectionsWide; x++) { var bottomY = MapNumSectionsTall - 1; _sections[x, 0] = new MapSection(MapSectionTypes.Wall, new Rectangle(_mapSectionWidth * x, _mapSectionHeight * 0, _mapSectionWidth, _mapSectionHeight), x, bottomY); _sections[x, bottomY] = new MapSection(MapSectionTypes.Wall, new Rectangle(_mapSectionWidth * x, _mapSectionHeight * bottomY, _mapSectionWidth, _mapSectionHeight), x, bottomY); } for (var y = 1; y < MapNumSectionsTall - 1; y++) { var rightX = MapNumSectionsWide - 1; _sections[0, y] = new MapSection(MapSectionTypes.Wall, new Rectangle(_mapSectionWidth * 0, _mapSectionHeight * y, _mapSectionWidth, _mapSectionHeight), rightX, y); _sections[rightX, y] = new MapSection(MapSectionTypes.Wall, new Rectangle(_mapSectionWidth * (rightX), _mapSectionHeight * y, _mapSectionWidth, _mapSectionHeight), rightX, y); } // Create the start var startingSectionX = Helpers.RandomIntInRange(1, MapNumSectionsWide - 2); var startingSectionY = Helpers.RandomIntInRange(1, MapNumSectionsWide - 2); StartingPosition = new Vector2(startingSectionX * _mapSectionWidth + _mapSectionHeight / 2, startingSectionY * _mapSectionHeight + _mapSectionHeight / 2); _sections[startingSectionX, startingSectionY] = new MapSection(MapSectionTypes.Start, new Rectangle(_mapSectionWidth * startingSectionX, _mapSectionHeight * startingSectionY, _mapSectionWidth, _mapSectionHeight), startingSectionX, startingSectionY); startSection = _sections[startingSectionX, startingSectionY]; // Create all of the other middle tiles for (var x = 1; x < MapNumSectionsWide - 1; x++) { for (var y = 1; y < MapNumSectionsTall - 1; y++) { if (_sections[x, y] == null) { _sections[x, y] = new MapSection(MapSectionTypes.Walled, new Rectangle(_mapSectionWidth * x, _mapSectionHeight * y, _mapSectionWidth, _mapSectionHeight), x, y); } } } // Create a maze var numVisited = 1; var stack = new List <(int, int)>(); (int X, int Y)currentSection = (startingSectionX, startingSectionY); while (numVisited < (MapNumSectionsTall - 2) * (MapNumSectionsWide - 2)) { var adjacentCells = GetAdjacentSections(currentSection.X, currentSection.Y, true); if (adjacentCells.Any()) { var randomNeighbor = adjacentCells[Globals.Random.Next(adjacentCells.Count)]; switch (randomNeighbor.Direction) { case CardinalDirection.Up: _sections[randomNeighbor.X, randomNeighbor.Y].DestroyWall(CardinalDirection.Down); _sections[currentSection.X, currentSection.Y].DestroyWall(CardinalDirection.Up); break; case CardinalDirection.Down: _sections[randomNeighbor.X, randomNeighbor.Y].DestroyWall(CardinalDirection.Up); _sections[currentSection.X, currentSection.Y].DestroyWall(CardinalDirection.Down); break; case CardinalDirection.Left: _sections[randomNeighbor.X, randomNeighbor.Y].DestroyWall(CardinalDirection.Right); _sections[currentSection.X, currentSection.Y].DestroyWall(CardinalDirection.Left); break; case CardinalDirection.Right: _sections[randomNeighbor.X, randomNeighbor.Y].DestroyWall(CardinalDirection.Left); _sections[currentSection.X, currentSection.Y].DestroyWall(CardinalDirection.Right); break; } stack.Add((currentSection.X, currentSection.Y)); currentSection = (randomNeighbor.X, randomNeighbor.Y); numVisited++; } else { // Set current section to the popped section from the stack currentSection = stack.Last(); stack.Remove(currentSection); } } } // Find the furthest cell from the start and spawn the boss there (if this is a real map) if (startSection != null) { var sectionsToVisit = new List <MapSection> { startSection }; var sections = new Dictionary <MapSection, int?> { [startSection] = 0 }; var bossSection = startSection; var maxDistance = 0; while (sectionsToVisit.Any()) { // Pop one var section = sectionsToVisit.Last(); sectionsToVisit.Remove(section); var adjacentCells = GetAdjacentSections(section.XPos, section.YPos, false); var distance = sections[section].Value + 1; foreach (var cell in adjacentCells) { var adjacentSection = _sections[cell.X, cell.Y]; // If we've already gotten to this cell in the same or less distance then ignore if (sections.Keys.Contains(adjacentSection) && sections[adjacentSection] <= distance) { continue; } // Process this section if we haven't already if (!sectionsToVisit.Contains(adjacentSection)) { sectionsToVisit.Add(adjacentSection); } sections[adjacentSection] = distance; if (distance > maxDistance) { maxDistance = distance; bossSection = adjacentSection; } } } bossSection.Type = MapSectionTypes.Boss; } // Tell the sections we are done making the map for (var x = 0; x < MapNumSectionsWide; x++) { for (var y = 0; y < MapNumSectionsTall; y++) { _sections[x, y].MapComplete(); } } }