public bool pointInMaze(QVector2Int point)
        {
            bool inMaze        = point.x >= 0 && point.x < mazeWidth && point.y >= 0 && point.y < mazeHeight;
            bool notInObstacle = !QListUtil.has(obstaclePointList, point);

            return(inMaze && notInObstacle);
        }
 private void generateFinishPoint()
 {
     if (generateFinishCount > 0)
     {
         finishPointList.Clear();
     }
     for (int i = 0; i < generateFinishCount; i++)
     {
         QVector2Int newFinishPoint = new QVector2Int(QMath.getRandom(0, mazeWidth), QMath.getRandom(0, mazeHeight));
         while (QListUtil.has(startPointList, newFinishPoint) || QListUtil.has(finishPointList, newFinishPoint))
         {
             newFinishPoint.x = QMath.getRandom(0, mazeWidth);
             newFinishPoint.y = QMath.getRandom(0, mazeHeight);
         }
         finishPointList.Add(newFinishPoint);
     }
 }
        private int checkStartFinishPoint(QVector2Int currentPosition, QVector2Int newPosition, List <QMazeOutput> newPositionOutputs, QMazeOutputDirection dir)
        {
            if (QListUtil.has(startPointList, newPosition) || QListUtil.has(finishPointList, newPosition))
            {
                if (mazeArray[newPosition.x][newPosition.y] == null)
                {
                    QMazeOutput output = mazeArray[currentPosition.x][currentPosition.y][mazeArray[currentPosition.x][currentPosition.y].Count - 1];
                    output.outputDirList.Add(dir);

                    output = new QMazeOutput();
                    output.outputDirList.Add(QMazeOutput.opposite[dir]);
                    mazeArray[newPosition.x][newPosition.y] = new List <QMazeOutput>();
                    mazeArray[newPosition.x][newPosition.y].Add(output);
                }
                return(CHECK_CONTINUE);
            }
            else if (QListUtil.has(startPointList, currentPosition) || QListUtil.has(finishPointList, currentPosition))
            {
                return(CHECK_BREAK);
            }
            return(CHECK_FAILED);
        }
        private IEnumerator generate(bool generateWithGeometry = true, bool asynchronous = true, float maxTime = 0.1f)
        {
            generationProgress = 0;

            generateStartPoint();
            generateFinishPoint();

            QVector2Int startGenerationPoint = new QVector2Int(QMath.getRandom(0, mazeWidth), QMath.getRandom(0, mazeHeight));

            while (QListUtil.has(startPointList, startGenerationPoint) ||
                   QListUtil.has(finishPointList, startGenerationPoint) ||
                   QListUtil.has(obstaclePointList, startGenerationPoint))
            {
                startGenerationPoint.x = QMath.getRandom(0, mazeWidth);
                startGenerationPoint.y = QMath.getRandom(0, mazeHeight);
            }

            path      = new List <QVector2Int>();
            mazeArray = new List <QMazeOutput> [mazeWidth][];
            for (int px = 0; px < mazeWidth; px++)
            {
                mazeArray[px] = new List <QMazeOutput> [mazeHeight];
            }

            lastDirection = QMazeOutputDirection.None;
            QVector2Int currentPosition = new QVector2Int(startGenerationPoint.x, startGenerationPoint.y);

            QMazeOutput output = new QMazeOutput();

            mazeArray[currentPosition.x][currentPosition.y] = new List <QMazeOutput>();
            mazeArray[currentPosition.x][currentPosition.y].Add(output);

            path.Add(new QVector2Int(currentPosition.x, currentPosition.y));

            checkTaskList.Clear();
            if (startPointList.Count > 0 || finishPointList.Count > 0)
            {
                checkTaskList.Add(checkStartFinishPoint);
            }
            checkTaskList.Add(checkStandard);
            if (piecePack.getPiece(QMazePieceType.Intersection).use)
            {
                checkTaskList.Add(checkUnder);
            }
            if (piecePack.getPiece(QMazePieceType.Crossing).use&& !onlyWay)
            {
                checkTaskList.Add(checkCrossing);
            }
            if (piecePack.getPiece(QMazePieceType.Triple).use&& !onlyWay)
            {
                checkTaskList.Add(checkTripple);
            }
            if (piecePack.getPiece(QMazePieceType.DoubleCorner).use)
            {
                checkTaskList.Add(checkDoubleCorner);
            }
            if (piecePack.getPiece(QMazePieceType.DeadlockCorner).use)
            {
                checkTaskList.Add(checkDeadlockCorner);
            }
            if (piecePack.getPiece(QMazePieceType.DeadlockLine).use)
            {
                checkTaskList.Add(checkDeadlockLine);
            }
            if (piecePack.getPiece(QMazePieceType.DeadlockTriple).use)
            {
                checkTaskList.Add(checkDeadlockTriple);
            }
            if (piecePack.getPiece(QMazePieceType.DeadlockCrossing).use)
            {
                checkTaskList.Add(checkDeadlockCrossing);
            }
            if (piecePack.getPiece(QMazePieceType.TripleDeadlock).use)
            {
                checkTaskList.Add(checkTripleDeadlock);
            }
            if (piecePack.getPiece(QMazePieceType.LineDeadlock).use)
            {
                checkTaskList.Add(checkLineDeadlock);
            }
            if (piecePack.getPiece(QMazePieceType.LineDeadlockLine).use)
            {
                checkTaskList.Add(checkLineDeadlockLine);
            }
            if (piecePack.getPiece(QMazePieceType.CornerDeadlock1).use)
            {
                checkTaskList.Add(checkCornerDeadlock1);
            }
            if (piecePack.getPiece(QMazePieceType.CornerDeadlock2).use)
            {
                checkTaskList.Add(checkCornerDeadlock2);
            }
            if (piecePack.getPiece(QMazePieceType.CornerDeadlockCorner).use)
            {
                checkTaskList.Add(checkCornerDeadlockCorner);
            }
            if (piecePack.getPiece(QMazePieceType.Empty).use)
            {
                checkTaskList.Add(checkEmpty);
            }

            float time = Time.realtimeSinceStartup;

            do
            {
                int lastPathIndex = path.Count - 1;
                currentPosition.set(path[lastPathIndex].x, path[lastPathIndex].y);

                lastDirection = QMazeOutputDirection.None;
                QMazeOutput outputArray = QMazeOutput.getShuffleOutput();

                foreach (QMazeOutputDirection dir in outputArray.outputDirList)
                {
                    QVector2Int newPosition = new QVector2Int(currentPosition.x + QMazeOutput.dx[dir], currentPosition.y + QMazeOutput.dy[dir]);
                    if (pointInMaze(newPosition))
                    {
                        if (mazeArray[currentPosition.x][currentPosition.y].Count == 1)
                        {
                            List <QMazeOutput> newPositionOutputs = mazeArray[newPosition.x][newPosition.y];

                            int checkResult = 0;
                            for (int i = 0; i < checkTaskList.Count; i++)
                            {
                                CheckTask checkTask = checkTaskList[i];
                                checkResult = checkTask(currentPosition, newPosition, newPositionOutputs, dir);
                                if (checkResult != CHECK_FAILED)
                                {
                                    break;
                                }
                            }

                            if (checkResult == CHECK_CONTINUE)
                            {
                                continue;
                            }
                            if (checkResult == CHECK_BREAK)
                            {
                                generationProgress++;
                                break;
                            }
                        }
                    }
                    else if (QListUtil.has(exitPointList, newPosition))
                    {
                        if (!mazeArray[currentPosition.x][currentPosition.y][0].outputDirList.Contains(dir))
                        {
                            mazeArray[currentPosition.x][currentPosition.y][0].outputDirList.Add(dir);
                        }
                    }
                }

                if (lastDirection == QMazeOutputDirection.None)
                {
                    path.RemoveAt(path.Count - 1);
                }

                if (asynchronous && Time.realtimeSinceStartup - time > maxTime)
                {
                    time = Time.realtimeSinceStartup;
                    yield return(null);
                }
            }while (path.Count > 0);

            if (generateWithGeometry && mazeGeometryGenerator != null)
            {
                if (asynchronous)
                {
                    yield return(StartCoroutine(mazeGeometryGenerator.generateGeometry(this, mazeArray, maxTime)));
                }
                else
                {
                    IEnumerator geometryCreatorEnumerator = mazeGeometryGenerator.generateGeometry(this, mazeArray, maxTime);
                    while (geometryCreatorEnumerator.MoveNext())
                    {
                        ;
                    }
                }
            }
        }
예제 #5
0
        public IEnumerator generateGeometry(QMazeEngine mazeEngine, List <QMazeOutput>[][] mazeArray, float maxTime = 0.1f)
        {
            Vector3    transformPosition = transform.position;
            Quaternion transformRotation = transform.rotation;

            transform.rotation = Quaternion.identity;

            float time       = Time.realtimeSinceStartup;
            int   mazeWidth  = mazeEngine.mazeWidth;
            int   mazeHeight = mazeEngine.mazeHeight;
            float mazeSize   = mazeWidth * mazeHeight;
            float count      = 0;

            instantiatingProgress = 0;
            bool wasError = false;

            QMazePiecePack    piecePack = mazeEngine.piecePack;
            List <QMazePiece> pieces    = piecePack.toMazePieceList();

            for (int i = 0; i < pieces.Count; i++)
            {
                if ((!pieces[i].use && !pieces[i].require) ||
                    pieces[i].type == QMazePieceType.Start ||
                    pieces[i].type == QMazePieceType.Finish)
                {
                    pieces.RemoveAt(i);
                    i--;
                }
            }

            for (int ix = 0; ix < mazeWidth; ix++)
            {
                for (int iy = 0; iy < mazeHeight; iy++)
                {
                    List <QMazeOutput> mazeOutputData = mazeArray[ix][iy];

                    QMazePiece targetPiece = null;

                    if (QListUtil.has(mazeEngine.startPointList, ix, iy) && mazeOutputData != null && piecePack.getPiece(QMazePieceType.Start).checkFit(mazeOutputData))
                    {
                        targetPiece = piecePack.getPiece(QMazePieceType.Start);
                    }
                    else if (QListUtil.has(mazeEngine.finishPointList, ix, iy) && mazeOutputData != null && piecePack.getPiece(QMazePieceType.Finish).checkFit(mazeOutputData))
                    {
                        targetPiece = piecePack.getPiece(QMazePieceType.Finish);
                    }
                    else
                    {
                        QListUtil.Shuffle <QMazePiece>(pieces);
                        for (int i = 0; i < pieces.Count; i++)
                        {
                            if (pieces[i].checkFit(mazeOutputData))
                            {
                                targetPiece = pieces[i];
                                break;
                            }
                        }
                    }

                    if (targetPiece == null)
                    {
                        if (mazeEngine.pointInMaze(new QVector2Int(ix, iy)) || mazeEngine.obstacleIsEmpty)
                        {
                            targetPiece = piecePack.getPiece(QMazePieceType.Empty);
                        }
                        else
                        {
                            continue;
                        }
                    }
                    else if (targetPiece.geometryList.Count == 0)
                    {
                        if (mazeEngine.pointInMaze(new QVector2Int(ix, iy)))
                        {
                            if (!wasError)
                            {
                                wasError = true;
                                Debug.LogWarning("QMaze: Geometry for " + targetPiece.type + " piece is not found. Please check that geometry is specified for it in the piece pack.");
                            }
                        }
                        continue;
                    }

                    GameObject prefab = targetPiece.geometryList[QMath.getRandom(0, targetPiece.geometryList.Count)];
                    GameObject go;
                                        #if UNITY_EDITOR
                    if (Application.isPlaying)
                    {
                        go = (GameObject)GameObject.Instantiate(prefab, new Vector3(), Quaternion.AngleAxis(randomPiecesRotation ? ((int)(UnityEngine.Random.value * 360 / 90)) * 90 : -targetPiece.getRotation(), Vector3.up));
                    }
                    else
                    {
                        go = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
                        go.transform.rotation = Quaternion.AngleAxis(randomPiecesRotation ? ((int)(UnityEngine.Random.value * 360 / 90)) * 90 : -targetPiece.getRotation(), Vector3.up);
                    }
                                        #else
                    go = (GameObject)GameObject.Instantiate(prefab, new Vector3(), Quaternion.AngleAxis(randomPiecesRotation ? ((int)(UnityEngine.Random.value * 360 / 90)) * 90 : -targetPiece.getRotation(), Vector3.up));
                                        #endif
                    go.transform.position = transformPosition + new Vector3(ix * mazeEngine.mazePieceWidth, 0, -iy * mazeEngine.mazePieceHeight);
                    Vector3 scale = go.transform.localScale;
                    go.transform.parent     = transform;
                    go.transform.localScale = scale;

                    count++;
                    instantiatingProgress = count / mazeSize;

                    if (Time.realtimeSinceStartup - time > maxTime)
                    {
                        time = Time.realtimeSinceStartup;
                        yield return(null);
                    }
                }
            }

            transform.rotation = transformRotation;
        }