// ########################################################### IEnumerator playGame() { string temp = ""; Vector3 pos; int i; bool tutorial = true; // if true, show the tutorial text bool cheat = false; // if true, monster does not kill you, progress to next carriage bool calcDispx = true; // if true, calculate values in trainStationDispX to give best view of characters mainMenu.SetActive(false); // Loop over tracks for (itrack = 0; itrack < ntracks; itrack++) { trackText.text = "Track: " + itrack.ToString(); int nsequence = 0; mainCamera.transform.position = camStartPos; // -4,0,10 mainCamera.transform.rotation = Quaternion.Euler(0, camStartRot, 0); controls.SetActive(false); yield return(StartCoroutine(trainArrives())); yield return(StartCoroutine(mainCameraScript.rotateTo(0, 180, 0, 20))); yield return(StartCoroutine(mainCameraScript.moveTo(camStartPos.x, 0, 0, 60))); yield return(StartCoroutine(mainCameraScript.rotateTo(0, -90, 0, 20))); yield return(StartCoroutine(mainCameraScript.moveTo(camStartPos.x + camTrainDisp.x, 0, 0, 60))); yield return(StartCoroutine(mainCameraScript.rotateTo(0, 180, 0, 20))); yield return(StartCoroutine(mainCameraScript.moveTo(camStartPos.x + camTrainDisp.x, 0, camTrainDisp.z, 60))); if (itrack > 1) { controls.SetActive(true); } else { controls.SetActive(false); } trackText.text = ""; mainCamera.transform.parent = train.transform; activateCarriages(0); // 0 means we are in the rear carriage int nacc; float x, astop, xst; xst = trainStationDispX[itrack][0]; // starting position of front of train float camDistFromFront = trainStationDispX[itrack][0] - (camStartPos.x + camTrainDisp.x); int carriagesBehind = 0; float ust = 0; // Process the track // 0 1 2 3 4 // 000 .R3 IL3 IR3 IE.; int nstation = track[itrack].Length; // 5 stations (incl beginning and end) for (int istation = 1; istation < nstation; istation++) { print("station text" + track[itrack][istation]); float xtun0 = tunnel.transform.position.x; // starting position of tunnel back-end nacc = (int)((umax - ust) / astart); // no time steps to get to max speed //-------------------------------------------------------------------- // Acceleration phase //-------------------------------------------------------------------- print("accelerate"); for (i = 0; i < nacc; i++) { x = xst + ust * i + 0.5f * astart * i * i; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); yield return(new WaitForFixedUpdate()); } xst = xst + ust * nacc + 0.5f * astart * nacc * nacc; // distance covered in acc'n phase ust = umax; outCharGroup.SetActive(false); previewCharGroup.SetActive(false); //-------------------------------------------------------------------- // Constant speed phase for n frames //-------------------------------------------------------------------- int n = Random.Range(100, 500); print(n + " frames at constant speed"); for (i = 0; i < n; i++) { x = xst + i * umax; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); yield return(new WaitForFixedUpdate()); } xst = xst + n * umax; //-------------------------------------------------------------------- // ask for sequence in tunnel //-------------------------------------------------------------------- if (track[itrack][istation][0] == 'I') { print("wait for input"); inputMenu.SetActive(true); textEntry.text = "---"; nentry = 0; // set by buttoms in inputMenu for (i = 0; i < nsequence * nInputTime; i++) { if (nentry >= nsequence) { break; } x = xst + i * umax; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); countDown.text = (nsequence * nInputTime - i).ToString(); yield return(new WaitForFixedUpdate()); } xst = xst + i * umax; inputMenu.SetActive(false); temp = ""; for (i = 0; i < nentry; i++) { temp += typed_sequence[i]; } print("typed sequence=" + temp); bool correct; if (nentry != nsequence) { correct = false; } else { correct = true; for (i = 0; i < nsequence; i++) { if (sequence[i] != typed_sequence[i]) { correct = false; break; } } } print("got it right? " + correct); nsequence = 0; // reset sequence if (correct) { finishedMoving = false; StartCoroutine(gotoNextCarriage()); i = 0; while (!finishedMoving) { x = xst + i * umax; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); i++; yield return(new WaitForFixedUpdate()); } xst = xst + i * umax; camDistFromFront -= tunnelLength / 2; carriagesBehind++; activateCarriages(carriagesBehind); } else { finishedMoving = false; StartCoroutine(jumpScare(camDistFromFront)); i = 0; while (!finishedMoving) { x = xst + i * umax; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); i++; yield return(new WaitForFixedUpdate()); } xst = xst + i * umax; if (!cheat) { goto jumpout; // exit to main game loop } } // ------------------------------------------------------- // Fireball attack in tunnel // ------------------------------------------------------- } else if (track[itrack][istation][0] == 'F') { StartCoroutine(fireballAttack(itrack == 3 && istation == 2)); i = 0; survivedFB = false; while (mainCameraScript.getFireball()) { x = xst + i * umax; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); i++; yield return(new WaitForFixedUpdate()); } xst = xst + i * umax; if (!cheat && !survivedFB) { goto jumpout; } } //-------------------------------------------------------------------- // Slow down phase calculation //-------------------------------------------------------------------- int sectionsDone; float totLength, distRemain; float dispx; if (calcDispx && istation != nstation - 1) { dispx = camDistFromFront - umin[itrack][istation] * nLowSpeed[itrack][istation] / 2; } else { dispx = trainStationDispX[itrack][istation]; } sectionsDone = (int)((xst - xtun0) / tunnelLength); totLength = (sectionsDone + nmore) * tunnelLength; distRemain = totLength - (xst - xtun0) + stationLength / 2 + dispx; astop = (umin[itrack][istation] * umin[itrack][istation] - umax * umax) / (2 * distRemain); // v^2=u^2+2as (will be negative) //-------------------------------------------------------------------- // Move Station. Set numbers on outside characters' signs (if needed) //-------------------------------------------------------------------- station.transform.Translate(new Vector3(stationLength + totLength, 0, 0)); // "000 .R3 IL3 IR3 IE. "; if (track[itrack][istation][1] == 'E') { outCharGroup.SetActive(false); previewCharGroup.SetActive(false); } else if (track[itrack][istation][1] == 'R' || track[itrack][istation][1] == 'L') { float z, rotY; if (track[itrack][istation][1] == 'R') { z = -8; rotY = 0; } else { z = 8; rotY = 180; } int nOutChars = track[itrack][istation][2] - '0'; for (i = 0; i < maxOutChars; i++) { outChars[i].SetActive(false); } for (i = 0; i < nOutChars; i++) { outChars[i].SetActive(true); outChars[i].transform.localPosition = new Vector3(-(nOutChars - 1) * 2 + i * 4, 1, z); outChars[i].transform.rotation = Quaternion.Euler(0, rotY, 0); } outCharGroup.SetActive(true); outCharGroup.transform.position = new Vector3(station.transform.position.x, station.transform.position.y, 0); for (i = 0; i < nOutChars; i++) { float r = Random.value; if (r < 0.333) { temp = "1"; } else if (r < 0.666) { temp = "2"; } else { temp = "3"; } sequence[nsequence] = temp; nsequence++; Text number = outChars[i].GetComponentInChildren <Text>(); number.text = temp; } temp = ""; for (i = 0; i < nsequence; i++) { temp += sequence[i]; } print("sequence=" + temp); } else if (track[itrack][istation][1] == 'P') { // ---------------------------------------------------- // set preview characters // ---------------------------------------------------- int nPreviewChars = track[itrack][istation][2] - '0'; print("nPreviewChars" + nPreviewChars); previewCharGroup.SetActive(true); char[] previewList; previewList = new char[nPreviewChars]; int ind = 0; i = 0; while (ind < nPreviewChars) { if (track[itrack][istation + i + 1][1] == 'R') { previewList[ind] = 'R'; ind++; } else if (track[itrack][istation + i + 1][1] == 'L') { previewList[ind] = 'L'; ind++; } i++; } for (i = 0; i < 3; i++) { previewChars[0, i].SetActive(false); previewChars[1, i].SetActive(false); } for (i = 0; i < nPreviewChars; i++) { previewChars[0, i].SetActive(true); previewChars[1, i].SetActive(true); string text; if (previewList[i] == 'R') { text = "R"; } else { text = "L"; } Text number = (previewChars[0, i]).GetComponentInChildren <Text>(); number.text = text; number = previewChars[1, i].GetComponentInChildren <Text>(); number.text = text; } previewCharGroup.transform.position = new Vector3(station.transform.position.x, station.transform.position.y, 0); } //-------------------------------------------------------------------- // Slow down phase //-------------------------------------------------------------------- print("sectionsDone" + sectionsDone); print("slow down" + astop); for (i = 0; i <= (int)((umin[itrack][istation] - umax) / astop); i++) { x = xst + umax * i + 0.5f * astop * i * i; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); yield return(new WaitForFixedUpdate()); } xst = station.transform.position.x + dispx; ust = umin[itrack][istation]; //-------------------------------------------------- // Move slowly through the station // (divided into 2 parts with tutorial text between) //-------------------------------------------------- if (istation != nstation) { for (i = 0; i < nLowSpeed[itrack][istation] / 2; i++) { x = xst + umin[itrack][istation] * i; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); yield return(new WaitForFixedUpdate()); } // ----------------------------------------------- // Put tutorial dialogs here // ----------------------------------------------- if (tutorial && itrack == 0 && istation == 1) { float lookCharsOffsetZ = -2.65f; float lookCharsRotateTo = 160; yield return(StartCoroutine(moveCameraTo(0, 0, lookCharsOffsetZ, 60, true))); yield return(StartCoroutine(rotateCameraTo(0, lookCharsRotateTo, 0, 30))); mbText.text = "What were those strange figures? " + "They didn't look human... The sequence seemed important: '" + temp + "'"; messageBox.SetActive(true); pressedOK = false; while (!pressedOK) { yield return(null); } messageBox.SetActive(false); yield return(StartCoroutine(rotateCameraTo(0, -180, 0, 30))); yield return(StartCoroutine(moveCameraTo(0, 0, -lookCharsOffsetZ, 40, true))); } else if (tutorial && itrack == 0 && istation == 4) { mbText.text = "I wasn't asked for the sequence in that tunnel " + "So I need to combine the two sequences to give: '" + temp + "'"; messageBox.SetActive(true); pressedOK = false; while (!pressedOK) { yield return(null); } messageBox.SetActive(false); } else if (tutorial && ((itrack == 1 && (istation == 2 || istation == 4 || istation == 6)) || (itrack == 2 && istation == 2))) { if (itrack == 1) { if (istation == 2) { mbText.text = "The little guy was telling me the next sequence would be shown on the LEFT platform. " + "Press 'SWITCH' to look out the other window"; } else if (istation == 4) { mbText.text = "So I should look RIGHT in the next station, then LEFT in the station after that"; } else { mbText.text = "Remember the sequence builds up (if not input) so it is now: " + temp; } } else { mbText.text = "Some stations were empty..."; } controls.SetActive(true); messageBox.SetActive(true); pressedOK = false; while (!pressedOK) { yield return(null); } messageBox.SetActive(false); } for (i = nLowSpeed[itrack][istation] / 2; i < nLowSpeed[itrack][istation]; i++) { x = xst + umin[itrack][istation] * i; train.transform.position = new Vector3(x, 0, 0); cycleTunnel(x - camDistFromFront); yield return(new WaitForFixedUpdate()); } xst = xst + umin[itrack][istation] * nLowSpeed[itrack][istation]; } tunnel.transform.Translate(new Vector3(3 * tunnelLength + stationLength, 0, 0)); } // istation loop print("Level complete"); // ----------------------------------------------------------------------------- // Leave train. // ----------------------------------------------------------------------------- controls.SetActive(false); for (i = 0; i < nCarriages; i++) { carriages[i].SetActive(true); } if (mainCamera.transform.position.z > 0) { yield return(StartCoroutine(mainCameraScript.rotateTo(0, 180, 0, 30))); } else { yield return(StartCoroutine(mainCameraScript.rotateTo(0, 0, 0, 30))); } pos = mainCamera.transform.localPosition; yield return(StartCoroutine(mainCameraScript.moveTo(pos.x, pos.y, 0, 60))); yield return(StartCoroutine(mainCameraScript.rotateTo(0, 90, 0, 20))); yield return(StartCoroutine(mainCameraScript.moveTo(-camTrainDisp.x, 0, 0, 60, true))); yield return(StartCoroutine(mainCameraScript.rotateTo(0, 0, 0, 20))); yield return(StartCoroutine(mainCameraScript.moveTo(0, 0, camStartPos.z, 60, true))); yield return(StartCoroutine(mainCameraScript.rotateTo(0, camStartRot, 0, 20))); mainCamera.transform.parent = null; // camera gets off train // ----------------------------------------------------------------------- // Move station, camera, train back to x=0 // ----------------------------------------------------------------------- Vector3 disp = mainCamera.transform.position - station.transform.position; // how far down the train we got disp.y = 0; pos = station.transform.position; pos.x = 0; station.transform.position = pos; mainCamera.transform.position = disp; tunnel.transform.position = new Vector3(stationLength / 2, 0, 0); train.transform.position = new Vector3(trainStationDispX[itrack][nstation - 1], 0, 0); yield return(StartCoroutine(trainLeaves())); yield return(StartCoroutine(mainCameraScript.moveTo(camStartPos.x, camStartPos.y, camStartPos.z, 60))); } // loop over tracks jumpout : print("jumped out"); }