Ejemplo n.º 1
0
    private void Start()
    {
#if UNITY_IOS || UNITY_ANDROID
        mobileControls.SetActive(true);
#endif
        fsm = GetComponent <FloodSoundManager>();

        playerCar       = player.GetComponent <PlayerCar>();
        player.position = startObj.position;
        referenceGraph  = new AdjacencyList <Vector3>(Vector3.zero);
        pathingGraph    = new AdjacencyList <Vector3>(Vector3.zero);


        for (int i = 0; i < numBlocksHorizontal; i++)
        {
            for (int j = 0; j < numBlocksVertical; j++)
            {
                Vector3 pos = new Vector3(i * blockDist, 0, j * blockDist);
                foreach (Vector3 neighbor in GetNeighbors(pos))
                {
                    referenceGraph.AddEdge(pos, neighbor);
                    pathingGraph.AddEdge(pos, neighbor);
                }
            }
        }

        //Remove edges until there is no path found
        List <KeyValuePair <Vector3, Vector3> > removedEdges = new List <KeyValuePair <Vector3, Vector3> >();
        while (AStar(referenceGraph, startObj.position, endObj.position, out List <Vector3> pathIter))
        {
            path = pathIter;
            Vector3        start     = referenceGraph.GetRandomVertex();
            List <Vector3> neighbors = referenceGraph.FindNeighbours(start);
            Vector3        neighbor  = neighbors[Random.Range(0, neighbors.Count)];
            referenceGraph.RemoveEdge(start, neighbor);
            removedEdges.Add(new KeyValuePair <Vector3, Vector3>(start, neighbor));
        }

        //Add the last removed edge back in
        KeyValuePair <Vector3, Vector3> lastEdge = removedEdges.Last();
        removedEdges.RemoveAt(removedEdges.Count - 1);
        referenceGraph.AddEdge(lastEdge.Key, lastEdge.Value);

        //face the player's car in the direction of the first waypoint
        float startDir = v3ToInt[(path[1] - path[0]).normalized];
        player.eulerAngles = new Vector3(0f, startDir, 0f);

        List <Vector3> startNeighborsMids = referenceGraph.FindNeighbours(startObj.position).Select(i => (startObj.position + i) / 2).ToList();

        //spawn in roadblock prefabs along 3/4s of blocked edges
        int endIdx = removedEdges.Count * 3 / 4;
        for (int i = 0; i < endIdx; i++)
        {
            KeyValuePair <Vector3, Vector3> edge = removedEdges[i];
            GameObject toInstantiate             = staticRoadBlockPrefabs[Random.Range(0, staticRoadBlockPrefabs.Count)];
            Vector3    midpoint = (edge.Key + edge.Value) / 2;
            if (startNeighborsMids.Any(x => x == midpoint))
            {
                continue;
            }

            Quaternion rot = Quaternion.Euler(0f, Mathf.Abs((edge.Key - edge.Value).x) > 0f ? 90f : 0f, 0f);
            Instantiate(toInstantiate, midpoint, rot, obstacles.transform);
            pathingGraph.RemoveEdge(edge.Key, edge.Value);
        }

        //spawn in obstacles along valid edges
        HashSet <Vector3> edgeSet = new HashSet <Vector3>();

        //prevent items from spawning on edges surrounding player's spawn point
        startNeighborsMids.ForEach(i => edgeSet.Add(i));
        foreach (Vector3 vertex in referenceGraph.GetAllEdges())
        {
            foreach (Vector3 neighbor in referenceGraph.FindNeighbours(vertex))
            {
                Vector3 mid = (vertex + neighbor) / 2;
                bool    onX = Mathf.Abs((vertex - neighbor).x) > 0;

                if (!edgeSet.Contains(mid) && Random.Range(0, 2) > 0)
                {
                    GameObject toInstantiate            = roadObstaclePrefabs[Random.Range(0, roadObstaclePrefabs.Count)];
                    float      randStreetOffsetLong     = Random.Range(-blockDist / 2, blockDist / 2);
                    float      randStreetOffsetWide     = Random.Range(-roadWidth / 4, roadWidth / 4);
                    Vector3    boundedRandomPosInStreet = mid;
                    boundedRandomPosInStreet += onX ? new Vector3(randStreetOffsetLong, 0f, randStreetOffsetWide) : new Vector3(randStreetOffsetWide, 0f, randStreetOffsetLong);
                    Quaternion rot = Quaternion.Euler(0f, onX ? Random.Range(60, 120) : Random.Range(-30, 30), 0f);
                    Instantiate(toInstantiate, boundedRandomPosInStreet, rot, obstacles.transform);
                }

                if (!edgeSet.Contains(mid) && Random.Range(0, 3) > 0)
                {
                    GameObject toInstantiate            = puddles[Random.Range(0, puddles.Count)];
                    float      randStreetOffsetLong     = Random.Range(-blockDist / 2, blockDist / 2);
                    float      randStreetOffsetWide     = Random.Range(-roadWidth / 4, roadWidth / 4);
                    Vector3    boundedRandomPosInStreet = mid;
                    boundedRandomPosInStreet += onX ? new Vector3(randStreetOffsetLong, 0f, randStreetOffsetWide) : new Vector3(randStreetOffsetWide, 0f, randStreetOffsetLong);
                    Quaternion rot = Quaternion.Euler(0f, Random.Range(0, 360), 0f);
                    Instantiate(toInstantiate, boundedRandomPosInStreet, rot, obstacles.transform);
                }
                edgeSet.Add(mid);
            }
        }

        fullPathLength = path.Count;
        StartCoroutine(UpdatePathOnDelay(pathUpdateDelay));
        StartCoroutine(EndGameCheckOnDelay(endGameCheckDelay, endObj.position, new Vector3(roadWidth, roadWidth, roadWidth) / 2f, playerLayer));
    }
Ejemplo n.º 2
0
    private static bool AStar(AdjacencyList <Vector3> graph, Vector3 start, Vector3 goal, out List <Vector3> path)
    {
        //make sure that the start and end points are valid points in the graph
        if (!graph.Contains(start) || !graph.Contains(goal))
        {
            path = new List <Vector3>();
            return(false);
        }

        bool success = false;
        Dictionary <Vector3, Vector3> from   = new Dictionary <Vector3, Vector3>();
        HashSet <Vector3>             closed = new HashSet <Vector3>();
        HashSet <Vector3>             open   = new HashSet <Vector3> {
            start
        };

        Dictionary <Vector3, float>          gScore = new Dictionary <Vector3, float>();
        SimplePriorityQueue <Vector3, float> fScore = new SimplePriorityQueue <Vector3, float>();

        gScore.Add(start, 0);
        fScore.Enqueue(start, Vector3.Distance(start, goal));

        while (open.Count > 0)
        {
            Vector3 current = fScore.Dequeue();
            if (current == goal)
            {
                success = true;
                break;
            }

            open.Remove(current);
            closed.Add(current);

            foreach (Vector3 neighbor in graph.FindNeighbours(current))
            {
                if (closed.Contains(neighbor))
                {
                    continue;
                }

                float dist = gScore[current] + Vector3.Distance(current, neighbor);

                if (!open.Contains(neighbor))
                {
                    open.Add(neighbor);
                }
                else if (gScore.ContainsKey(neighbor) && dist >= gScore[neighbor])
                {
                    continue;
                }

                from[neighbor]   = current;
                gScore[neighbor] = dist;
                fScore.Enqueue(neighbor, dist + Vector3.Distance(neighbor, goal));
            }
        }

        path = FormPath(from, goal);
        return(success);
    }