private List <AstarTile> GetWalkableTiles(int[] map, AstarTile currentTile, AstarTile targetTile) { var possibleTiles = new List <AstarTile>() { new AstarTile { X = currentTile.X, Y = currentTile.Y - 1, Parent = currentTile, Cost = currentTile.Cost + 1 }, new AstarTile { X = currentTile.X, Y = currentTile.Y + 1, Parent = currentTile, Cost = currentTile.Cost + 1 }, new AstarTile { X = currentTile.X - 1, Y = currentTile.Y, Parent = currentTile, Cost = currentTile.Cost + 1 }, new AstarTile { X = currentTile.X + 1, Y = currentTile.Y, Parent = currentTile, Cost = currentTile.Cost + 1 }, }; possibleTiles.ForEach(tile => tile.SetDistance(targetTile.X, targetTile.Y)); return(possibleTiles .Where(tile => tile.X >= 0 && tile.X < _width) .Where(tile => tile.Y >= 0 && tile.Y < _height) .Where(tile => map[tile.Y * 8 + tile.X] == 0) // || tile.Y = // map[tile.Y * 8 + tile.X] == 'B') .ToList()); }
public void SetTile(AstarTile _lastindex, List <AstarTile> _openlist, Position _endpos) { if (tileData.tileRestriction == TILE_RESTRICTION.FORBIDDEN || tileData.tileRestriction == TILE_RESTRICTION.OCCUPIED) { return; //이동 할 수 없는 타일이면 리턴 } //비행형일시 다른 제한값 필요 //몬스터의 검색범위 한정 필요 if (!isListed) //오픈 리스트에 없다면 { isListed = true; //트루로 바꾸고 _openlist.Add(this); //오픈 리스트에 추가 CalcH(_endpos); //H값 계산 적용 G = _lastindex.G + 14; //G값 계산 적용 CalcF(); //F계산 parentTile = _lastindex; //검색타일을 부모로 설정 } else //오픈 리스트에 있다면 { if (_lastindex.G + 14 < G) //기존 G보다 새로운 G가 작다면 { G = _lastindex.G + 14; //G값 다시 적용 CalcF(); //새로운 F계산 parentTile = _lastindex; //검색타일을 부모로 설정 } } }
public void AstarInit() { //해당 층에서 필요한 타일맵 정보를 받아온다. mapHeight = TileManager.Instance.mapHeight; mapWidth = TileManager.Instance.mapWidth; tileMapInfo = TileManager.Instance.tileMapInfoArray; astarTiles = new AstarTile[mapWidth, mapHeight]; for (int i = 0; i < mapHeight; i++) { for (int j = 0; j < mapWidth; j++) { astarTiles[j, i] = new AstarTile(); astarTiles[j, i].tileData = new TileData(); astarTiles[j, i].parentTile = new AstarTile(); astarTiles[j, i].Init(); astarTiles[j, i].position.PosX = j; astarTiles[j, i].position.PosY = i; astarTiles[j, i].tileData = tileMapInfo[j, i].tileData; //참조 형식 X } } lastIndex = 0; openList = new List <AstarTile>(); closeList = new List <AstarTile>(); pathList = new List <TileData>(); }
public int H; //여기부터 끝까지 public void Init() { parentTile = null; isListed = false; F = 5000; G = 0; H = 0; }
void MakePath(AstarTile _tile, Position _beginpos) { pathList.Add(_tile.tileData); _tile = _tile.parentTile; //타일의 부모를 참조 if (_tile.tileData.position.PosX == _beginpos.PosX && _tile.tileData.position.PosY == _beginpos.PosY) //시작점까지 왔으면 그만 { pathList.Reverse(); return; } else { MakePath(_tile, _beginpos); //다시 호출 } }
public bool WalkToTarget(int sx, int sy, int fx, int fy, int[] usable) { NextTile = null; Array.Clear(_map, 0, _map.Length); for (int i = 0; i < _map.Length; i++) { if (!usable.Contains(i)) { _map[i] = 1; } } // Set the start to walkable ;) _map[sy * 8 + sx] = 0; var start = new AstarTile() { X = sx, Y = sy }; var finish = new AstarTile() { X = fx, Y = fy }; start.SetDistance(finish.X, finish.Y); var activeTiles = new List <AstarTile>(); activeTiles.Add(start); var visitedTiles = new List <AstarTile>(); while (activeTiles.Any()) { var checkTile = activeTiles.OrderBy(x => x.CostDistance).First(); if (checkTile != null && checkTile.X == finish.X && checkTile.Y == finish.Y) { // Walk back through the tiles to the tile AFTER the start. // That's going to be our next tile var tile = checkTile; while (tile?.Parent != null && tile?.Parent != start) { tile = tile?.Parent; } NextTile = tile; // Only return true if we have a tile and it's NOT the player's tile return(NextTile != null && NextTile.X != fx && NextTile.Y != fy); } visitedTiles.Add(checkTile); activeTiles.Remove(checkTile); var walkableTiles = GetWalkableTiles(_map, checkTile, finish); foreach (var walkableTile in walkableTiles) { //We have already visited this tile so we don't need to do so again! if (visitedTiles.Any(x => x.X == walkableTile.X && x.Y == walkableTile.Y)) { continue; } //It's already in the active list, but that's OK, maybe this new tile has a better value (e.g. We might zigzag earlier but this is now straighter). if (activeTiles.Any(x => x.X == walkableTile.X && x.Y == walkableTile.Y)) { var existingTile = activeTiles.First(x => x.X == walkableTile.X && x.Y == walkableTile.Y); if (existingTile.CostDistance > checkTile.CostDistance) { activeTiles.Remove(existingTile); activeTiles.Add(walkableTile); } } else { //We've never seen this tile before so add it to the list. activeTiles.Add(walkableTile); } } } // No path found return(false); }