コード例 #1
0
ファイル: Class_Node_Spider.cs プロジェクト: hand32/Mechanity
        public List <SpiderNode> FindNextNode(List <SpiderNode> nodes, Spider _monster)
        {
            List <SpiderNode> _connectNodeList = new List <SpiderNode>();

            if (parentNode == this)
            {
                List <DirandRot> _canMoveVectors = _monster.FindCanMoveVectors(this);
                foreach (DirandRot _DR in _canMoveVectors)
                {
                    if (_DR == null)
                    {
                        continue;
                    }
                    foreach (DirandRot _parentDR in _monster.FindCollisionVectors())
                    {
                        if (_parentDR == null)
                        {
                            continue;
                        }
                        parentDR = _parentDR;
                        Vector2   nextNodePosition = this.position;
                        DirandRot downDR;
                        if (parentDR.rot.eulerAngles.y == 0f)
                        {
                            downDR = new DirandRot(new Vector2(parentDR.dir.y, -parentDR.dir.x),
                                                   Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z - 90f));
                        }
                        else
                        {
                            downDR = new DirandRot(new Vector2(-parentDR.dir.y, parentDR.dir.x),
                                                   Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z - 90f));
                        }

                        DirandRot checkDR;
                        checkDR = new DirandRot(new Vector2(-parentDR.dir.y, parentDR.dir.x),
                                                parentDR.rot.eulerAngles.y == 0f ? Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z + 90f)
                                                                                                                        : Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z - 90f));


                        if (_DR == parentDR)                // 직진할 경우
                        {
                            bool isFloorExist = true;
                            foreach (DirandRot d in _canMoveVectors)
                            {
                                if (d == null)
                                {
                                    continue;
                                }
                                if (d == downDR)                        // 바닥이 없을 경우.
                                {
                                    isFloorExist = false;
                                    break;
                                }
                            }
                            if (isFloorExist)
                            {
                                nextNodePosition = this.position + _DR.dir;
                                checkDR          = parentDR;
                            }
                        }
                        if (this.position == nextNodePosition && _DR == checkDR)                //반시계 90도 회전.
                        {
                            bool canTurn = true;
                            if (parentDR.rot.eulerAngles.y != 0f)
                            {
                                foreach (DirandRot d in _canMoveVectors)
                                {
                                    if (d == null)
                                    {
                                        continue;
                                    }
                                    if (d == downDR)                            // 바닥이 없을 경우.
                                    {
                                        canTurn = false;
                                        break;
                                    }
                                    else if (d == parentDR)                            // 앞쪽 벽이 없을 경우.
                                    {
                                        canTurn = false;
                                        break;
                                    }
                                }
                            }
                            if (canTurn)
                            {
                                nextNodePosition = this.position + checkDR.dir;
                            }
                        }
                        else if (this.position == nextNodePosition)
                        {                 // 시계 90도 회전. 아마도.
                            checkDR = new DirandRot(new Vector2(parentDR.dir.y, -parentDR.dir.x),
                                                    parentDR.rot.eulerAngles.y == 0f ? Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z - 90f)
                                                                                                                                : Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z + 90f));
                            if (_DR == checkDR)                    //가는 경로 바닥에 타일 있는지 확인 조건 추가.
                            {
                                bool canTurn = true;
                                if (parentDR.rot.eulerAngles.y == 0f)
                                {
                                    foreach (DirandRot d in _canMoveVectors)
                                    {
                                        if (d == null)
                                        {
                                            continue;
                                        }
                                        if (d == downDR)                                // 바닥이 없을 경우.
                                        {
                                            canTurn = false;
                                            break;
                                        }
                                        else if (d == parentDR)                                // 앞쪽 벽이 없을 경우.
                                        {
                                            canTurn = false;
                                            break;
                                        }
                                    }
                                }
                                if (canTurn)
                                {
                                    nextNodePosition = this.position + checkDR.dir;
                                }
                            }
                        }

                        if (nextNodePosition != this.position)
                        {
                            foreach (SpiderNode _node in nodes)
                            {
                                if (_node.position == nextNodePosition)
                                {
                                    _node.parentDR = new DirandRot(checkDR.dir, checkDR.rot);
                                    _connectNodeList.Add(_node);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                foreach (DirandRot _DR in canMoveVectors)
                {
                    if (_DR == null)
                    {
                        continue;
                    }
                    Vector2   nextNodePosition = this.position;
                    DirandRot downDR;
                    if (parentDR.rot.eulerAngles.y == 0f)
                    {
                        downDR = new DirandRot(new Vector2(parentDR.dir.y, -parentDR.dir.x),
                                               Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z - 90f));
                    }
                    else
                    {
                        downDR = new DirandRot(new Vector2(-parentDR.dir.y, parentDR.dir.x),
                                               Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z - 90f));
                    }

                    DirandRot checkDR;
                    checkDR = new DirandRot(new Vector2(-parentDR.dir.y, parentDR.dir.x),
                                            parentDR.rot.eulerAngles.y == 0f ? Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z + 90f)
                                                                                                                : Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z - 90f));


                    if (_DR == parentDR)            // 직진할 경우
                    {
                        bool isFloorExist = true;
                        foreach (DirandRot d in canMoveVectors)
                        {
                            if (d == null)
                            {
                                continue;
                            }
                            if (d == downDR)                    // 바닥이 없을 경우.
                            {
                                isFloorExist = false;
                                break;
                            }
                        }
                        if (isFloorExist)
                        {
                            nextNodePosition = this.position + _DR.dir;
                            checkDR          = parentDR;
                        }
                    }
                    if (this.position == nextNodePosition && _DR == checkDR)            //반시계 90도 회전.
                    {
                        bool canTurn = true;
                        if (parentDR.rot.eulerAngles.y != 0f)
                        {
                            foreach (DirandRot d in canMoveVectors)
                            {
                                if (d == null)
                                {
                                    continue;
                                }
                                if (d == downDR)                        // 바닥이 없을 경우.
                                {
                                    canTurn = false;
                                    break;
                                }
                                else if (d == parentDR)                        // 앞쪽 벽이 없을 경우.
                                {
                                    canTurn = false;
                                    break;
                                }
                            }
                        }
                        if (canTurn)
                        {
                            nextNodePosition = this.position + checkDR.dir;
                        }
                    }
                    else if (this.position == nextNodePosition)
                    {             // 시계 90도 회전. 아마도.
                        checkDR = new DirandRot(new Vector2(parentDR.dir.y, -parentDR.dir.x),
                                                parentDR.rot.eulerAngles.y == 0f ? Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z - 90f)
                                                                                                                        : Quaternion.Euler(parentDR.rot.eulerAngles.x, parentDR.rot.eulerAngles.y, parentDR.rot.eulerAngles.z + 90f));
                        if (_DR == checkDR)                //가는 경로 바닥에 타일 있는지 확인 조건 추가.
                        {
                            bool canTurn = true;
                            if (parentDR.rot.eulerAngles.y == 0f)
                            {
                                foreach (DirandRot d in canMoveVectors)
                                {
                                    if (d == null)
                                    {
                                        continue;
                                    }
                                    if (d == downDR)                            // 바닥이 없을 경우.
                                    {
                                        canTurn = false;
                                        break;
                                    }
                                    else if (d == parentDR)                            // 앞쪽 벽이 없을 경우.
                                    {
                                        canTurn = false;
                                        break;
                                    }
                                }
                            }
                            if (canTurn)
                            {
                                nextNodePosition = this.position + checkDR.dir;
                            }
                        }
                    }

                    if (nextNodePosition != this.position)
                    {
                        foreach (SpiderNode _node in nodes)
                        {
                            if (_node.position == nextNodePosition)
                            {
                                _node.parentDR = new DirandRot(checkDR.dir, checkDR.rot);
                                _connectNodeList.Add(_node);
                                break;
                            }
                        }
                    }
                }
            }

            if (_connectNodeList.Count == 0)
            {
                Debug.Log(this.position + " : this SpiderNode can't find connected Node!");
            }

            return(_connectNodeList);
        }
コード例 #2
0
        public DirandRot GetNextNode(Spider _monster)
        {
            int loopcount            = 0;
            List <SpiderNode> _nodes = new List <SpiderNode>(nodes);

            List <SpiderNode> nodeOpenList   = new List <SpiderNode>();
            List <SpiderNode> nodeClosedList = new List <SpiderNode>();


            // 플레이어가 공중에 있을때 원래 있던 땅 자리를 목적지로 만드려는 것.
            Vector2 playerNodePosition = new Vector2();
            int     playerXindex       = Mathf.FloorToInt(playerPosition.position.x + 0.5f + offsetX);
            int     playerYindex       = Mathf.FloorToInt(playerPosition.position.y + 0.5f + offsetY);

            for (int i = 0; i < (platformTiles[playerXindex].Count - playerYindex); i++)
            {
                if (platformTiles[playerXindex][playerYindex - i - 1].exist)
                {
                    playerNodePosition = new Vector2(playerXindex - offsetX, playerYindex - i - offsetY);
                    break;
                }

                else if (Mathf.Abs(playerXindex - offsetX - playerPosition.position.x) + playerColliderSizeX / 2 > 0.5f)
                {
                    int _playerXindex = playerXindex + (playerXindex - offsetX - playerPosition.position.x > 0 ? -1 : 1);
                    if (platformTiles[_playerXindex][playerYindex - i - 1].exist && !platformTiles[_playerXindex][playerYindex - i].exist)
                    {
                        playerNodePosition = new Vector2(_playerXindex - offsetX, playerYindex - i - offsetY);
                        break;
                    }
                }
            }
            SpiderNode goalNode =
                MakeNode((int)(playerNodePosition.x + offsetX), (int)(playerNodePosition.y + offsetY)
                         , _nodes);

            //현재 길 찾고있는 Spider의 속한 그리드의 중심에 노드를 만들기 위함. 원래 그자리에 노드가 있으면 합침.
            SpiderNode selfNode =
                MakeNode((int)(_monster.GetPosition().x + offsetX), (int)(_monster.GetPosition().y + offsetY)
                         , _nodes);

            if (selfNode == null || goalNode == null) //spider 주변에 벽이 없거나, 플레이어 아래 바닥이 끝까지 없을 때.
            {
                _monster.inGameObject.SendMessage("Fall");
                return(new DirandRot(new Vector2(0, 0), Quaternion.Euler(0, 0, 0)));
            }
            selfNode.parentNode = selfNode;
            selfNode.SetGH(goalNode);
            nodeOpenList.Add(selfNode);

            SpiderNode nearestNode = null;

            while (loopcount < 100)
            {
                loopcount++;
                float      minF     = Mathf.Infinity;
                SpiderNode minFNode = null;
                foreach (SpiderNode _node in nodeOpenList)
                {
                    float _currentF = _node.GetF();
                    if (minFNode == null || _currentF < minF && _node.H <= _monster.m_Script.spiderInfo.findRadius)
                    {
                        minF     = _currentF;
                        minFNode = _node;
                    }
                    else if (_currentF == minF)
                    {
                        if (Random.Range(0, 2) == 1)
                        {
                            minF     = _currentF;
                            minFNode = _node;
                        }
                    }
                }
                //Debug.Log(minFNode.position +" is 탐색됨. " + minFNode.FindNextNode(_nodes).Count);
                if (!nodeClosedList.Contains(minFNode))
                {
                    nodeClosedList.Add(minFNode);
                }
                nodeOpenList.Remove(minFNode);
                if (nearestNode == null || nearestNode.H > minFNode.H)
                {
                    nearestNode = minFNode;
                }
                foreach (SpiderNode _node in minFNode.FindNextNode(_nodes, _monster))
                {
                    if (!nodeClosedList.Contains(_node))
                    {
                        _node.parentNode = minFNode;
                        if (_node == goalNode)
                        {
                            if (selfNode.position == goalNode.position)
                            {
                                return(new DirandRot(Vector2.zero, new Quaternion()));
                            }
                            SpiderNode getBackNode = _node;
                            loopcount = 0;
                            while (loopcount < 100)
                            {
                                loopcount++;
                                if (getBackNode.parentNode == selfNode)
                                {
                                    return(getBackNode.parentDR);
                                }
                                getBackNode = getBackNode.parentNode;
                            }
                            Debug.Log("Loop count over to Goal Node. " + goalNode.position);
                            return(new DirandRot(Vector2.zero, new Quaternion()));
                        }
                        _node.SetGH(goalNode);
                        if (!nodeOpenList.Contains(_node))
                        {
                            nodeOpenList.Add(_node);
                        }
                    }
                }

                if (nodeOpenList.Count == 0)
                {
                    Debug.Log(_monster.inGameObject.name + " can't find the path.");
                    if (nearestNode.position == selfNode.position)
                    {
                        return(new DirandRot(Vector2.zero, new Quaternion()));
                    }
                    SpiderNode getBackNode = nearestNode;
                    loopcount = 0;
                    while (loopcount < 100)
                    {
                        loopcount++;
                        if (getBackNode.parentNode == selfNode)
                        {
                            return(getBackNode.parentDR);
                        }
                        getBackNode = getBackNode.parentNode;
                    }
                    Debug.Log("Loop count over to Nearest Node.");
                    return(new DirandRot(Vector2.zero, new Quaternion()));
                }
            }
            //Debug.Log("Loop count over in finding path. " + goalNode.position);
            if (nearestNode.position == selfNode.position)
            {
                return(new DirandRot(Vector2.zero, new Quaternion()));
            }
            SpiderNode _getBackNode = nearestNode;

            loopcount = 0;
            while (loopcount < 100)
            {
                loopcount++;
                if (_getBackNode.parentNode == selfNode)
                {
                    return(_getBackNode.parentDR);
                }
                _getBackNode = _getBackNode.parentNode;
            }
            Debug.Log("Can't Find Anything with " + _monster.inGameObject.name);
            return(new DirandRot(Vector2.zero, new Quaternion()));
        }