public override void Update() { if (_character.EmptyPathFindingTileCell() == false) { TileCell tileCell = _character.PopPathFindingTileCell(); sPosition curPosition; curPosition.x = _character.GetTileX(); curPosition.y = _character.GetTileY(); sPosition nextPosition; nextPosition.x = tileCell.GetTileX(); nextPosition.y = tileCell.GetTileY(); eMoveDirection direction = GetDirection(curPosition, nextPosition); _character.SetNextDirection(direction); if ((_character.MoveStart(tileCell.GetTileX(), tileCell.GetTileY()) == false)) { //_nextState = eStateType.ATTACK; _nextState = eStateType.DISCOVER; } } else { _nextState = eStateType.IDLE; } }
bool CheckPrecondition(eFindMode mode, TileCell nextTileCell, TileCell targetTileCell) { //if ((null != nextTileCell) && (true == nextTileCell.IsPathfindable() && false == nextTileCell.IsVisit() || // (nextTileCell.GetTileX() == _targetTileCell.GetTileX() && nextTileCell.GetTileY() == _targetTileCell.GetTileY()))) // return true; bool condition = false; if (false == nextTileCell.IsVisit()) { condition = true; } if (eFindMode.VIEW_MOVERANGE == mode || eFindMode.FIND_PATH == mode) { if (condition) { condition = nextTileCell.CanMove(); } } if (eMapType.DUNGEON == GameManager.Instance.GetMapType()) { return(condition); } else if (eMapType.TOWN == GameManager.Instance.GetMapType()) { //해당 타일이 목표 타일 if (nextTileCell.GetTileX() == targetTileCell.GetTileX() && nextTileCell.GetTileY() == targetTileCell.GetTileY()) { condition = true; } } return(condition); }
// Actions public void MoveTileCell(TileCell tileCell) { ResetMoveCooltime(); TileMap map = GameManager.Instance.GetMap(); int moveX = tileCell.GetTileX(); int moveY = tileCell.GetTileY(); map.ResetObject(_tileX, _tileY, this); _tileX = moveX; _tileY = moveY; map.SetObject(_tileX, _tileY, this, eTileLayer.MIDDLE); //pick message 주기 List <MapObject> mapObejctList = map.GetTileCell(_tileX, _tileY).GetMapObjectList(eTileLayer.MIDDLE); for (int i = 0; i < mapObejctList.Count; i++) { MessageParam msgParam = new MessageParam(); msgParam.sender = this; msgParam.receiver = mapObejctList[i]; msgParam.message = "pick"; MessageSystem.Instance.Send(msgParam); } }
float CalcSimpleHeuristic(TileCell tileCell, TileCell nextTileCell, TileCell targetTileCell) { float heuristic = 0.0f; int diffFromCurrent = 0; int diffFromNext = 0; //x축 { //현재타일 ~ 목표타일까지 거리 diffFromCurrent = tileCell.GetTileX() - targetTileCell.GetTileX(); diffFromCurrent = Mathf.Abs(diffFromCurrent); //다음타일 ~ 목표타일까지 거리 diffFromNext = nextTileCell.GetTileX() - targetTileCell.GetTileX(); diffFromNext = Mathf.Abs(diffFromNext); if (diffFromCurrent < diffFromNext) { heuristic += 1.0f; } else if (diffFromNext < diffFromCurrent) { heuristic -= 1.0f; } } //y축 { //현재타일 ~ 목표타일까지 거리 diffFromCurrent = tileCell.GetTileY() - targetTileCell.GetTileY(); diffFromCurrent = Mathf.Abs(diffFromCurrent); //다음타일 ~ 목표타일까지 거리 diffFromNext = nextTileCell.GetTileY() - targetTileCell.GetTileY(); diffFromNext = Mathf.Abs(diffFromNext); if (diffFromCurrent < diffFromNext) { heuristic += 1.0f; } else if (diffFromNext < diffFromCurrent) { heuristic -= 1.0f; } } return(heuristic); }
public bool IsClickedCharacter(TileCell tileCell) { if (_tileX == tileCell.GetTileX() && _tileY == tileCell.GetTileY()) { return(true); } return(false); }
public void SetTargetTileCell(TileCell targetTileCell) { _targetTileCell = targetTileCell; if (_targetTileCell.GetTileX() != this.GetTileX() && _targetTileCell.GetTileY() != this.GetTileY()) { SetPathFindingType(ePathFindingType.ASTAR); } }
public HashSet <MapObject> FindObjectsByRange(eMapObjectType type, eTileLayer layer, TileCell center, int range = 1) { int minX = center.GetTileX() - range; int minY = center.GetTileY() - range; int maxX = center.GetTileX() + range; int maxY = center.GetTileY() + range; if (minX < 0) { minX = 0; } if (minY < 0) { minY = 0; } if (_width <= maxX) { maxX = _width; } if (_height <= maxY) { maxY = _height; } HashSet <MapObject> mapObjects = new HashSet <MapObject>(); for (int y = minY; y <= maxY; y++) { for (int x = minX; x <= maxX; x++) { var mapObject = GetTileCell(x, y)?.FindObjectByType(type, layer); if (null != mapObject) { mapObjects.Add(mapObject); } } } if (0 == mapObjects.Count) { return(null); } return(mapObjects); }
float CalcComplexHeuristic(TileCell nextTileCell, TileCell targetTileCell) { int distanceW = nextTileCell.GetTileX() - targetTileCell.GetTileX(); int distanceH = nextTileCell.GetTileY() - targetTileCell.GetTileY(); distanceW = distanceW * distanceW; distanceH = distanceH * distanceH; return((float)(distanceW + distanceH)); }
float CalcEuclideanDistance(TileCell tileCell, TileCell targetCell) { int distanceW = targetCell.GetTileX() - tileCell.GetTileX(); int distanceH = targetCell.GetTileY() - tileCell.GetTileY(); distanceW *= distanceW; distanceH *= distanceH; return(Mathf.Sqrt(distanceW + distanceH)); }
public override void Update() { if (false == _character.IsEmptyPathfindingTileCell()) { if (_moveDuration < _moveSpeed) { _moveDuration += Time.deltaTime; return; } _moveDuration = 0.0f; TileCell tileCell = _character.PopPathfindingTileCell(); sPosition curPosition; curPosition.x = _character.GetTileX(); curPosition.y = _character.GetTileY(); sPosition toPosition; toPosition.x = tileCell.GetTileX(); toPosition.y = tileCell.GetTileY(); eMoveDirection direction = GetDirection(toPosition, curPosition); _character.SetNextDirection(direction); if (false == _character.MoveStart(tileCell.GetTileX(), tileCell.GetTileY())) { if (_character.IsAttackable()) { _nextState = eStateType.ATTACK; } else { _nextState = eStateType.IDLE; } } } else { _nextState = eStateType.IDLE; } }
float CalcComplexHeuristic(TileCell nextTileCell, TileCell targetTileCell) { int deltaX = nextTileCell.GetTileX() - targetTileCell.GetTileX(); deltaX = deltaX * deltaX; int deltaY = nextTileCell.GetTileY() - targetTileCell.GetTileY(); deltaY = deltaY * deltaY; return((float)(deltaX + deltaY)); }
float CalcSimpleHeuristic(TileCell tileCell, TileCell nextTileCell, TileCell targetTileCell) { float heuristic = 0.0f; int deltaTileX = tileCell.GetTileX() - targetTileCell.GetTileX(); deltaTileX = Mathf.Abs(deltaTileX); int nextDeltaTileX = nextTileCell.GetTileX() - targetTileCell.GetTileX(); nextDeltaTileX = Mathf.Abs(nextDeltaTileX); if (deltaTileX < nextDeltaTileX) { heuristic += 1.0f; } else if (deltaTileX > nextDeltaTileX) { heuristic -= 1.0f; } int deltaTileY = tileCell.GetTileY() - targetTileCell.GetTileY(); deltaTileY = Mathf.Abs(deltaTileY); int nextDeltaTileY = nextTileCell.GetTileY() - targetTileCell.GetTileY(); nextDeltaTileY = Mathf.Abs(nextDeltaTileY); if (deltaTileY < nextDeltaTileY) { heuristic += 1.0f; } else if (deltaTileY > nextDeltaTileY) { heuristic -= 1.0f; } return(heuristic); }
public List <MapObject> GetCollisionList(TileCell tileCell) { int tileX = tileCell.GetTileX(); int tileY = tileCell.GetTileY(); if (tileX < 0 || _width <= tileX) { return(null); } if (tileY < 0 || _height <= tileY) { return(null); } return(tileCell.GetCollisionList()); }
void FindPath() { TileSystem tileSystem = TileSystem.Instance; while (0 != _pathfindingQueue.Count) { //제일 앞 타일을 하나 꺼낸다. sPathCommand command = _pathfindingQueue[0]; _pathfindingQueue.RemoveAt(0); //방문한 타일인가? if (false == command.tileCell.IsVisit()) { command.tileCell.Visit(); if (_targetTileCell.GetTilePosition().Equals(command.tileCell.GetTilePosition())) { _reverseTileCell = _targetTileCell; return; } for (int direction = 0; direction < (int)eDirection.MAX; direction++) { sTilePosition nextTilePos = new sTilePosition(command.tileCell.GetTileX(), command.tileCell.GetTileY()); TileHelper.GetNextTilePosByDirection((eDirection)direction, ref nextTilePos); TileCell nextTileCell = tileSystem.GetTileCell(nextTilePos); if (((true == tileSystem.CanMoveTileCell(nextTilePos.tileX, nextTilePos.tileY)) && false == nextTileCell.IsVisit()) || (nextTilePos.tileX == _targetTileCell.GetTileX() && nextTilePos.tileY == _targetTileCell.GetTileY())) { float newDistanceFromStart = command.tileCell.GetDistanceFromStart() + command.tileCell.GetDistanceWeight(); float newHeuristic = CalcAstarHeuristic(newDistanceFromStart, nextTileCell, _targetTileCell); if (null == nextTileCell.GetPrevCell()) { nextTileCell.SetDistanceFromStart(newDistanceFromStart); nextTileCell.SetPrevCell(command.tileCell); //이전 타일 기억 sPathCommand newCommand = new sPathCommand(); newCommand.heuristic = newHeuristic; newCommand.tileCell = nextTileCell; PushCommand(newCommand); } } } } } }
void UpdateMove() { if (_character.IsMovePossible()) { _eMoveState = eMoveState.END; } switch (_eMoveState) { case eMoveState.START: if (0 != _pathfindingStack.Count) { _nextTileCell = _pathfindingStack.Pop(); sPosition curPosition; curPosition.x = _character.GetTileX(); curPosition.y = _character.GetTileY(); sPosition toPosition; toPosition.x = _nextTileCell.GetTileX(); toPosition.y = _nextTileCell.GetTileY(); _direction = _character.GetDirection(curPosition, toPosition); _character.SetAnimation(_direction.ToString().ToLower()); } else { //상태 변경 MoveFinish(); return; } _eMoveState = eMoveState.MOVE; break; case eMoveState.MOVE: MoveInterpolation(); //보간 break; case eMoveState.END: _character.MoveTileCell(_nextTileCell); _characterVector = _character.GetPosition(); _eMoveState = eMoveState.START; break; default: break; } }
void MoveAction() { TileCell targetCell = _character.GetTargetTileCell(); if (null == targetCell) { return; } if (!(targetCell.GetTileX() == _character.GetTileX() && targetCell.GetTileY() == _character.GetTileY())) { if (_rangeViewer.CheckRange(targetCell)) { _nextState = eStateType.PATHFINDING; } } }
public override void Update() { base.Update(); if (_character.GetMoveSpeed() <= _movingDuration) { _movingDuration = 0.0f; if (0 != _pathTileCellStack.Count) { TileCell tileCell = _pathTileCellStack.Pop(); sPosition curPosition; curPosition.x = _character.GetTileX(); curPosition.y = _character.GetTileY(); sPosition nextPosition; nextPosition.x = tileCell.GetTileX(); nextPosition.y = tileCell.GetTileY(); eMoveDirection direction = GlobalUtility.GetDirection(curPosition, nextPosition); _character.SetNextDirection(direction); if (GameManager.Instance.GetMap().CanMoveTile(nextPosition.x, nextPosition.y)) { _character.MoveStart(nextPosition.x, nextPosition.y); } else { _nextState = eStateType.IDLE; } } else { _nextState = eStateType.IDLE; } } else { _movingDuration += Time.deltaTime; } }
public void FindPath(eFindMode mode, eFindMethod method) { bool isViewRange = (eFindMode.VIEW_MOVERANGE == mode || eFindMode.VIEW_ATTACKRANGE == mode); while (0 != _pathfindingQueue.Count) { sPathCommand command = _pathfindingQueue[0]; _pathfindingQueue.RemoveAt(0); if (false == command.tileCell.IsVisit()) { command.tileCell.Visit(); //FIND TARGET if (eFindMode.FIND_PATH == mode) { if ((_targetTileCell.GetTileX() == command.tileCell.GetTileX()) && (_targetTileCell.GetTileY() == command.tileCell.GetTileY())) { _reverseTileCell = _targetTileCell; return; } } for (eMoveDirection direction = 0; direction <= eMoveDirection.DOWN; direction++) { sPosition curPosition; curPosition.x = command.tileCell.GetTileX(); curPosition.y = command.tileCell.GetTileY(); sPosition nextPosition = GlobalUtility.GetPositionByDirection(curPosition, direction); TileMap map = GameManager.Instance.GetMap(); TileCell nextTileCell = map.GetTileCell(nextPosition.x, nextPosition.y); if (CheckPrecondition(mode, nextTileCell, _targetTileCell)) { float distanceFromStart = command.tileCell.GetDistanceFromStart() + command.tileCell.GetDistanceWeight(); float heuristic = CalcHeuristic(method, distanceFromStart, command.tileCell, nextTileCell, _targetTileCell); if (isViewRange && (_range < distanceFromStart)) { return; } if (null == nextTileCell.GetPrevTileCell()) { nextTileCell.SetDistanceFromStart(distanceFromStart); nextTileCell.SetPrevTileCell(command.tileCell); sPathCommand newCommand; newCommand.tileCell = nextTileCell; newCommand.heuristic = heuristic; PushCommand(newCommand); //검색범위를 그려준다. if (isViewRange) { DrawSearchTile(nextTileCell); } } } } } } }
float CalcSimpleHeuristic(TileCell tileCell, TileCell nextTileCell, TileCell goalTileCell) { float heuristic = 0.0f; int diffFromCurrent = 0; int diffFromNext = 0; // x 축 { // 현재 타일부터 목표 까지의 거리 diffFromCurrent = tileCell.GetTileX() - _goalTileCell.GetTileX(); if (diffFromCurrent < 0) { diffFromCurrent = -diffFromCurrent; } // 검사할 타일부터 목표까지의 거리 diffFromNext = nextTileCell.GetTileX() - _goalTileCell.GetTileX(); if (diffFromNext < 0) { diffFromNext = -diffFromNext; } if (diffFromCurrent < diffFromNext) { heuristic += 1.0f; } else if (diffFromNext < diffFromCurrent) { heuristic -= 1.0f; } } // y 축 { // 현재 타일부터 목표 까지의 거리 diffFromCurrent = tileCell.GetTileY() - _goalTileCell.GetTileY(); if (diffFromCurrent < 0) { diffFromCurrent = -diffFromCurrent; } // 검사할 타일부터 목표까지의 거리 diffFromNext = nextTileCell.GetTileY() - _goalTileCell.GetTileY(); if (diffFromNext < 0) { diffFromNext = -diffFromNext; } if (diffFromCurrent < diffFromNext) { heuristic += 1.0f; } else if (diffFromNext < diffFromCurrent) { heuristic -= 1.0f; } } return(heuristic); }
public void UpdatePathFinding() { if (_pathFindingQueue.Count != 0) { sPathCommand command = PopCommand(); if (command.tileCell.Marked() == false) { command.tileCell.Mark(); if (command.tileCell.CanMove() == true) { command.tileCell.SetPathFindingTestMark(Color.blue); } else if (command.tileCell.CanMove() == false) { command.tileCell.SetPathFindingTestMark(Color.red); } if (command.tileCell.GetDistanceFromStart() > 5) { _reverseTileCell = command.tileCell; _updateState = eUpdateState.BUILD; return; } // 목표 도달? if (command.tileCell.GetTileX() == _targetTileCell.GetTileX() && command.tileCell.GetTileY() == _targetTileCell.GetTileY()) { _updateState = eUpdateState.BUILD; _reverseTileCell = _targetTileCell; return; } // 주변 타일 검사 for (int direction = (int)eMoveDirection.UP; direction < (int)eMoveDirection.NONE; direction++) { sPosition currentTilePosition; currentTilePosition.x = command.tileCell.GetTileX(); currentTilePosition.y = command.tileCell.GetTileY(); sPosition nextTilePos = GetPositionByDirection(currentTilePosition, (eMoveDirection)direction); TileCell nextTileCell = GameManager.Instance.GetMap().GetTileCell(nextTilePos.x, nextTilePos.y); //nextTileCell.SetPathFindingTestMark(Color.red); // 검사 한타일인지 && 이동 가능한 타일 인지 && 갈수 없는 노드의 타입이 혹시 몬스터? -> 리팩토링하고싶다ㅏㅏ if ((nextTileCell.IsPathFindable() == true && nextTileCell.Marked() == false)) { float distanceFromStart = command.tileCell.GetDistanceFromStart() + command.tileCell.GetDistanceWeight() + 1; //float heuristic = CalcAStarHeuristic(distanceFromStart, nextTileCell, _targetTileCell); float heuristic = 0; switch (_character.GetPathFindingType()) { case ePathFindingType.DISTANCE: heuristic = distanceFromStart; break; case ePathFindingType.SIMPLE: heuristic = CalcSimpleHeuristic(command.tileCell, nextTileCell, _targetTileCell); break; case ePathFindingType.COMPLEX: heuristic = CalcComplexHeuristic(nextTileCell, _targetTileCell); break; case ePathFindingType.ASTAR: heuristic = CalcAStarHeuristic(distanceFromStart, nextTileCell, _targetTileCell); break; } if (nextTileCell.GetPrevTileCell() == null) { nextTileCell.SetDistanceFromStart(distanceFromStart); nextTileCell.SetPrevTileCell(command.tileCell); sPathCommand newCommand; newCommand.heuristic = heuristic; newCommand.tileCell = nextTileCell; PushCommand(newCommand); } } } } } }
protected void UpdatePathfinding() { // 길찾기 알고리즘이 시작 if (0 != _pathfindingQueue.Count) { sPathCommand command = _pathfindingQueue[0]; _pathfindingQueue.RemoveAt(0); if (false == command.tileCell.IsPathfided()) { command.tileCell.Pathfinded(); // 목표에 도달 했나? if (command.tileCell.GetTileX() == _goalTileCell.GetTileX() && command.tileCell.GetTileY() == _goalTileCell.GetTileY()) { _reverseTileCell = command.tileCell; _updateState = eUpdateState.BUILD_PATH; return; } for (int direction = (int)eMoveDirection.LEFT; direction < (int)eMoveDirection.DOWN + 1; direction++) { sPosition curPosition; curPosition.x = command.tileCell.GetTileX(); curPosition.y = command.tileCell.GetTileY(); sPosition nextPosition = GetPositionByDirection(curPosition, (eMoveDirection)direction); TileCell searchTileCell = GameManager.Instance.GetMap().GetTileCell(nextPosition.x, nextPosition.y); if (null != searchTileCell && searchTileCell.IsPathfindable() && false == searchTileCell.IsPathfided()) { float distance = command.tileCell.GetDistanceFromStart() + searchTileCell.GetDistanceWeight(); if (null == searchTileCell.GetPrevPathfindingCell()) { searchTileCell.SetDistanceFromStart(distance); searchTileCell.SetPrevPathfindingCell(command.tileCell); searchTileCell.SetPathfindingTestMark(); sPathCommand newCommand; newCommand.tileCell = searchTileCell; /* * newCommand.heuristic = CalcSimpleHeuristic( * command.tileCell, * searchTileCell, * _goalTileCell); */ newCommand.heuristic = CalcAStarHeuristic(distance, searchTileCell, _goalTileCell); PushCommand(newCommand); } else { if (distance < searchTileCell.GetDistanceFromStart()) { searchTileCell.SetDistanceFromStart(distance); searchTileCell.SetPrevPathfindingCell(command.tileCell); sPathCommand newCommand; newCommand.tileCell = searchTileCell; /* * newCommand.heuristic = CalcSimpleHeuristic( * command.tileCell, * searchTileCell, * _goalTileCell); */ newCommand.heuristic = CalcAStarHeuristic(distance, searchTileCell, _goalTileCell); PushCommand(newCommand); } } } } } } }
//타일좌표 뺀 값을 방향벡터로 변환 public static Vector2Int GetDirectionVector(TileCell from, TileCell to) { int x = to.GetTileX() - from.GetTileX(); int y = to.GetTileY() - from.GetTileY(); if (x > 1) { x = 1; } if (x < -1) { x = -1; } if (y > 1) { y = 1; } if (y < -1) { y = -1; } Vector2Int direction = Vector2Int.zero; if (x == 1 && y == 1) //NORTH(0,1) { direction.x = 0; direction.y = 1; } else if (x == -1 && y == -1) //SOUTH(0,-1) { direction.x = 0; direction.y = -1; } else if (x == 1 && y == -1) //EAST(1,0) { direction.x = 1; direction.y = 0; } else if (x == -1 && y == 1) //WEST(-1,0) { direction.x = -1; direction.y = 0; } else if (x == 1 && y == 0) //NORTH_EAST(1,1) { direction.x = 1; direction.y = 1; } else if (x == 0 && y == 1) //NORTH_WEST(-1,1) { direction.x = -1; direction.y = 1; } else if (x == 0 && y == -1) //SOUTH_EAST(1,-1) { direction.x = 1; direction.y = -1; } else if (x == -1 && y == 0) //SOUTH_WEST(-1,-1) { direction.x = -1; direction.y = -1; } return(direction); }