public IEnumerable <Tile> GetNeighbors(Tile tile) { Block block; if (!_blockCache.TryGetValue(tile, out block)) { block = _level.GetBlock(new BlockCoordinates((int)tile.X, _startY, (int)tile.Y)); _blockCache.Add(tile, block); } HashSet <Tile> list = new HashSet <Tile>(); for (int index = 0; index < Neighbors.GetLength(0); ++index) { var item = new Tile(tile.X + Neighbors[index, 0], tile.Y + Neighbors[index, 1]); // Check for too high steps BlockCoordinates coord = new BlockCoordinates((int)item.X, block.Coordinates.Y, (int)item.Y); if (_level.GetBlock(coord).IsSolid) { if (_entity.CanClimb) { Block blockUp = _level.GetBlock(coord + BlockCoordinates.Up); bool canMove = false; for (int i = 0; i < 10; i++) { if (IsBlocked(blockUp.Coordinates)) { blockUp = _level.GetBlock(blockUp.Coordinates + BlockCoordinates.Up); continue; } canMove = true; break; } if (!canMove) { continue; } if (IsObstructed(blockUp.Coordinates)) { continue; } _blockCache[item] = blockUp; } else { Block blockUp = _level.GetBlock(coord + BlockCoordinates.Up); if (blockUp.IsSolid) { // Can't jump continue; } if (IsObstructed(blockUp.Coordinates)) { continue; } _blockCache[item] = blockUp; } } else { var blockDown = _level.GetBlock(coord + BlockCoordinates.Down); if (!blockDown.IsSolid) { if (_entity.CanClimb) { bool canClimb = false; blockDown = _level.GetBlock(blockDown.Coordinates + BlockCoordinates.Down); for (int i = 0; i < 10; i++) { if (!blockDown.IsSolid) { blockDown = _level.GetBlock(blockDown.Coordinates + BlockCoordinates.Down); continue; } canClimb = true; break; } if (!canClimb) { continue; } blockDown = _level.GetBlock(blockDown.Coordinates + BlockCoordinates.Up); if (IsObstructed(blockDown.Coordinates)) { continue; } _blockCache[item] = blockDown; } else { if (!_level.GetBlock(coord + BlockCoordinates.Down + BlockCoordinates.Down).IsSolid) { // Will fall continue; } if (IsObstructed(blockDown.Coordinates)) { continue; } _blockCache[item] = blockDown; } } else { if (IsObstructed(coord)) { continue; } _blockCache[item] = _level.GetBlock(coord); } } list.Add(item); } CheckDiagonals(block, list); return(list); }
public IEnumerable <ImprovedTile> GetNeighbors(ImprovedTile tile) { Block block; if (!_blockCache.TryGetValue(tile, out block)) { block = _level.GetBlock(new BlockCoordinates(tile.X, _startY, tile.Y)); _blockCache.Add(tile, block); } List <ImprovedTile> list = new List <ImprovedTile>(); for (int index = 0; index < Neighbors.GetLength(0); ++index) { var item = new ImprovedTile(tile.X + Neighbors[index, 0], tile.Y + Neighbors[index, 1]); // Check for too high steps BlockCoordinates coord = new BlockCoordinates(item.X, block.Coordinates.Y, item.Y); if (_level.GetBlock(coord).IsSolid) { Block blockUp = _level.GetBlock(coord + BlockCoordinates.Up); if (blockUp.IsSolid) { // Can't jump continue; } if (IsObstructed(blockUp.Coordinates)) { continue; } _blockCache[item] = blockUp; } else { var blockDown = _level.GetBlock(coord + BlockCoordinates.Down); if (!blockDown.IsSolid) { if (!_level.GetBlock(coord + BlockCoordinates.Down + BlockCoordinates.Down).IsSolid) { // Will fall continue; } if (IsObstructed(blockDown.Coordinates)) { continue; } _blockCache[item] = blockDown; } else { if (IsObstructed(coord)) { continue; } _blockCache[item] = _level.GetBlock(coord); } } list.Add(item); } CheckDiagonals(block, list); return(list); }
public IEnumerable <Tile> GetNeighbors(Tile start) { if (!_blockCache.TryGetValue(start, out var block)) { block = _level.GetBlock(new BlockCoordinates(start.X, _startY, start.Y)); _blockCache.Add(start, block); } HashSet <Tile> neighbors = new HashSet <Tile>(); for (int index = 0; index < Neighbors.GetLength(0); ++index) { var item = new Tile3d(start.X + Neighbors[index, 0], start.Y + Neighbors[index, 1], block.Coordinates.Y); bool isDiagonalMove = item.X != start.X && item.Y != start.Y; if (isDiagonalMove) { // Don't allow cutting corners where there is a block Tile undiagonal = new Tile(start.X, start.Y + Neighbors[index, 1]); if (!_blockCache.TryGetValue(undiagonal, out var udblock)) { continue; } if (udblock.Coordinates.Y != block.Coordinates.Y) { continue; } } // Check for too high steps BlockCoordinates coord = new BlockCoordinates(item.X, block.Coordinates.Y, item.Y); if (_level.GetBlock(coord).IsSolid) { // Only allow diagonal movements if on same Y level if (isDiagonalMove) { continue; } // Check if we hit head if we jump or climb up to next block if (IsObstructed(block.Coordinates.BlockUp())) { continue; } if (_entity.CanClimb) { Block blockUp = _level.GetBlock(coord.BlockUp()); Block currBlockUp = _level.GetBlock(block.Coordinates.BlockUp()); // Check if we hit ceiling too bool canMove = false; for (int i = 0; i < 10; i++) { if (IsBlocked(blockUp) && !IsBlocked(currBlockUp)) { blockUp = _level.GetBlock(blockUp.Coordinates.BlockUp()); currBlockUp = _level.GetBlock(currBlockUp.Coordinates.BlockUp()); continue; } canMove = true; break; } if (!canMove) { continue; } if (IsObstructed(blockUp.Coordinates)) { continue; } if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockUp.Coordinates.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = blockUp.Coordinates.Y; _blockCache[item] = blockUp; } else { // Check block collision box, not hit box if (_level.GetBlock(coord) is Fence) { continue; } Block blockUp = _level.GetBlock(coord.BlockUp()); if (blockUp.IsSolid) { // Can't jump. This is hardwired for 1 block jump height for all mobs. continue; } if (IsObstructed(blockUp.Coordinates)) { continue; } //TODO: There is a problem when there is a path both under and over a block. It chooses the last checked block. if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockUp.Coordinates.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = blockUp.Coordinates.Y; _blockCache[item] = blockUp; } } else { if (IsObstructed(coord)) { continue; } var blockDown = _level.GetBlock(coord.BlockDown()); if (blockDown.IsSolid) { // Continue on same Y level if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != coord.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = coord.Y; _blockCache[item] = _level.GetBlock(coord); } else { // Only allow diagonal movements if on same Y level if (isDiagonalMove) { continue; } if (_entity.CanClimb) { bool canClimb = false; blockDown = _level.GetBlock(blockDown.Coordinates.BlockDown()); for (int i = 0; i < 10; i++) { if (!blockDown.IsSolid) { blockDown = _level.GetBlock(blockDown.Coordinates.BlockDown()); continue; } canClimb = true; break; } if (!canClimb) { continue; } blockDown = _level.GetBlock(blockDown.Coordinates.BlockUp()); if (IsObstructed(blockDown.Coordinates)) { continue; } if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockDown.Coordinates.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = blockDown.Coordinates.Y; _blockCache[item] = blockDown; } else { if (!_level.GetBlock(coord.BlockDown().BlockDown()).IsSolid) { // Will fall continue; } if (IsObstructed(blockDown.Coordinates)) { continue; } if (_blockCache.TryGetValue(item, out var trash) && trash.Coordinates.Y != blockDown.Coordinates.Y) { //Log.Warn("Already had this coordinated but on different Y"); continue; } item.RealY = blockDown.Coordinates.Y; _blockCache[item] = blockDown; } } } neighbors.Add(item); } CheckDiagonals(block, neighbors); return(neighbors); }