//=================================== //=================================== // PERIODIC UPDATE //=================================== //=================================== void Update() { float fadeTime; float guiFlybySpeed = 0f; //pumaAnimator.SetLayerWeight(1, 1f); if (pumaObj == null || buck == null || doe == null || fawn == null) { return; } CalculateFrameRate(); inputControls.ProcessControls(gameState); //================================= // Get distances from puma to deer //================================= float pumaDeerDistance1 = Vector3.Distance(pumaObj.transform.position, buck.gameObj.transform.position); float pumaDeerDistance2 = Vector3.Distance(pumaObj.transform.position, doe.gameObj.transform.position); float pumaDeerDistance3 = Vector3.Distance(pumaObj.transform.position, fawn.gameObj.transform.position); //================================= // Check for Skip Ahead //================================= if (goStraightToFeeding == true && gameState == "gameStateStalking") { SetGameState("gameStateChasing"); pumaDeerDistance1 = 0; } //=========================== // Update Game-State Logic //=========================== switch (gameState) { //------------------------------ // GUI States // // user interface states // main panel showing //------------------------------ case "gameStateGui": // high in air, overlay panel showing guiFlybySpeed = 1f; SelectCameraPosition("cameraPosGui", -120f, 0f, null, null); break; case "gameStateLeavingGui": // zoom down into close up fadeTime = 2.5f; guiFlybySpeed = 1f - (Time.time - stateStartTime) / fadeTime; if (stateInitFlag == false) { // init the level before zooming down PlaceDeerPositions(); ResetAnimations(); // stateInitFlag set to TRUE in the next function } SelectCameraPosition("cameraPosCloseup", 1000000f, fadeTime, "mainCurveSForward", "curveRotXLogarithmicSecondHalf"); // 1000000 signifies no change for cameraRotOffsetY if (Time.time >= stateStartTime + fadeTime) { guiFlybySpeed = 0f; SetGameState("gameStateEnteringGameplay1"); } break; //------------------------------ // Gameplay States // // entering, leaving, // stalking and chasing //------------------------------ case "gameStateEnteringGameplay1": // brief pause on close up fadeTime = 0.1f; if (Time.time >= stateStartTime + fadeTime) { SetGameState("gameStateEnteringGameplay2"); } break; case "gameStateEnteringGameplay2": // swing around to behind view fadeTime = 1.7f; SelectCameraPosition("cameraPosHigh", 0f, fadeTime, "mainCurveSBackward", "curveRotXLinearBackwardsSecondHalf"); if (Time.time >= stateStartTime + fadeTime) { inputControls.ResetControls(); SetGameState("gameStateStalking"); } break; case "gameStateStalking": float lookingDistance = chaseTriggerDistance * 2f; float chasingDistance = chaseTriggerDistance; if (pumaDeerDistance1 < lookingDistance || pumaDeerDistance2 < lookingDistance || pumaDeerDistance3 < lookingDistance) { buckAnimator.SetBool("Looking", true); doeAnimator.SetBool("Looking", true); fawnAnimator.SetBool("Looking", true); } else { buckAnimator.SetBool("Looking", false); doeAnimator.SetBool("Looking", false); fawnAnimator.SetBool("Looking", false); } if (pumaDeerDistance1 < chasingDistance || pumaDeerDistance2 < chasingDistance || pumaDeerDistance3 < chasingDistance) { SetGameState("gameStateChasing"); pumaAnimator.SetBool("Chasing", true); buckAnimator.SetBool("Running", true); doeAnimator.SetBool("Running", true); fawnAnimator.SetBool("Running", true); newChaseFlag = true; pumaHeadingOffset = 0; // instantly disable diagonal movement (TEMP - really should swing camera around) } buck.forwardRate = 0f; buck.turnRate = 0f; doe.forwardRate = 0f; doe.turnRate = 0f; fawn.forwardRate = 0f; fawn.turnRate = 0f; break; case "gameStateChasing": // main chasing state - with a couple of quick initial camera moves handled via sub-states if (stateInitFlag == false) { gameSubState = "chasingSubState1"; cameraController.SelectTargetPosition("cameraPosMedium", 1000000f, 0.75f, "mainCurveLinear", "curveRotXLinear"); // 1000000 signifies no change for cameraRotOffsetY stateInitFlag = true; } else if (gameSubState == "chasingSubState1" && (Time.time >= stateStartTime + 0.75f)) { gameSubState = "chasingSubState2"; cameraController.SelectTargetPosition("cameraPosLow", 1000000f, 0.25f, "mainCurveLinear", "curveRotXLinear"); // 1000000 signifies no change for cameraRotOffsetY } buck.forwardRate = buckDefaultForwardRate * Random.Range(0.9f, 1.1f); // ??? should these really be changed every frame ??? buck.turnRate = buckDefaultTurnRate * Random.Range(0.9f, 1.1f); doe.forwardRate = doeDefaultForwardRate * Random.Range(0.9f, 1.1f); doe.turnRate = doeDefaultTurnRate * Random.Range(0.9f, 1.1f); fawn.forwardRate = fawnDefaultForwardRate * Random.Range(0.9f, 1.1f); fawn.turnRate = fawnDefaultTurnRate * Random.Range(0.9f, 1.1f); //buck.forwardRate = 0f; //doe.forwardRate = 0f; //fawn.forwardRate = 0f; //buck.turnRate = 0f; //doe.turnRate = 0f; //fawn.turnRate = 0f; if (pumaDeerDistance1 < 2.5f || pumaDeerDistance2 < 2.5f || pumaDeerDistance3 < 2.5f) { // DEER IS CAUGHT !!! if (pumaDeerDistance1 < 2.5f) { buck.forwardRate = 0; buck.turnRate = 0f; buckAnimator.SetBool("Die", true); caughtDeer = buck; scoringSystem.DeerCaught(selectedPuma, "Buck"); } else if (pumaDeerDistance2 < 2.5f) { doe.forwardRate = 0f; doe.turnRate = 0f; doeAnimator.SetBool("Die", true); caughtDeer = doe; scoringSystem.DeerCaught(selectedPuma, "Doe"); } else { fawn.forwardRate = 0f; fawn.turnRate = 0f; fawnAnimator.SetBool("Die", true); caughtDeer = fawn; scoringSystem.DeerCaught(selectedPuma, "Fawn"); } // prepare caughtDeer obj for slide deerCaughtHeading = caughtDeer.heading; if (mainHeading >= deerCaughtHeading) { deerCaughtHeadingLeft = (mainHeading - deerCaughtHeading <= 180) ? false : true; } else { deerCaughtHeadingLeft = (deerCaughtHeading - mainHeading <= 180) ? true : false; } if (deerCaughtHeadingLeft == true) { deerCaughtFinalHeading = mainHeading + 90; } else { //deerCaughtFinalHeading = mainHeading - 90; deerCaughtFinalHeading = mainHeading + 90; } if (deerCaughtFinalHeading < 0) { deerCaughtFinalHeading += 360; } if (deerCaughtFinalHeading >= 360) { deerCaughtFinalHeading -= 360; } deerCaughtmainHeading = mainHeading; deerCaughtOffsetX = caughtDeer.gameObj.transform.position.x - pumaX; deerCaughtOffsetZ = caughtDeer.gameObj.transform.position.z - pumaZ; deerCaughtFinalOffsetX = (Mathf.Sin(mainHeading * Mathf.PI / 180) * deerCaughtFinalOffsetFactor0); deerCaughtFinalOffsetZ = (Mathf.Cos(mainHeading * Mathf.PI / 180) * deerCaughtFinalOffsetFactor0); deerCaughtFinalOffsetX += (Mathf.Sin((mainHeading - 90f) * Mathf.PI / 180) * deerCaughtFinalOffsetFactor90); deerCaughtFinalOffsetZ += (Mathf.Cos((mainHeading - 90f) * Mathf.PI / 180) * deerCaughtFinalOffsetFactor90); deerCaughtNextFrameTime = 0; if (Time.time - stateStartTime < 5f) { deerCaughtEfficiency = 3; } else if (Time.time - stateStartTime < 10f) { deerCaughtEfficiency = 2; } else if (Time.time - stateStartTime < 16f) { deerCaughtEfficiency = 1; } else { deerCaughtEfficiency = 0; } pumaAnimator.SetBool("DeerKill", true); SetGameState("gameStateFeeding1"); } break; case "gameStateLeavingGameplay": // zoom up to high in the air fadeTime = 2f; guiFlybySpeed = (Time.time - stateStartTime) / fadeTime; SelectCameraPosition("cameraPosGui", -120f, fadeTime, "mainCurveSBackward", "curveRotXLogarithmicBackwardsSecondHalf"); if (Time.time >= stateStartTime + fadeTime) { guiFlybySpeed = 1f; ResetAnimations(); SetGameState("gameStateGui"); } break; //------------------------------ // Feeding States // // puma has caught a deer // kills it and feeds on it //------------------------------ case "gameStateFeeding1": // deer and puma slide to a stop as camera swings around to front fadeTime = 1.3f; SelectCameraPosition("cameraPosCloseup", -160f, fadeTime, "mainCurveSBackward", "curveRotXLogarithmic"); if (Time.time < stateStartTime + fadeTime) { // puma and deer slide to a stop float percentDone = 1f - ((Time.time - stateStartTime) / fadeTime); float pumaMoveDistance = 1f * Time.deltaTime * pumaChasingSpeed * percentDone * 1.1f; pumaX += (Mathf.Sin(deerCaughtmainHeading * Mathf.PI / 180) * pumaMoveDistance); pumaZ += (Mathf.Cos(deerCaughtmainHeading * Mathf.PI / 180) * pumaMoveDistance); // during slide move deer to correct position percentDone = ((Time.time - stateStartTime) / fadeTime); if ((deerCaughtFinalHeading > deerCaughtHeading) && (deerCaughtFinalHeading - deerCaughtHeading > 180)) { deerCaughtHeading += 360; } else if ((deerCaughtHeading > deerCaughtFinalHeading) && (deerCaughtHeading - deerCaughtFinalHeading > 180)) { deerCaughtFinalHeading += 360; } if (deerCaughtFinalHeading > deerCaughtHeading) { caughtDeer.heading = deerCaughtHeading + ((deerCaughtFinalHeading - deerCaughtHeading) * percentDone); } else { caughtDeer.heading = deerCaughtHeading - ((deerCaughtHeading - deerCaughtFinalHeading) * percentDone); } if (caughtDeer.heading < 0) { caughtDeer.heading += 360; } if (caughtDeer.heading >= 360) { caughtDeer.heading -= 360; } float deerX = pumaX + (deerCaughtOffsetX * (1f - percentDone)) + (deerCaughtFinalOffsetX * percentDone); float deerY = caughtDeer.gameObj.transform.position.y; float deerZ = pumaZ + (deerCaughtOffsetZ * (1f - percentDone)) + (deerCaughtFinalOffsetZ * percentDone); caughtDeer.gameObj.transform.rotation = Quaternion.Euler(0, caughtDeer.heading, 0); //System.Console.WriteLine("update heading: " + caughtDeer.heading.ToString()); caughtDeer.gameObj.transform.position = new Vector3(deerX, deerY, deerZ); } else { float deerX = pumaX + deerCaughtFinalOffsetX; float deerY = caughtDeer.gameObj.transform.position.y; float deerZ = pumaZ + deerCaughtFinalOffsetZ; caughtDeer.gameObj.transform.rotation = Quaternion.Euler(0, deerCaughtFinalHeading, 0); caughtDeer.gameObj.transform.position = new Vector3(deerX, deerY, deerZ); SetGameState("gameStateFeeding2"); } break; case "gameStateFeeding2": // brief pause fadeTime = 1.3f; if (Time.time >= stateStartTime + fadeTime) { SetGameState("gameStateFeeding3"); } break; case "gameStateFeeding3": // camera slowly lifts as puma feeds on deer fadeTime = 5f; SelectCameraPosition("cameraPosEating", 1000000f, fadeTime, "mainCurveSBackward", "curveRotXLinear"); if (Time.time >= stateStartTime + fadeTime) { SetGameState("gameStateFeeding4"); } break; case "gameStateFeeding4": // camera spins slowly around puma as it feeds if (Time.time >= stateStartTime + 0.1f) { float spinningRotOffsetY = cameraController.GetCurrentRotOffsetY() - (Time.deltaTime + 0.03f); if (spinningRotOffsetY < -180f) { spinningRotOffsetY += 360f; } cameraController.SelectTargetPosition("cameraPosEating", spinningRotOffsetY, 0f, "mainCurveNull", "curveRotXNull"); } break; case "gameStateFeeding5": // camera swings back into position for stalking fadeTime = 2.4f; pumaAnimator.SetBool("DeerKill", false); SelectCameraPosition("cameraPosHigh", 0f, fadeTime, "mainCurveSBackward", "curveRotXLogarithmic"); if (Time.time >= stateStartTime + fadeTime) { PlaceDeerPositions(); ResetAnimations(); scoringSystem.ClearLastKillInfo(selectedPuma); inputControls.ResetControls(); SetGameState("gameStateStalking"); } break; //------------------------------ // Died States // // puma has died // returns to overlay display //------------------------------ case "gameStateDied1": // camera swings around to front of puma fadeTime = 3f; SelectCameraPosition("cameraPosCloseup", -160f, fadeTime, "mainCurveSBackward", "curveRotXLogarithmic"); if (Time.time >= stateStartTime + fadeTime) { SetGameState("gameStateDied2"); } break; case "gameStateDied2": // brief pause fadeTime = 0.2f; if (Time.time >= stateStartTime + fadeTime) { SetGameState("gameStateDied3"); } break; case "gameStateDied3": // camera lifts slowly away from puma fadeTime = 5f; SelectCameraPosition("cameraPosEating", 1000000f, fadeTime, "mainCurveSBackward", "curveRotXLinear"); if (Time.time >= stateStartTime + fadeTime) { SetGameState("gameStateDied4"); } break; case "gameStateDied4": // camera spins slowly around puma if (Time.time >= stateStartTime + 0.1f) { float spinningRotOffsetY = cameraController.GetCurrentRotOffsetY() - (Time.deltaTime + 0.03f); if (spinningRotOffsetY < -180f) { spinningRotOffsetY += 360f; } cameraController.SelectTargetPosition("cameraPosEating", spinningRotOffsetY, 0f, "mainCurveNull", "curveRotXNull"); } break; //------------------ // Error Check //------------------ default: Debug.Log("ERROR - LevelManager.Update() got bad state: " + gameState); break; } //=============== // Update Puma //=============== float distance = 0f; pumaHeading = mainHeading; if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.LeftControl)) { // filter out the input when manual camera moves are in progress - DEV ONLY } else if (gameState == "gameStateGui" || gameState == "gameStateLeavingGameplay" || gameState == "gameStateLeavingGui") { // process automatic puma walking during GUI state if ((gameState != "gameStateLeavingGui") || (Time.time - stateStartTime < 1.8f)) { pumaAnimator.SetBool("GuiMode", true); } distance = guiFlybySpeed * Time.deltaTime * 12f * speedOverdrive; pumaX += (Mathf.Sin(mainHeading * Mathf.PI / 180) * distance); pumaZ += (Mathf.Cos(mainHeading * Mathf.PI / 180) * distance); } else if (gameState == "gameStateStalking") { // main stalking state float rotationSpeed = 100f; distance = inputControls.GetInputVert() * Time.deltaTime * pumaStalkingSpeed * speedOverdrive; mainHeading += inputControls.GetInputHorz() * Time.deltaTime * rotationSpeed; pumaHeading = mainHeading + pumaHeadingOffset; pumaX += (Mathf.Sin(pumaHeading * Mathf.PI / 180) * distance); pumaZ += (Mathf.Cos(pumaHeading * Mathf.PI / 180) * distance); scoringSystem.PumaHasWalked(selectedPuma, distance); if (scoringSystem.GetPumaHealth(selectedPuma) == 0f) { SetGameState("gameStateDied1"); } } else if (gameState == "gameStateChasing") { // main chasing state float rotationSpeed = 150f; distance = inputControls.GetInputVert() * Time.deltaTime * pumaChasingSpeed * speedOverdrive; float travelledDistance = (scoringSystem.GetPumaHealth(selectedPuma) > 0.05f) ? distance : distance * (scoringSystem.GetPumaHealth(selectedPuma) / 0.05f); mainHeading += inputControls.GetInputHorz() * Time.deltaTime * rotationSpeed; pumaHeading = mainHeading + pumaHeadingOffset; pumaX += (Mathf.Sin(pumaHeading * Mathf.PI / 180) * travelledDistance); pumaZ += (Mathf.Cos(pumaHeading * Mathf.PI / 180) * travelledDistance); scoringSystem.PumaHasRun(selectedPuma, distance); if (scoringSystem.GetPumaHealth(selectedPuma) == 0f) { SetGameState("gameStateDied1"); } } pumaAnimator.SetBool("GuiMode", false); pumaAnimator.SetFloat("Distance", distance); // calculate puma rotX based on terrain in front and behind float pumaRotX; float offsetDistance = 1f; float pumaAheadX = pumaX + (Mathf.Sin(pumaHeading * Mathf.PI / 180) * offsetDistance * 1f); float pumaAheadZ = pumaZ + (Mathf.Cos(pumaHeading * Mathf.PI / 180) * offsetDistance * 1f); float pumaBehindX = pumaX + (Mathf.Sin(pumaHeading * Mathf.PI / 180) * offsetDistance * -1f); float pumaBehindZ = pumaZ + (Mathf.Cos(pumaHeading * Mathf.PI / 180) * offsetDistance * -1f); pumaRotX = GetAngleFromOffset(0, GetTerrainHeight(pumaAheadX, pumaAheadZ), offsetDistance * 2f, GetTerrainHeight(pumaBehindX, pumaBehindZ)) - 90f; // update puma obj pumaY = GetTerrainHeight(pumaX, pumaZ); pumaObj.transform.position = new Vector3(pumaX, pumaY, pumaZ); pumaObj.transform.rotation = Quaternion.Euler(pumaRotX, (pumaHeading - 180f), 0); //================ // Update Camera //================ cameraController.UpdateCameraPosition(pumaX, pumaY, pumaZ, mainHeading); //================ // Update Deer //================ UpdateDeerHeading(buck); UpdateDeerHeading(doe); UpdateDeerHeading(fawn); UpdateDeerPosition(buck); UpdateDeerPosition(doe); UpdateDeerPosition(fawn); //================================ // Leap-Frog the Ground Planes //================================ for (int i = 0; i < terrainArray.Length; i++) { float terrainX = terrainArray[i].transform.position.x; float terrainZ = terrainArray[i].transform.position.z; if (pumaX - terrainX > 3000) { terrainX += 4000; } else if (terrainX - pumaX > 1000) { terrainX -= 4000; } if (pumaZ - terrainZ > 3000) { terrainZ += 4000; } else if (terrainZ - pumaZ > 1000) { terrainZ -= 4000; } terrainArray[i].transform.position = new Vector3(terrainX, 0, terrainZ); } }