Пример #1
0
 private static bool IsNavigableGridIndex(GridBitfield blockedTerrain, int2 coords)
 {
     return
         (coords.x >= 0 &&
          coords.y >= 0 &&
          coords.x < Grid.NumCells.x &&
          coords.y < Grid.NumCells.y &&
          !blockedTerrain[coords.x, coords.y]);
 }
Пример #2
0
    //bool first = true;
    protected override unsafe void OnUpdate()
    {
        var entityManager = World.Active.GetOrCreateManager <EntityManager>();

        for (int danglingEnemyIndex = 0; danglingEnemyIndex < m_DanglingEnemyData.Length; ++danglingEnemyIndex)
        {
            m_PathManager.RemovePath(m_DanglingEnemyData.EnemyStates[danglingEnemyIndex].PathId);
            PostUpdateCommands.RemoveComponent <EnemyState>(m_DanglingEnemyData.Entities[danglingEnemyIndex]);
        }

        s_Start = m_SpawnPointData.SpawnPoint[0].GridIndex;
        s_Goal  = m_GoalPointData.GoalPoint[0].GridIndex;
        s_BlockedTerrainCardinal      = new GridBitfield();
        s_BlockedTerrainIntercardinal = new GridBitfield();
        for (int turretIndex = 0; turretIndex < m_TurretData.Length; ++turretIndex)
        {
            int2 turretGridCoords = Grid.ConvertToGridIndex(m_TurretData.Positions[turretIndex].Value);
            s_BlockedTerrainCardinal[turretGridCoords]      = true;
            s_BlockedTerrainIntercardinal[turretGridCoords] = true;
            if (turretGridCoords.x > 0)
            {
                s_BlockedTerrainIntercardinal[turretGridCoords.x - 1, turretGridCoords.y] = true;
            }
            if (turretGridCoords.x < Grid.NumCells.x - 1)
            {
                s_BlockedTerrainIntercardinal[turretGridCoords.x + 1, turretGridCoords.y] = true;
            }
            if (turretGridCoords.y > 0)
            {
                s_BlockedTerrainIntercardinal[turretGridCoords.x, turretGridCoords.y - 1] = true;
            }
            if (turretGridCoords.y < Grid.NumCells.y - 1)
            {
                s_BlockedTerrainIntercardinal[turretGridCoords.x, turretGridCoords.y + 1] = true;
            }
        }

        // clear out all previous paths to force path-recompute if the tower layour has changed
        if (m_PreviousBlockedTerrain != null && m_PreviousBlockedTerrain != s_BlockedTerrainCardinal)
        {
            m_PathManager.ForcePathRecompute();
        }
        m_PreviousBlockedTerrain = s_BlockedTerrainCardinal;

        for (int trackedEnemyIndex = 0; trackedEnemyIndex < m_TrackedEnemyData.Length; ++trackedEnemyIndex)
        {
            float3 currentPos       = m_TrackedEnemyData.Positions[trackedEnemyIndex].Value;
            int2   currentGridIndex = Grid.ConvertToGridIndex(currentPos);
            float3 target           = HandleLiveEnemy(currentGridIndex, m_TrackedEnemyData.EnemyStates[trackedEnemyIndex]);

            if (currentPos.Equals(target))
            {
                List <float3> path = m_PathManager.GetPath(m_TrackedEnemyData.EnemyStates[trackedEnemyIndex].PathId);
                path.RemoveAt(path.Count - 1);
                target = HandleLiveEnemy(currentGridIndex, m_TrackedEnemyData.EnemyStates[trackedEnemyIndex]);
            }

            float3 delta = Time.deltaTime * m_TrackedEnemyData.Enemies[trackedEnemyIndex].Speed * math.normalize(target - currentPos);

            while (WouldDeltaJumpTarget(currentPos, delta, target))
            {
                float3 toTarget           = target - currentPos;
                float  magDelta           = math.length(delta);
                float  normalizedTimeUsed = math.length(toTarget) / magDelta;
                float  distanceLeft       = (1.0f - normalizedTimeUsed) * magDelta;

                List <float3> path = m_PathManager.GetPath(m_TrackedEnemyData.EnemyStates[trackedEnemyIndex].PathId);
                path.RemoveAt(path.Count - 1);

                if (path.Count == 0)
                {
                    if (m_PlayerData.Player[0].gameState.Equals(GameState.PLAYING))
                    {
                        for (int i = 0; i < m_PlayerData.Player.Length; i++)
                        {
                            var playerData = m_PlayerData.Player[i];
                            playerData.Health--;
                            m_PlayerData.Player[i] = playerData;
                        }
                    }
                    PostUpdateCommands.DestroyEntity(m_TrackedEnemyData.Entities[trackedEnemyIndex]);
                    return;
                }

                currentPos = target;
                target     = path[path.Count - 1];
                delta      = distanceLeft * math.normalize(target - currentPos);
            }

            m_TrackedEnemyData.Positions[trackedEnemyIndex] = new Position {
                Value = currentPos + delta
            };
        }

        for (int newEnemyIndex = 0; newEnemyIndex < m_NewEnemyData.Length; ++newEnemyIndex)
        {
            EnemyState enemyState = new EnemyState {
                PathId = m_PathManager.AddPath()
            };
            PostUpdateCommands.AddComponent(m_NewEnemyData.Entities[newEnemyIndex], enemyState);
        }
    }
Пример #3
0
    private static bool TryFindPath(int2 currentGridIndex, out Dictionary <int2, int2> cameFrom, int2?blocker)
    {
        GridBitfield closedSet = new GridBitfield();

        // TODO: clean up the terrible perf incurred from just using an array here
        List <int2> openSet = new List <int2>();

        openSet.Add(currentGridIndex);

        cameFrom = new Dictionary <int2, int2>();

        // nodes have a default value of infinity
        Dictionary <int2, float> gScore = new Dictionary <int2, float>();

        gScore[currentGridIndex] = 0.0f;

        // nodes have a default value of infinity
        Dictionary <int2, float> fScore = new Dictionary <int2, float>();

        fScore[currentGridIndex] = CalcHeurisitic(currentGridIndex, s_Goal);

        while (openSet.Count > 0)
        {
            int bestIndex = 0;
            for (int b = 1; b < openSet.Count; ++b)
            {
                if (CmpNodes(fScore, openSet[bestIndex], openSet[b]) > 0)
                {
                    bestIndex = b;
                }
            }

            int2 currentNode = openSet[bestIndex];
            if (s_Goal.Equals(currentNode))
            {
                return(true);
            }

            openSet.RemoveAt(bestIndex);
            closedSet[currentNode] = true;
            int2[] neighbors    = new int2[8];
            int    numNeighbors = 0;

            int blockedCardinalFlags = 0;
            for (int neighborIndex = 0; neighborIndex < s_NeighborOffsetsCardinal.Length; ++neighborIndex)
            {
                int2 neighbor = currentNode + s_NeighborOffsetsCardinal[neighborIndex];
                if (!IsNavigableGridIndex(s_BlockedTerrainCardinal, neighbor) || blocker != null && neighbor.Equals(blocker))
                {
                    blockedCardinalFlags |= 1 << neighborIndex;
                    continue;
                }

                neighbors[numNeighbors] = neighbor;
                ++numNeighbors;
            }

            for (int neighborIndex = 0; neighborIndex < s_NeighborOffsetsIntercardinal.Length; ++neighborIndex)
            {
                int adjacentCardinalFlags = (1 << neighborIndex) | (1 << ((neighborIndex + 1) % 4));
                if (adjacentCardinalFlags == (adjacentCardinalFlags & blockedCardinalFlags))
                {
                    continue;
                }

                int2 neighbor = currentNode + s_NeighborOffsetsIntercardinal[neighborIndex];
                if (!IsNavigableGridIndex(s_BlockedTerrainIntercardinal, neighbor))
                {
                    continue;
                }

                neighbors[numNeighbors] = neighbor;
                ++numNeighbors;
            }

            for (int neighborIndex = 0; neighborIndex < numNeighbors; ++neighborIndex)
            {
                if (closedSet[neighbors[neighborIndex]])
                {
                    continue;
                }

                // why doesn't Contains do what it's supposed to...?
                bool exists = false;
                foreach (int2 iv in openSet)
                {
                    if (neighbors[neighborIndex].Equals(iv))
                    {
                        exists = true;
                        break;
                    }
                }
                if (!exists)
                {
                    openSet.Add(neighbors[neighborIndex]);
                }

                float tentativeScoreFromStart = gScore[currentNode] + math.length(currentNode - neighbors[neighborIndex]);

                float scoreFromStartToNeighbor = float.MaxValue;
                if (gScore.ContainsKey(neighbors[neighborIndex]))
                {
                    scoreFromStartToNeighbor = gScore[neighbors[neighborIndex]];
                }
                if (tentativeScoreFromStart >= scoreFromStartToNeighbor)
                {
                    continue;
                }

                cameFrom[neighbors[neighborIndex]] = currentNode;
                gScore[neighbors[neighborIndex]]   = tentativeScoreFromStart;
                fScore[neighbors[neighborIndex]]   = tentativeScoreFromStart + CalcHeurisitic(neighbors[neighborIndex], s_Goal);
            }
        }

        return(false);
    }