/// <summary> /// Return a list of path nodes from the start tile to the end tile ( Use RpgMapHelper class to get the tile index ) /// </summary> /// <param name="startIdx"></param> /// <param name="endIdx"></param> /// <returns></returns> public IEnumerator GetRouteFromToAsync(int startIdx, int endIdx) { IPathNode start = GetMapTileNode(startIdx); EndNode = GetMapTileNode(endIdx); return(m_pathFinding.ComputePathAsync(start, EndNode)); }
public MapTileNode GetMapTileNode( int idx ) { MapTileNode mapTileNode; bool wasFound = m_dicTileNodes.TryGetValue(idx, out mapTileNode); if(!wasFound) { mapTileNode = new MapTileNode(idx, this); m_dicTileNodes[idx] = mapTileNode; } return mapTileNode; }
// special case for walls bool _IsWallPassable(MapTileNode neighNode) { AutoTileMap autoTileMap = AutoTileMap.Instance; eTileCollisionType collType = eTileCollisionType.EMPTY; eTileCollisionType collTypeNeigh = eTileCollisionType.EMPTY; for (int iLayer = autoTileMap.GetLayerCount() - 1; iLayer >= 0; --iLayer) { if (autoTileMap.MapLayers[iLayer].LayerType == eLayerType.Ground) { AutoTile autoTile = autoTileMap.GetAutoTile(TileX, TileY, iLayer); AutoTile autoTileNeigh = autoTileMap.GetAutoTile(neighNode.TileX, neighNode.TileY, iLayer); if (autoTile.Id == autoTileNeigh.Id) // you can walk over two wall tiles if they have the same type { if (autoTile.Id >= 0) { return(true); } else { continue; } } else { // collType will keep the first collision type found of type wall or passable if (collType != eTileCollisionType.PASSABLE && collType != eTileCollisionType.WALL) { collType = autoTile.Id >= 0 ? autoTileMap.Tileset.AutotileCollType[autoTile.Id] : eTileCollisionType.EMPTY; } if (collTypeNeigh != eTileCollisionType.PASSABLE && collTypeNeigh != eTileCollisionType.WALL) { collTypeNeigh = autoTileNeigh.Id >= 0 ? autoTileMap.Tileset.AutotileCollType[autoTileNeigh.Id] : eTileCollisionType.EMPTY; } if (collType == eTileCollisionType.PASSABLE && collTypeNeigh == eTileCollisionType.PASSABLE) { return(true); } else if (collType == eTileCollisionType.WALL || collTypeNeigh == eTileCollisionType.WALL) { return(false); } } } } return(true); }
public LinkedList<IPathNode> GetRouteFromTo(int startIdx, int endIdx) { LinkedList<IPathNode> nodeList = new LinkedList<IPathNode>(); if (m_pathFinding.IsComputing) { Debug.LogWarning("PathFinding is already computing. GetRouteFromTo will not be executed!"); } else { IPathNode start = GetMapTileNode(startIdx); EndNode = GetMapTileNode(endIdx); nodeList = m_pathFinding.ComputePath(start, EndNode); } return nodeList; }
/// <summary> /// Return a list of path nodes from the start tile to the end tile ( Use RpgMapHelper class to get the tile index ) /// </summary> /// <param name="startIdx"></param> /// <param name="endIdx"></param> /// <returns></returns> public LinkedList <IPathNode> GetRouteFromTo(int startIdx, int endIdx) { LinkedList <IPathNode> nodeList = new LinkedList <IPathNode>(); if (m_pathFinding.IsComputing) { Debug.LogWarning("PathFinding is already computing. GetRouteFromTo will not be executed!"); } else { IPathNode start = GetMapTileNode(startIdx); EndNode = GetMapTileNode(endIdx); nodeList = m_pathFinding.ComputePath(start, EndNode); //NOTE: the path is given from end to start ( change the order? ) } return(nodeList); }
IEnumerator ComputePath() { m_isComputing = true; IEnumerator coroutine = m_mapPathFinding.GetRouteFromToAsync(m_startTileIdx, m_endTileIdx); while (coroutine.MoveNext()) { yield return(null); } //Debug.Log("GetRouteFromToAsync execution time(ms): " + (Time.realtimeSinceStartup - now) * 1000); PathFinding.FindingParams findingParams = (PathFinding.FindingParams)coroutine.Current; m_path = findingParams.computedPath; //+++find closest node and take next one if possible m_curNode = Path.First; if (m_curNode != null) { Vector3 vPos = transform.position; vPos.z = ((MapTileNode)m_curNode.Value).Position.z; // use same z level while (m_curNode != null && m_curNode.Next != null) { MapTileNode n0 = m_curNode.Value as MapTileNode; MapTileNode n1 = m_curNode.Next.Value as MapTileNode; float distSqr = (vPos - n0.Position).sqrMagnitude; float distSqr2 = (vPos - n1.Position).sqrMagnitude; if (distSqr2 < distSqr) { m_curNode = m_curNode.Next; } else { break; } } // take next one, avoid moving backward in the path if (m_curNode.Next != null) { m_curNode = m_curNode.Next; } } //--- m_isComputing = false; if (OnComputedPath != null) { OnComputedPath(this); } yield return(null); }
public override float GetNeigborMovingCost(int neigborIdx) { float fCost = 1f; //012 // //3X4 // neighbor index positions, X is the position of this node //567 if (neigborIdx == 0 || neigborIdx == 2 || neigborIdx == 5 || neigborIdx == 7) { //check if can reach diagonals as it could be not possible if flank tiles are not passable MapTileNode nodeN = GetNeighbor(1) as MapTileNode; MapTileNode nodeW = GetNeighbor(3) as MapTileNode; MapTileNode nodeE = GetNeighbor(4) as MapTileNode; MapTileNode nodeS = GetNeighbor(6) as MapTileNode; if ( !m_owner.AllowDiagonals || (neigborIdx == 0 && (!nodeN.IsPassable() || !nodeW.IsPassable() || !_IsWallPassable(nodeN) || !_IsWallPassable(nodeW))) || // check North West (neigborIdx == 2 && (!nodeN.IsPassable() || !nodeE.IsPassable() || !_IsWallPassable(nodeN) || !_IsWallPassable(nodeE))) || // check North East (neigborIdx == 5 && (!nodeS.IsPassable() || !nodeW.IsPassable() || !_IsWallPassable(nodeS) || !_IsWallPassable(nodeW))) || // check South West (neigborIdx == 7 && (!nodeS.IsPassable() || !nodeE.IsPassable() || !_IsWallPassable(nodeS) || !_IsWallPassable(nodeE))) // check South East ) { return(PathFinding.k_InfiniteCostValue); } else { fCost = 1.41421356237f; } } else { fCost = 1f; } MapTileNode neighNode = GetNeighbor(neigborIdx) as MapTileNode; if (!_IsWallPassable(neighNode)) { return(PathFinding.k_InfiniteCostValue); } return(fCost); }
protected void FixedUpdate() { if (m_curNode != null) { MapTileNode curTileNode = m_curNode.Value as MapTileNode; AutoTile autoTile = RpgMapHelper.GetAutoTileByPosition(transform.position, 0); if ( (autoTile.TileX != curTileNode.TileX || autoTile.TileY != curTileNode.TileY) || GetDistToTarget(autoTile) > MinDistToMoveNextTarget // wait until min dist is reached ) { Vector3 vSeek = curTileNode.Position; vSeek.z = transform.position.z; // put at this object level if (m_movingBehavior) { if (m_curNode.Next != null) { m_movingBehavior.Seek(vSeek); } else { m_movingBehavior.Arrive(vSeek); } } } else { m_curNode = m_curNode.Next; } } //if (TargetPos != null) //TODO: TargetPos can't be null { int prevTileidx = m_startTileIdx; m_startTileIdx = RpgMapHelper.GetTileIdxByPosition(TargetPos); m_isUpdatePath |= prevTileidx != m_startTileIdx; if (m_isUpdatePath)//|| !m_isComputing) //Removed to keep actor moving until reach the center of the node { m_isUpdatePath = false; m_endTileIdx = RpgMapHelper.GetTileIdxByPosition(transform.position); //now = Time.realtimeSinceStartup; StopCoroutine("ComputePath"); StartCoroutine("ComputePath"); } } //+++ Debug for (LinkedListNode <IPathNode> it = Path.First; it != null; it = it.Next) { MapTileNode mapTileNode0 = it.Value as MapTileNode; if (it.Next != null) { MapTileNode mapTileNode1 = it.Next.Value as MapTileNode; Vector3 v0 = mapTileNode0.Position; Vector3 v1 = mapTileNode1.Position; v0.z = transform.position.z; v1.z = transform.position.z; Debug.DrawLine(v0, v1, Color.red); } } //--- }
public IEnumerator GetRouteFromToAsync( int startIdx, int endIdx ) { IPathNode start = GetMapTileNode(startIdx); EndNode = GetMapTileNode(endIdx); return m_pathFinding.ComputePathAsync(start, EndNode); }
// special case for walls bool _IsWallPassable( MapTileNode neighNode ) { AutoTileMap autoTileMap = AutoTileMap.Instance; AutoTileMap.eTileCollisionType collType = AutoTileMap.eTileCollisionType.EMPTY; AutoTileMap.eTileCollisionType collTypeNeigh = AutoTileMap.eTileCollisionType.EMPTY; for (int iLayer = autoTileMap.GetLayerCount() - 1; iLayer >= 0; --iLayer) { if (autoTileMap.MapLayers[iLayer].LayerType == AutoTileMap.eLayerType.Ground) { AutoTileMap.AutoTile autoTile = autoTileMap.GetAutoTile(TileX, TileY, iLayer); AutoTileMap.AutoTile autoTileNeigh = autoTileMap.GetAutoTile(neighNode.TileX, neighNode.TileY, iLayer); if (autoTile.Id == autoTileNeigh.Id) // you can walk over two wall tiles if they have the same type { if (autoTile.Id >= 0) return true; else continue; } else { // collType will keep the first collision type found of type wall or passable if (collType != AutoTileMap.eTileCollisionType.PASSABLE && collType != AutoTileMap.eTileCollisionType.WALL) collType = autoTile.Id >= 0 ? autoTileMap.Tileset.AutotileCollType[autoTile.Id] : AutoTileMap.eTileCollisionType.EMPTY; if (collTypeNeigh != AutoTileMap.eTileCollisionType.PASSABLE && collTypeNeigh != AutoTileMap.eTileCollisionType.WALL) collTypeNeigh = autoTileNeigh.Id >= 0 ? autoTileMap.Tileset.AutotileCollType[autoTileNeigh.Id] : AutoTileMap.eTileCollisionType.EMPTY; if( collType == AutoTileMap.eTileCollisionType.PASSABLE && collTypeNeigh == AutoTileMap.eTileCollisionType.PASSABLE ) { return true; } else if (collType == AutoTileMap.eTileCollisionType.WALL || collTypeNeigh == AutoTileMap.eTileCollisionType.WALL) { return false; } } } } return true; }
// special case for walls bool _IsWallPassable( MapTileNode neighNode ) { bool isPassableAutoTile1 = false; bool isPassableAutoTileNeigh1 = false; for (int iLayer = 1; iLayer >= 0; --iLayer) { AutoTileMap.AutoTile autoTile = AutoTileMap.Instance.GetAutoTile(TileX, TileY, iLayer); AutoTileMap.AutoTile autoTileNeigh = AutoTileMap.Instance.GetAutoTile(neighNode.TileX, neighNode.TileY, iLayer); if (iLayer == 1) { isPassableAutoTile1 = (autoTile.Idx >= 0 && AutoTileMap.Instance.Tileset.AutotileCollType[autoTile.Idx] == AutoTileMap.eTileCollisionType.PASSABLE); isPassableAutoTileNeigh1 = (autoTileNeigh.Idx >= 0 && AutoTileMap.Instance.Tileset.AutotileCollType[autoTileNeigh.Idx] == AutoTileMap.eTileCollisionType.PASSABLE); } if (autoTile.Idx == autoTileNeigh.Idx) // you can walk over two wall tiles if they have the same type { continue; } else { bool isWall = (autoTile.Idx >= 0 && AutoTileMap.Instance.Tileset.AutotileCollType[autoTile.Idx] == AutoTileMap.eTileCollisionType.WALL); bool isWallNeigh = (autoTileNeigh.Idx >= 0 && AutoTileMap.Instance.Tileset.AutotileCollType[autoTileNeigh.Idx] == AutoTileMap.eTileCollisionType.WALL); if (iLayer == 0) { // even if it's a wall, a NONE tile over it make it walkable isWall &= !isPassableAutoTile1; isWallNeigh &= !isPassableAutoTileNeigh1; } if (isWall || isWallNeigh) { return false; } } } return true; }