private void ConstructLinks() //步驟3 { currentStatus = GeneratingStatus.Construct_Links; /*此段以上負責狀態更改*/ int len = lvToPut.Length; Vector2Int fromTo = new Vector2Int(-1, -1); for (int i = 0; i < len; i++) { if (lvInform[i].connection == 1 && fromTo.x < 0) { fromTo.x = i; } else if (lvInform[i].connection == 1 && fromTo.y < 0) { fromTo.y = i; } if (fromTo.x >= 0 && fromTo.y >= 0) { BuildLink(fromTo.x, fromTo.y, true); fromTo = new Vector2Int(-1, -1); } } FindPaths(); }
private void Selecting() //步驟1 { currentStatus = GeneratingStatus.Selecting; /*此段以上負責狀態更改*/ int len = levels.Length; for (int i = 0; i < len; i++) { int rand = UnityEngine.Random.Range(0, len - 1); GameObject newGO = levels[i]; levels[i] = levels[rand]; levels[rand] = newGO; } /*此段以上負責洗牌*/ int lvCount = UnityEngine.Random.Range(minMap, maxMap); lvToPut = new GameObject[lvCount + 1]; lvInform = new Level[lvCount + 1]; link = new Vector2Int[lvCount + 1, lvCount + 1]; for (int i = 0; i < lvCount + 1; i++) { for (int j = 0; j < lvCount + 1; j++) { link[i, j] = Vector2Int.zero; } } lvToPut[0] = StartingPlace; lvInform[0] = StartingPlace.GetComponent <Level>(); for (int i = 1; i < lvCount + 1; i++) { lvToPut[i] = levels[i]; lvInform[i] = lvToPut[i].GetComponent <Level>(); } /*此段以上負責抽關卡*/ for (int i = 1; i < lvCount; i++) { for (int j = i; j >= 1; j--) { if (Mathf.Max(lvInform[j].X, lvInform[j].Y) > Mathf.Max(lvInform[j - 1].X, lvInform[j - 1].Y)) { GameObject tempGO = lvToPut[j]; lvToPut[j] = lvToPut[j - 1]; lvToPut[j - 1] = tempGO; Level tempLV = lvInform[j]; lvInform[j] = lvInform[j - 1]; lvInform[j - 1] = tempLV; } else { break; } } } /*此段以上負責排序(用selection sort,因為基數不大(< 100),而且演算法in place且stable)*/ PlaceLevels(); }
IEnumerator Finish() //步驟7 { AstarPath.active.data.gridGraph.center = Index2Pos(new Vector2(minX, minY), maxX - minX + 1, maxY - minY + 1); AstarPath.active.data.gridGraph.SetDimensions(4 * (maxX - minX) + 4, 4 * (maxY - minY) + 4, 1); AstarPath.active.Scan(); yield return(new WaitForSeconds(1.5f)); currentStatus = GeneratingStatus.Finish; }
private void FinalMakeup() //步驟6 { currentStatus = GeneratingStatus.Final_Makeup; /*for (int i = 0; i < lvInform.Length; i++) * { * for (int j = 0; j < lvInform[i].directions.Length; j++) * { * int k = (int)lvInform[i].directions[j].direction; * if (lvInform[i].directions[j].connectedAmount == 0) * Instantiate(makeUp[k], Index2Pos(ConnectionPos(i, j), 1, 1), Quaternion.identity); * } * }*/ StartCoroutine(Finish()); }
private void BuildPaths() //步驟5 { currentStatus = GeneratingStatus.Build_Paths; while (PathCoordinate.Count != 0) { //int spawnIndex = 0; Vector2Int Pos = PathCoordinate.Dequeue(); /*if (Pos.y > 0 && map[Pos.x, Pos.y - 1] != 2 && map[Pos.x, Pos.y - 1] > 0) * spawnIndex += 1; * if (Pos.y < mapY - 1 && map[Pos.x, Pos.y + 1] != 2 && map[Pos.x, Pos.y + 1] > 0) * spawnIndex += 2; * if (Pos.x > 0 && map[Pos.x - 1, Pos.y] != 2 && map[Pos.x - 1, Pos.y] > 0) * spawnIndex += 4; * if (Pos.x < mapX - 1 && map[Pos.x + 1, Pos.y] != 2 && map[Pos.x + 1, Pos.y] > 0) * spawnIndex += 8;*/ Instantiate(path, Index2Pos(Pos, 1, 1), Quaternion.identity, Composite.transform); } FinalMakeup(); }
private void PlaceLevels() //步驟2 { currentStatus = GeneratingStatus.Place_Levels; /*此段以上負責狀態更改*/ int len = lvToPut.Length; Vector2Int startPos = new Vector2Int(UnityEngine.Random.Range(mapX / 2 - 5, mapX / 2 + 6), UnityEngine.Random.Range(mapY / 2 - 5, mapY / 2 + 6)); PlaceLevelSetup(0, startPos); /*第一個被隨機生成的關卡*/ for (int i = 1; i < len; i++) { bool findPlace = false; while (findPlace == false) { Vector4 newDir = checkDir.Pop(); for (int j = 0; j < 5; j++) { Vector2Int newPos = PickPosition(new Vector2(newDir.y, newDir.z), lvInform[(int)newDir.x].X, lvInform[(int)newDir.x].Y, lvInform[i].X, lvInform[i].Y, (int)newDir.w); if (map[newPos.x, newPos.y] == 0 && map[newPos.x + lvInform[i].X - 1, newPos.y] == 0 && map[newPos.x, newPos.y + lvInform[i].Y - 1] == 0 && map[newPos.x + lvInform[i].X - 1, newPos.y + lvInform[i].Y - 1] == 0) { PlaceLevelSetup(i, newPos); /*int rand = UnityEngine.Random.Range(0, i); * while((lvInform[i].PosInArray - lvInform[rand].PosInArray).sqrMagnitude > 400) * rand = UnityEngine.Random.Range(0, i);*/ BuildLink(i - 1, i, false); findPlace = true; break; } } } } /*此段以上負責生成關卡*/ ConstructLinks(); }
private void FindPaths() //步驟4 { currentStatus = GeneratingStatus.Find_Paths; Queue <Vector2Int> temp = new Queue <Vector2Int>(); while (linkConstructor.Count != 0) { temp.Clear(); Vector4 newLink = linkConstructor.Dequeue(); Vector2Int from = BuildLinkInit(temp, ConnectionPos((int)newLink.x, (int)newLink.y), (int)newLink.x, (int)newLink.y); Vector2Int to = BuildLinkInit(temp, ConnectionPos((int)newLink.z, (int)newLink.w), (int)newLink.z, (int)newLink.w); int stepcount = 0; while (stepcount < 100 && from != to) { stepcount++; if (map[from.x, from.y] != 1) { PathCoordinate.Enqueue(from); } temp.Enqueue(from); map[from.x, from.y] = 3; int upCost = int.MaxValue, downCost = int.MaxValue, leftCost = int.MaxValue, rightCost = int.MaxValue; int oriCost = (to - from).sqrMagnitude; if (from.y > 0 && map[from.x, from.y - 1] < 2 && DeadEnd(from.x, from.y - 1) == false) { upCost = (to - (from + new Vector2Int(0, -1))).sqrMagnitude; } if (from.y < mapY - 1 && map[from.x, from.y + 1] < 2 && DeadEnd(from.x, from.y + 1) == false) { downCost = (to - (from + new Vector2Int(0, 1))).sqrMagnitude; } if (from.x > 0 && map[from.x - 1, from.y] < 2 && DeadEnd(from.x - 1, from.y) == false) { leftCost = (to - (from + new Vector2Int(-1, 0))).sqrMagnitude; } if (from.x < mapX - 1 && map[from.x + 1, from.y] < 2 && DeadEnd(from.x + 1, from.y) == false) { rightCost = (to - (from + new Vector2Int(1, 0))).sqrMagnitude; } int bestCost = (int)Mathf.Min(upCost, downCost, leftCost, rightCost); if (upCost - oriCost < 0 || upCost == bestCost) { from += new Vector2Int(0, -1); } else if (downCost - oriCost < 0 || downCost == bestCost) { from += new Vector2Int(0, 1); } else if (leftCost - oriCost < 0 || leftCost == bestCost) { from += new Vector2Int(-1, 0); } else if (rightCost - oriCost < 0 || rightCost == bestCost) { from += new Vector2Int(1, 0); } minX = ((from.x < minX) ? from.x : minX); minY = ((from.y < minY) ? from.y : minY); maxX = ((from.x > maxX) ? from.x : maxX); maxY = ((from.y > maxY) ? from.y : maxY); } if (map[from.x, from.y] != 1) { PathCoordinate.Enqueue(from); } map[from.x, from.y] = 3; temp.Enqueue(from); foreach (Vector2Int vector in temp) { map[vector.x, vector.y] = 1; } } //linkConstructor(a,b,c,d) => "從第a號關卡的第b號接口做一條路到第c號關卡的第d號接口" #if UNITY_EDITOR string path = "Assets/Resources/Test.txt"; StreamWriter writer = new StreamWriter(new FileStream(path, FileMode.Truncate)); for (int i = 0; i < mapY; i++) { string str = ""; for (int j = 0; j < mapX; j++) { if (map[j, i] >= 0) { str += map[j, i].ToString(); } else { str += "+"; } } str += "\n"; writer.Write(str); } writer.Close(); #endif BuildPaths(); }