diff --git a/AnalyticsUtil.js b/AnalyticsUtil.js new file mode 100644 index 0000000..7caa6ca --- /dev/null +++ b/AnalyticsUtil.js @@ -0,0 +1,6 @@ +#pragma strict + +function Event (eventString: String, eventArg: float) { + // Debug.Log("Received event " + eventString + " with arg: " + eventArg); + GameAnalyticsSDK.GameAnalytics.NewDesignEvent(eventString, eventArg); +} \ No newline at end of file diff --git a/AudioDuckingRegion.js b/AudioDuckingRegion.js index ec80464..7978223 100644 --- a/AudioDuckingRegion.js +++ b/AudioDuckingRegion.js @@ -1,12 +1,17 @@ #pragma strict var duckingObject : GameObject; +var moveControllerComponent : MoveController; var duckingVal : float = .5f; var StopAudioOnComplete : boolean = false; var audioSource : AudioSource; function Start () { audioSource = duckingObject.GetComponent.(); + // go one or two levels up, since in VR the parent may be shifted around: + moveControllerComponent = + duckingObject.transform.parent.GetComponent.() || + duckingObject.transform.parent.parent.GetComponent.(); } function OnTriggerEnter (other : Collider) { @@ -23,6 +28,8 @@ function OnTriggerExit (other : Collider) { function lerpDuck (timer : float, endVal : float) { + if (!StopAudioOnComplete && !audioSource.isPlaying) {audioSource.UnPause();} + var start = audioSource.volume; var end = endVal; var i = 0.0; @@ -30,10 +37,10 @@ function lerpDuck (timer : float, endVal : float) { while (i <= 1.0) { i += step * Time.deltaTime; - audioSource.volume = Mathf.Lerp(start, end, i); - yield; - } + moveControllerComponent.setMaxDuckedVolume( Mathf.Lerp(start, end, i) ); + yield; + } yield WaitForSeconds (timer); - if (StopAudioOnComplete) {audioSource.Stop();} + if (StopAudioOnComplete) {audioSource.Pause();} } diff --git a/AudioVolumeInterpolate.js b/AudioVolumeInterpolate.js index dd8cd69..5753ff8 100644 --- a/AudioVolumeInterpolate.js +++ b/AudioVolumeInterpolate.js @@ -14,7 +14,7 @@ function Start () { aSource = GetComponent(AudioSource); aSource.volume = 0f; // findPlayer(); - player = GameObject.Find("Player/Camera").transform; + player = Camera.main.transform; } function OnTriggerEnter (other : Collider) { diff --git a/EndSequence1stPerson.js b/EndSequence1stPerson.js index fc73a19..9725818 100644 --- a/EndSequence1stPerson.js +++ b/EndSequence1stPerson.js @@ -1,10 +1,13 @@ #pragma strict +var Player : GameObject; +private var FallingPlayerScript : FallingPlayer; var PlayerController : MoveController; var ScoreController : ScoreController; var LifeController : lifeCountdown; var EndTriggerName : GameObject; var EndTriggerComponent : EndSequenceTrigger; +var EndMenuLogoObjectVR : GameObject; var EndMenuLogoObject : GameObject; var EndMenuLogoCamera : GameObject; var OutroMusic : AudioSource; @@ -14,64 +17,113 @@ var MusicBedInterpolated : AudioVolumeInterpolate; var UIscriptEndMenuName : GameObject; var UIscriptEndMenuComponent : FallingEndMenuUI; +var reticleVRUIScript : VRLifeMeter; //var outroShards : GameObject; var outroCompletedOrb : GameObject; var outroCompletionPoint : GameObject; function Start () { + FallingPlayerScript = GetComponent("FallingPlayer"); PlayerController = GetComponent("MoveController"); ScoreController = GetComponent("ScoreController"); LifeController = GetComponent("lifeCountdown"); MusicBedInterpolated = OutroMusicBedObject.GetComponent("AudioVolumeInterpolate"); UIscriptEndMenuComponent = UIscriptEndMenuName.GetComponent("FallingEndMenuUI"); EndTriggerComponent = EndTriggerName.GetComponent("EndSequenceTrigger"); + + // Look up manually if not added in inspector: + if (!reticleVRUIScript) { + Debug.Log("Did you forget to select a reticleVRUIScript in the Unity Inspector?"); + reticleVRUIScript = GameObject.Find("vr-radial-life-meter").GetComponent.(); + } + // Skip to the outro for testing. + // Make sure to disable EndSequenceTrigger's PlayOutro call so they don't compete: + // PlayOutro(); } function PlayOutro () { - //GameAnalytics events for beating the game + // GameAnalytics events for beating the game + var isNewGamePlus : String = (FallingLaunch.NewGamePlus) ? "new_game_plus" : "first_game"; + FallingLaunch.secondsInLevel = (Time.time - FallingPlayer.levelStartTime); - // GA.API.Design.NewEvent("GameComplete:" + FallingPlayer.isNewGamePlus, FallingLaunch.secondsInLevel, transform.position); - + FallingLaunch.Analytics.Event( + "GameComplete:" + FallingLaunch.vrModeAnalyticsString + isNewGamePlus, + FallingLaunch.secondsInLevel + ); + // TestFlightUnity.TestFlight.PassCheckpoint( "LevelComplete:" + Application.loadedLevelName ); // TestFlightUnity.TestFlight.PassCheckpoint( "GameComplete"); FallingPlayer.isPausable = false; ScoreController.enabled = false; - LifeController.enabled = false; - FallingPlayer.isTiltable = false; + LifeController.enabled = false; + FallingPlayer.isTiltable = false; + PlayerController.lerpSlowdown(1); OutroMusic.Play(); //PlayerController.SpeedLinesOff(1); yield WaitForSeconds (1); PlayerController.enabled = false; - FallingPlayer.UIscriptComponent.BeginOutroUI(); + + FallingPlayer.isPausable = false; + Player.transform.GetComponent.().isKinematic = true; + + if (FallingLaunch.isVRMode) { + reticleVRUIScript.FadeReticleOut(0.5); + } else { + FallingPlayer.UIscriptComponent.BeginOutroUI(); + } + ScoreController.IncrementScore(35); LerpTowardsDiamond(10); RotateTowardsDiamond(10); yield WaitForSeconds (10); - //LerpIntoDiamond(14); + + // LerpIntoDiamond(14); MusicBedInterpolated.falsifyCheckDistance(); FadeMusic(8, OutroMusicBed); - GetComponent.().Play("end-player-anim"); + + // Only using iTween for path movement. + // Rotation is handled via FinalRotation's Slerp. + iTween.MoveTo(gameObject, + iTween.Hash("path",iTweenPath.GetPath("player-end-path"), + "orienttopath", false, + // "looktarget", EndTriggerComponent.getDiamondCenter(), + // "axis", "y", + "time", 13, + "easetype", "easeOutSine" + )); + + // start rotating player camera to end at the same time as the above tween path traveling. + FinalRotation(13); + EndTriggerComponent.AddDiamondCore(5); yield WaitForSeconds (1); EndTriggerComponent.AddDiamond3DCore(6); yield WaitForSeconds (1); EndTriggerComponent.FadeDiamond(8); - yield WaitForSeconds (6); + yield WaitForSeconds (6); ScoreController.enabled = true; LifeController.enabled = true; lifeCountdown.inOutro = false; - FallingPlayer.UIscriptComponent.GameCompleteUI(); - UIscriptEndMenuComponent.ShowEndGameUI(); + if (!FallingLaunch.isVRMode) { + FallingPlayer.UIscriptComponent.GameCompleteUI(); + UIscriptEndMenuComponent.ShowEndGameUI(); + } FadeAudioListener (4); yield WaitForSeconds(1); - FadeEndMenuLogo(3); + + if (FallingLaunch.isVRMode) { + FadeEndMenuLogoVR(3.0); + FallingPlayerScript.WhiteFadeVREndGame(5.0); + } else { + FadeEndMenuLogo(3.0); + } + FallingLaunch.NewGamePlus = true; - //UIscriptComponent.LevelComplete(); } function LerpTowardsDiamond (timer : float) { @@ -90,7 +142,8 @@ function LerpTowardsDiamond (timer : float) { while (i <= 1.0) { // transform.LookAt(diamondLookTarget); i += step * Time.deltaTime; - transform.position = Vector3.Slerp(start, end, i); + var t : float = i*i*i * (i * (6f*i - 15f) + 10f); // smootherstep lerp + transform.position = Vector3.Slerp(start, end, t); //transform.rotation = Quaternion.Slerp(startRotation, endRotation, i); yield; @@ -99,38 +152,81 @@ function LerpTowardsDiamond (timer : float) { EndTriggerComponent.SwapDiamonds(4); } -function RotateTowardsDiamond (timer : float) { +function FinalRotation (timer : float) { var i = 0.0; var step = 1.0/timer; - var startRotation = transform.rotation; - var endRotation = Quaternion.Euler(-54,96,-2.3); - + var startRotation = transform.rotation; + var endRotation = Quaternion.Euler(-23.9,101.74,-2.52); + while (i <= 1.0) { i += step * Time.deltaTime; - transform.rotation = Quaternion.Slerp(startRotation, endRotation, i); + var t : float = i*i*i * (i * (6f*i - 15f) + 10f); // smootherstep lerp + transform.rotation = Quaternion.Slerp(startRotation, endRotation, t); yield; } } -function LerpIntoDiamond (timer : float) { - var end = outroCompletedOrb.transform.position; - var start = gameObject.transform.position; - var startRotation = transform.rotation; - var endRotation = Quaternion.Euler(-79,97,-2.3); +function RotateTowardsDiamond (timer : float) { var i = 0.0; var step = 1.0/timer; - + var startRotation = transform.rotation; + var endRotation = Quaternion.Euler(-54,96,-2.3); + + var myCameraParent = transform.Find("Player-cameras"); + var parentRotation = myCameraParent ? myCameraParent.localRotation : Quaternion.identity; + while (i <= 1.0) { i += step * Time.deltaTime; - transform.position = Vector3.Slerp(start, end, i); - transform.rotation = Quaternion.Slerp(startRotation, endRotation, i); - + var t : float = i*i * (3f - 2f*i); // smoothstep lerp + transform.rotation = Quaternion.Slerp(startRotation, endRotation, t); + // myCameraParent needs rotating too, because otherwise the local container object + // (tilted via FallingPlayer.playerTilt) will not be aligned to 0,0,0 local rotation, + // so the diamond target won't be centered in view. VR mode is unaffected by this, + // since the VR eye cameras aren't children of myCameraParent. + if (myCameraParent) { + myCameraParent.localRotation = Quaternion.Slerp(parentRotation, Quaternion.identity, t); + } yield; } +} +// function LerpIntoDiamond (timer : float) { +// var end = outroCompletedOrb.transform.position; +// var start = gameObject.transform.position; +// var startRotation = transform.rotation; +// var endRotation = Quaternion.Euler(-79,97,-2.3); +// var i = 0.0; +// var step = 1.0/timer; + +// while (i <= 1.0) { +// i += step * Time.deltaTime; +// transform.position = Vector3.Slerp(start, end, i); +// transform.rotation = Quaternion.Slerp(startRotation, endRotation, i); + +// yield; +// } + +// } + +function FadeEndMenuLogoVR(timer:float){ + + EndMenuLogoObjectVR.GetComponent.().enabled = true; + var start = 0; + var end = 1.0; + var i = 0.0; + var step = 1.0/timer; + + while (i <= 1.0) { + i += step * Time.deltaTime; + EndMenuLogoObjectVR.GetComponent.().material.color.a = Mathf.Lerp(start, end, i); + yield; + } + + yield WaitForSeconds (timer); } + function FadeEndMenuLogo(timer:float){ EndMenuLogoCamera.GetComponent(Camera).enabled = true; @@ -144,7 +240,7 @@ function FadeEndMenuLogo(timer:float){ i += step * Time.deltaTime; EndMenuLogoObject.GetComponent.().material.color.a = Mathf.Lerp(start, end, i); yield; - } + } yield WaitForSeconds (timer); } diff --git a/EndSequenceTrigger.js b/EndSequenceTrigger.js index 1060664..4b0337c 100644 --- a/EndSequenceTrigger.js +++ b/EndSequenceTrigger.js @@ -1,6 +1,7 @@ #pragma strict var Player : GameObject; +var FallingPlayerScript : FallingPlayer; var EndScriptComponent : EndSequence1stPerson; var shards : Array; @@ -18,26 +19,27 @@ function Awake () { function Start () { audioSource = GetComponent.(); + FallingPlayerScript = Player.GetComponent("FallingPlayer"); } function OnTriggerEnter (other : Collider) { if (other.gameObject.CompareTag ("Player") && lifeCountdown.inOutro == false) { lifeCountdown.inOutro = true; - + MoveController.SpeedLinesMeshScript.LinesLerpOut(3); - + if (EndScriptComponent) { - EndScriptComponent.PlayOutro(); + EndScriptComponent.PlayOutro(); } - - for(var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) + + for(var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) shard.GetComponent.().Play(); - + if (audioSource) {audioSource.Play();} - FallingPlayer.ScoreFlashTextureScript.FadeFlash (12.0, FadeDir.In); + FallingPlayer.ScoreFlashTextureScript.FadeFlash(12.0, FadeDir.In); //yield WaitForSeconds (1.0); - //FallingPlayer.ScoreFlashTextureScript.FadeFlash (0.5, FadeDir.Out); + //FallingPlayer.ScoreFlashTextureScript.FadeFlash(0.5, FadeDir.Out); } } @@ -50,29 +52,37 @@ function GetChildren(obj : GameObject) : Array{ return children; } +function getDiamondCenter() { + return diamondCore.transform.position; +} + function SwapDiamonds(timer : float){ - FallingPlayer.ScoreFlashTextureScript.FadeFlash (3.0, FadeDir.Out); - FallingPlayer.UIscriptComponent.OutroDiamondFlash(2); - //yield WaitForSeconds (.2); - endDiamond.active = true; + if (!FallingLaunch.isVRMode) { + FallingPlayer.ScoreFlashTextureScript.FadeFlash(3.0, FadeDir.Out); + FallingPlayer.UIscriptComponent.OutroDiamondFlash(2); + } else { + FallingPlayerScript.ScoreFlashVR(3.0, FadeDir.Out); + } + endDiamond.active = true; + var start = shardColor.color; var end = Color.black; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; - - for(var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) + + for (var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) shard.transform.Find("sky-rock-angled-segment").GetComponent.().material.color = Color.Lerp(start, end, i); - + yield; } - + yield WaitForSeconds (1); - - for(var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) + + for(var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) Destroy (shard); } @@ -83,13 +93,13 @@ function AddDiamondCore(timer : float){ var end = .9; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; diamondCore.GetComponent.().material.color.a = Mathf.Lerp(start, end, i); yield; } - + yield WaitForSeconds (timer); } @@ -100,13 +110,13 @@ function FadeDiamond(timer : float){ var end = Color.black; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; endDiamond.GetComponent.().material.color = Color.Lerp(start, end, i); yield; } - + yield WaitForSeconds (timer); } @@ -120,14 +130,14 @@ function AddDiamond3DCore(timer : float){ var end = diamond3DCore1.GetComponent.().material.color; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; diamond3DCore1.GetComponent.().material.color = Color.Lerp(start, end, i); diamond3DCore2.GetComponent.().material.color = Color.Lerp(start, end, i); yield; } - + yield WaitForSeconds (timer); -} \ No newline at end of file +} diff --git a/FallingEndMenuUI.js b/FallingEndMenuUI.js index 9d97cac..7a5fd0c 100644 --- a/FallingEndMenuUI.js +++ b/FallingEndMenuUI.js @@ -20,6 +20,9 @@ var text3 : UITextInstance; var openSiteButtonText : UIButton; var BackToEndMenuButton : UIButton; +var appStoreButtonText : UITextInstance; +var appStoreButtonBg : UIButton; + function Start () { textHeight = (UIT.isHD == true) ? 18 : 18; @@ -79,28 +82,36 @@ function Start () { thinText.wrapMode = UITextLineWrapMode.None; text1 = thinText.addTextInstance( "CREATED BY TYSON KUBOTA", 0, 0 ); - //text1.positionFromTop(.3f); - //text1.positionFromCenter(-.1f,0f); - text1.pixelsFromCenter( -25, 0 ); + text1.pixelsFromCenter( -55, 0 ); text2 = boldText.addTextInstance( "tysonkubota.net/skydrift", 0, 0); - text2.positionCenter(); + text2.pixelsFromCenter( -30, 0 ); - //text3 = thinText.addTextInstance( "Music by Evan Kubota\nTextures: nobiax\nSound effects: freesound.org", 0, 0 ); - text3 = thinText.addTextInstance( "MUSIC BY EVAN KUBOTA\n\nSOUND EFFECTS: freesound.org", - 0, 0, 0.8f, 1, Color.white, UITextAlignMode.Center, UITextVerticalAlignMode.Bottom ); - text3.positionFromBottom(.3f); - - text1.hidden = true; - text2.hidden = true; - text3.hidden = true; + text3 = thinText.addTextInstance( "MUSIC BY EVAN KUBOTA\n\nSOUND EFFECTS: freesound.org", 0, 0); + text3.pixelsFromCenter( 45, 0 ); openSiteButtonText = UIButton.create("tutorialBackground.png","tutorialBackground.png", 40, 40); openSiteButtonText.positionFromCenter(0,0); openSiteButtonText.onTouchUpInside += OpenFallingSite; openSiteButtonText.scaleTo( 0.1f, new Vector3( (Screen.width), 3, 1 ), Easing.Sinusoidal.easeOut); openSiteButtonText.alphaFromTo(0.1f, 0.0f, 0.0f, Easing.Sinusoidal.easeOut); + + appStoreButtonText = boldText.addTextInstance( "WRITE A REVIEW...", 0, 0); + appStoreButtonText.positionFromBottom(.05); + + // A transparent tappable background; chosen for its width: + appStoreButtonBg = UIButton.create("spheresText.png", "spheresText.png", 0,0); + appStoreButtonBg.positionFromBottom(.05); + appStoreButtonBg.onTouchUpInside += OpenAppStorePage; + appStoreButtonBg.alphaFromTo(0.1f, 0.0f, 0.0f, Easing.Sinusoidal.easeOut); + + text1.hidden = true; + text2.hidden = true; + text3.hidden = true; + openSiteButtonText.hidden = true; + appStoreButtonText.hidden = true; + appStoreButtonBg.hidden = true; } @@ -182,21 +193,25 @@ function OpenAbout() { endGameSprite.hidden = true; BackToEndMenuButton.hidden = false; - BackToEndMenuButton.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); + BackToEndMenuButton.alphaFromTo(1.0, 0.0, 1.0, Easing.Sinusoidal.easeIn); EndMenuLogoCamera.GetComponent(Camera).enabled = false; + appStoreButtonBg.hidden = false; + appStoreButtonText.hidden = false; openSiteButtonText.hidden = false; text1.hidden = false; text2.hidden = false; text3.hidden = false; - text1.alphaFromTo(1.0f, 0.0f, 0.8f, Easing.Sinusoidal.easeOut); - text2.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeOut); - text3.alphaFromTo(1.5f, 0.0f, 0.6f, Easing.Sinusoidal.easeInOut); - + text1.alphaFromTo(1.0, 0.0, 0.8, Easing.Sinusoidal.easeOut); + text2.alphaFromTo(1.0, 0.0, 1.0, Easing.Sinusoidal.easeOut); + text3.alphaFromTo(1.5, 0.0, 0.6, Easing.Sinusoidal.easeInOut); + appStoreButtonText.alphaFromTo(2.5, 0.0, 1.0, Easing.Sinusoidal.easeIn); } function BackToEndMenu() { + appStoreButtonBg.hidden = true; + appStoreButtonText.hidden = true; BackToEndMenuButton.hidden = true; @@ -231,9 +246,18 @@ function fadeOutContinue() { } function OpenFallingSite() { - Application.OpenURL ("http://tysonkubota.net/skydrift?utm_source=skydrift-game&utm_medium=ios&utm_campaign=skydrift-gui"); + var urlToOpen : String = "http://tysonkubota.net/skydrift?utm_source=skydrift-game&utm_medium=ios&utm_campaign=skydrift-gui"; + // use a float instead of an int, as required by the GameAnalytics SDK: + FallingLaunch.Analytics.Event("OpenURL:FallingSite", FallingLaunch.levelAchieved*1.0); + Application.OpenURL(urlToOpen); } +function OpenAppStorePage() { + var urlToOpen : String = "https://itunes.apple.com/us/app/skydrift/id728636851?action=write-review&mt=8"; + // use a float instead of an int, as required by the GameAnalytics SDK: + FallingLaunch.Analytics.Event("OpenURL:AppStorePage", FallingLaunch.levelAchieved*1.0); + Application.OpenURL(urlToOpen); +} function ShowLevel1Logo() { fallingUITest.nextLevelLabel.hidden = false; diff --git a/FallingLaunch.js b/FallingLaunch.js index 4c60118..23b45eb 100644 --- a/FallingLaunch.js +++ b/FallingLaunch.js @@ -1,22 +1,29 @@ #pragma strict -static var flipMultiplier : float = 1; -static var landscapeFlipped : boolean = false; -static var levelEndSlowdown : int = 0; + +static var Analytics : AnalyticsUtil; + +static var flipMultiplier : float = 1.0; +static var levelEndSlowdown : float = 0.0; static var alreadyLaunched : boolean = false; -static var hasSetOrientation : boolean = false; static var NewGamePlus : boolean = false; var targetFPS : int = 30; static var isTablet : boolean = false; static var tiltable : boolean = false; + +static var initialInputDeviceOrientation : DeviceOrientation; +static var cachedScreenOrientation : ScreenOrientation; + static var hasSetAccel : boolean = false; static var restPosition : Vector3; static var neutralPosFlat : Vector3 = Vector3(0,0,-1.0); static var neutralPosTiltedRegular : Vector3 = Vector3(.6,0,-.9); static var neutralPosTiltedFlipped : Vector3 = Vector3(-.6,0,-.9); -static var neutralPosVertical : Vector3 = Vector3(1.0,0,0.0); -static var neutralPosTilted : Vector3; +static var neutralPosVerticalRegular = Vector3(1.0,0,0.0); +static var neutralPosVerticalFlipped = Vector3(-1.0,0,0.0); +static var neutralPosVertical : Vector3 = neutralPosVerticalRegular; +static var neutralPosTilted : Vector3 = neutralPosTiltedRegular; static var accelerator : Vector3; static var calibrationRotation : Quaternion; static var acceleratorSnapshot : Vector3; @@ -26,10 +33,15 @@ static var invertVertAxisVal : int; static var LoadedLatestLevel : boolean = false; static var levelAchieved : int; -static var debugMode : boolean = false; +static var debugMode : boolean = false; // true; var testFlightToken : String; +static var isVRMode : boolean = false; +static var vrModeAnalyticsString : String = "nonVRMode:"; +static var shouldShowVRIntroUI : boolean = false; +static var showingVREndGameUI : boolean = false; + //GameAnalytics variables static var secondsAlive : float = 0; static var secondsInLevel : float = 0; @@ -47,41 +59,34 @@ enum iPads { }; function Awake () { + isVRMode = false; // User can override this via start menu UI } function Start () { - + // PlayerPrefs.DeleteAll(); if (!alreadyLaunched) { - + Analytics = GetComponent.(); + // TestFlightUnity.TestFlight.TakeOff( testFlightToken ); - Debug.Log("Your screen orientation is " + Input.deviceOrientation + "!"); - - // if (!hasSetOrientation) { - // if (iPhoneInput.orientation == iPhoneOrientation.LandscapeRight) { - // flipMultiplier = flipMultiplier * -1; - // //Debug.Log("I'm in LandscapeRight!"); - // Screen.orientation = ScreenOrientation.LandscapeRight; - // landscapeFlipped = true; - // neutralPosTilted = neutralPosTiltedFlipped; - // } - // else { Screen.orientation = ScreenOrientation.LandscapeLeft; - // flipMultiplier = flipMultiplier * 1; - // //Debug.Log("I'm in LandscapeLeft, or Portrait, or FaceDown/Up!"); - // neutralPosTilted = neutralPosTiltedRegular; - // } - - // hasSetOrientation = true; - // } - - //this is necessary to override Unity 4's auto-orientation code + if (Debug.isDebugBuild) { + Debug.Log("Your device orientation is " + Input.deviceOrientation + "!"); + } + + initialInputDeviceOrientation = Input.deviceOrientation; + cachedScreenOrientation = Screen.orientation; + + // this is necessary to override Unity 4's auto-orientation code Input.compensateSensors = false; - + + // Debug.Log("Device orientation after Input.compensateSensors = false is " + Input.deviceOrientation); + var iOSGen = iOS.Device.generation; - - // Debug.Log("this is an " + iOSGen + " device!"); - // Debug.Log("Your screen dpi is " + Screen.dpi + "!"); - if (iOSGen == UnityEngine.iOS.DeviceGeneration.iPad1Gen || iOSGen == UnityEngine.iOS.DeviceGeneration.iPad2Gen || + + // Debug.Log("this is an " + iOSGen + " device!"); + + // Reduce target framerate for very old iOS devices: + if (iOSGen == UnityEngine.iOS.DeviceGeneration.iPad1Gen || iOSGen == UnityEngine.iOS.DeviceGeneration.iPad2Gen || iOSGen == UnityEngine.iOS.DeviceGeneration.iPhone4 || iOSGen == UnityEngine.iOS.DeviceGeneration.iPodTouch4Gen || iOSGen.ToString().Contains("iPhone3G")) { QualitySettings.DecreaseLevel(false); @@ -89,107 +94,89 @@ function Start () { } else { targetFPS = 60; - } - + } + + var screenDPI : float = Screen.dpi; + var screenWidthInInches: float = (Screen.width / screenDPI); + var screenHeightInInches: float = (Screen.height / screenDPI); + + // Debug.Log("Screen DPI: " + screenDPI); + // Debug.Log("Screen width in inches: " + screenWidthInInches); + // Debug.Log("Screen height in inches: " + screenHeightInInches); + + // DPI/screen size no longer a good heuristic for tablet vs. phone, so just use the iPad string regex: + // var hasLargeScreen: boolean = screenDPI > 0 && (screenWidthInInches > 8 && screenHeightInInches > 5); if (iOSGen.ToString().Contains("iPad")) { + // Debug.Log("Looks like a tablet!"); isTablet = true; + } else { + // Debug.Log("Based on device generation name string, not a tablet..."); + isTablet = false; } - - if (Screen.dpi > 0) { - if ((Screen.width / Screen.dpi) > 5 || (Screen.height / Screen.dpi) > 5) { - isTablet = true; - //Debug.Log("Looks like a tablet!"); - } - else { - isTablet = false; - //Debug.Log("Based on reported screen size, not a tablet..."); - } - } - + if (!Input.gyro.enabled) { Debug.Log("Your device doesn't have a gyroscope..."); } - // if ((iOSGen && + // if ((iOSGen && // (iPads.iPad1Gen | iPads.iPad2Gen | iPads.iPad3Gen | iPads.iPad4Gen | iPads.iPadMini1Gen | iPads.iPadUnknown)) != 0) { - - flipMultiplier = (isTablet == true) ? (2 * flipMultiplier) : (1.5 * flipMultiplier); + + flipMultiplier = isTablet ? 2 * flipMultiplier : 1.5 * flipMultiplier; DontDestroyOnLoad (this); alreadyLaunched = true; Application.targetFrameRate = targetFPS; - + Application.LoadLevel("Falling-scene-menu"); } else { Destroy(this.gameObject); } - + // myTimer = new GAUserTimer("Timer", "Session Length"); // myTimer.Start(); //Calibrate(); - //Calibrating in Start here was unwise, in case the user is swinging + //Calibrating in Start here was unwise, in case the user is swinging //the device around and the accelerometer readings haven't settled yet. } -function OnApplicationPause(pauseStatus: boolean) { - //paused = pauseStatus; - if (pauseStatus) { -// myTimer.Stop(); -// GoogleAnalytics.instance.Add(myTimer); -// GoogleAnalytics.instance.Dispatch(); - } +function EnableVRMode () { + isVRMode = true; + vrModeAnalyticsString = "isVRMode:"; } -function OnLevelWasLoaded (level : int) { - //loadedLevel = Application.loadedLevelName; -// var loadedLevel : GALevel = new GALevel(); -// GoogleAnalytics.instance.Add(loadedLevel); -// GoogleAnalytics.instance.Dispatch(); - - //Debug.Log("my loaded level is... " + Application.loadedLevelName); +function DisableVRMode () { + isVRMode = false; + vrModeAnalyticsString = "nonVRMode:"; } -function Calibrate () { - tiltable = false; - - if (PlayerPrefs.GetInt("TiltNeutral", 0) == 1) {restPosition = neutralPosTilted;} - else if (PlayerPrefs.GetInt("TiltNeutral", 0) == 2) {restPosition = neutralPosVertical;} - else {restPosition = neutralPosFlat;} - +function SetAxesInversion () { if (PlayerPrefs.GetInt("invertHorizAxis", 0) == 1) {invertHorizAxisVal = -1;} else {invertHorizAxisVal = 1;} if (PlayerPrefs.GetInt("invertVertAxis", 0) == 1) {invertVertAxisVal = -1;} else {invertVertAxisVal = 1;} - //acceleratorSnapshot = Input.acceleration; - acceleratorSnapshot = Vector3(0.0,0.0,-1.0); - calibrationRotation = Quaternion.FromToRotation(acceleratorSnapshot, restPosition); - - tiltable = true; } -function CalibrateInLevel () { +function Calibrate () { tiltable = false; - + if (PlayerPrefs.GetInt("TiltNeutral", 0) == 1) {restPosition = neutralPosTilted;} else if (PlayerPrefs.GetInt("TiltNeutral", 0) == 2) {restPosition = neutralPosVertical;} else {restPosition = neutralPosFlat;} - if (PlayerPrefs.GetInt("invertHorizAxis", 0) == 1) {invertHorizAxisVal = -1;} - else {invertHorizAxisVal = 1;} - if (PlayerPrefs.GetInt("invertVertAxis", 0) == 1) {invertVertAxisVal = -1;} - else {invertVertAxisVal = 1;} + SetAxesInversion(); + //acceleratorSnapshot = Input.acceleration; + acceleratorSnapshot = Vector3(0.0,0.0,-1.0); calibrationRotation = Quaternion.FromToRotation(acceleratorSnapshot, restPosition); tiltable = true; } - function ChangeTilt (toFlat : int) { if (toFlat == 2) { PlayerPrefs.SetInt("TiltNeutral", 2); Debug.Log("tilt set to vertical."); - } + } else if (toFlat == 0) { PlayerPrefs.SetInt("TiltNeutral", 0); Debug.Log("tilt set to flat."); @@ -197,14 +184,155 @@ function ChangeTilt (toFlat : int) { else { PlayerPrefs.SetInt("TiltNeutral", 1); Debug.Log("tilt set to angled."); - } - CalibrateInLevel(); + } + Calibrate(); +} + +// Only relevant in non-VR mode. +// In VR mode, we simply set landscapeLeft in all cases to meet the Google Cardboard SDK's expectations. +function LockDeviceOrientation (waitTime: float) { + cachedScreenOrientation = Screen.orientation; + + // Our outer function shouldn't actually get called if in VR mode, but for + // safety, defensively force landscapeLeft and early return in that case... + if (isVRMode) { + LockLandscapeLeftOrientation(isVRMode); + return; + } + + // Let the device auto-rotate if necessary: + Screen.autorotateToLandscapeLeft = true; + Screen.autorotateToLandscapeRight = true; + Screen.orientation = ScreenOrientation.AutoRotation; + + // iOS/Unity can give strange/wrong orientation values while screen is mid-rotation + // or close to flat, so we manually add a wait yield (~1s). + yield WaitForSeconds(waitTime); + + switch (Input.deviceOrientation) { + case DeviceOrientation.LandscapeLeft: + LockLandscapeLeftOrientation(isVRMode); + + FallingLaunch.Analytics.Event("DeviceOrientationSet:LandscapeLeft", 0.0); + break; + case DeviceOrientation.LandscapeRight: + LockLandscapeRightOrientation(); + + FallingLaunch.Analytics.Event("DeviceOrientationSet:LandscapeRight", 0.0); + break; + default: + HandleDeviceOrientationMismatch(); + + FallingLaunch.Analytics.Event("DeviceOrientationCheck:NonLandscape:" + Input.deviceOrientation, 0.0); + break; + } + + // These are handled within each individual LockLandscapeLeft/Right function: + // Screen.autorotateToLandscapeLeft = false; + // Screen.autorotateToLandscapeRight = false; + + Calibrate(); + + if (Debug.isDebugBuild) { + Debug.Log("Final screen orientation is: " + Screen.orientation); + } + + return; +} + + +function HandleDeviceOrientationMismatch() { + if (initialInputDeviceOrientation != Input.deviceOrientation) { + + FallingLaunch.Analytics.Event( + "DeviceOrientationCheck:CachedAndCurrentMismatch:" + Input.deviceOrientation + ":" + initialInputDeviceOrientation, + 0.0 + ); + + if (initialInputDeviceOrientation == DeviceOrientation.LandscapeLeft) { + if (Debug.isDebugBuild) { + Debug.Log("There's been a cached/current deviceOrientation mismatch. Setting to landscape left..."); + } + initialInputDeviceOrientation = Input.deviceOrientation; + LockLandscapeLeftOrientation(isVRMode); + } else if (initialInputDeviceOrientation == DeviceOrientation.LandscapeRight) { + if (Debug.isDebugBuild) { + Debug.Log("There's been a cached/current deviceOrientation mismatch. Setting to landscape right..."); + } + initialInputDeviceOrientation = Input.deviceOrientation; + LockLandscapeRightOrientation(); + } else { + DefaultToLandscapeLeftOrientation(); + } + + } else { + if (Debug.isDebugBuild) { + Debug.Log("InitialInputDeviceOrientation and Input.deviceOrientation do match, as " + Input.deviceOrientation); + } + FallingLaunch.Analytics.Event("DeviceOrientationSet:CachedAndCurrentMatch:" + Input.deviceOrientation, 0.0); + + // But we must choose left or right, ultimately... + DefaultToLandscapeLeftOrientation(); + } + + return; } -// function Update () { -// ListCurrentAccelerometer(); -// } -// -// function ListCurrentAccelerometer() { -// Debug.Log ("Your rotation is " + Input.acceleration); -// } \ No newline at end of file +function DefaultToLandscapeLeftOrientation() { + if (Screen.orientation == ScreenOrientation.LandscapeRight || cachedScreenOrientation == ScreenOrientation.LandscapeRight || + Input.deviceOrientation == DeviceOrientation.LandscapeRight) { + if (Debug.isDebugBuild) { + Debug.Log("Picking LandscapeRight, to match Screen.orientation or Input.deviceOrientation"); + } + LockLandscapeRightOrientation(); + } else { + if (Debug.isDebugBuild) { + Debug.Log("Defaulting to LandscapeLeft, since Screen.orientation / Input.deviceOrientation were not LandscapeRight"); + } + LockLandscapeLeftOrientation(isVRMode); + } +} + +function LockLandscapeLeftOrientation (isVR : boolean) { + if (Debug.isDebugBuild) {Debug.Log("Locking LandscapeLeft orientation with isVR " + isVR);} + + // if the device is held in landscapeRight already, + // the autorotateToLandscapeRight = false below is not enough + // to force the left-hand orientation needed for VR mode. + if (isVR) { + // We disable all autorotation before forcing the new orientation, to prevent + // UnityViewControllerBaseiOS.mm `UnityShouldAutorotate` assert crashes: + Screen.autorotateToLandscapeLeft = false; + Screen.autorotateToLandscapeRight = false; + Screen.autorotateToPortrait = false; + Screen.autorotateToPortraitUpsideDown = false; + Screen.orientation = ScreenOrientation.LandscapeLeft; + } + + cachedScreenOrientation = Screen.orientation; + + // Further interaction with Screen.autorotate... values will crash + // the app if we've already forced a given Screen.orientation + // (see UnityViewControllerBaseiOS.mm assert note above), so the below + // is for non-VR mode only: + if (!isVR) { + Screen.autorotateToLandscapeRight = false; + } + + neutralPosTilted = neutralPosTiltedRegular; + neutralPosVertical = neutralPosVerticalRegular; + flipMultiplier = 1.0; +} + +function LockLandscapeRightOrientation () { + if (Debug.isDebugBuild) {Debug.Log("Locking LandscapeRight orientation");} + + // Screen.orientation = ScreenOrientation.LandscapeRight; + cachedScreenOrientation = Screen.orientation; + + Screen.autorotateToLandscapeLeft = false; + + neutralPosTilted = neutralPosTiltedFlipped; + neutralPosVertical = neutralPosVerticalFlipped; + flipMultiplier = -1.0; +} diff --git a/FallingPlayer.js b/FallingPlayer.js index 3bf710a..3d689b4 100644 --- a/FallingPlayer.js +++ b/FallingPlayer.js @@ -1,9 +1,13 @@ -#pragma strict +#pragma strict +private var fallingLaunch : GameObject; +private var fallingLaunchComponent : FallingLaunch; + +// 10/25/2017: `Color` uses a 0-1 float range, not 0-2, in Unity. // 2 = 255 for rgba in this color array -static var startingFogColor : Color = Color(1.17, 1.17, 1.17, 2); +// static var startingFogColor : Color = Color(1.17, 1.17, 1.17, 2); static var startingFogEndDistance : int = 1500; -static var startingCameraFarClipPlane : int = 1700; +static var startingFogStartDistance : int = 150; static var startingCloudsAlpha : float = .25f; // Unity 4 used .39f (99 in RGBA) //original for corroded sky tubes level @@ -19,11 +23,13 @@ var ScoreFlashTexture : GameObject; static var ScoreFlashTextureScript : GUITextureLaunch; ScoreFlashTextureScript = ScoreFlashTexture.GetComponent("GUITextureLaunch"); +var lifeCountdownScript : lifeCountdown; + public var force:float = 1.0; var dir : Vector3 = Vector3.zero; enum FadeDir {In, Out} -var fadeTime = 0.75; +var fadeTime : float = 0.75; var origMat : Material; //var thisOceanCamera : Component; @@ -42,27 +48,62 @@ var tiltAroundX : float; var script : ScoreController; script = GetComponent("ScoreController"); -static var isAlive : int = 0; -isAlive = lifeCountdown.isAlive; +private var homeLevel : String = "Falling-scene-menu"; + +static var isAlive : int = 1; static var lifeStartTime : float = 0; static var levelStartTime : float = 0; -static var isNewGamePlus : String; - + static var isTiltable : boolean = true; static var isPausable : boolean = false; +private var isExitableFromVR : boolean = true; var isExitingLevel : boolean = false; var UIscriptName : GameObject; static var UIscriptComponent : fallingUITest; +var deathFadeUIVR : GameObject; +private var deathFadeUIVRRenderer : Renderer; +private var deathFadeUIVRMatl : Material; + +var opaqueDeathFadeUIVR : GameObject; +private var opaqueDeathFadeUIVRRenderer : Renderer; +private var opaqueDeathFadeUIVRMatl : Material; + +var levelStartUIVR : GameObject; +var deathPauseUIVR : GameObject; + +var whiteFadeUIVR : GameObject; +private var whiteFadeUIVRRenderer : Renderer; +private var whiteFadeUIVRMatl : Material; + +var whiteFadeEndGameUIVR : GameObject; +private var whiteFadeEndGameUIVRRenderer : Renderer; +private var whiteFadeEndGameUIVRMatl : Material; + +var scoreUIVR : GameObject; +private var scoreUIVRRenderer : Renderer; +private var scoreUIVRMatl : Material; +private var peakScoreFlashValueVR : float = 1.0; + +var reticleVRUIObj : GameObject; +static var reticleVRUIScript : VRLifeMeter; + +var endGameUIObjVR : GameObject; +private var endGameUIVRRenderer : Renderer; +private var endGameUIVRMatl : Material; + var clearDestroyedObjects : boolean = false; var whiteFader : FadeInOutAlt; -var introComponent : IntroSequence1stPerson; +private var introComponent : IntroSequence1stPerson; introComponent = GetComponent("IntroSequence1stPerson"); +var simpleVelocityLimiterComponent : SimpleVelocityLimiter; +simpleVelocityLimiterComponent = GetComponent("SimpleVelocityLimiter"); + var playAltScoreAudio : boolean = false; var clipToPlay : float; var audioToPlay : AudioSource; @@ -76,9 +117,21 @@ var myVol : float; var peakVol : float; private var myTransform : Transform; +private var myMainCamera : Camera; +private var myMainCameraTransform : Transform; + +private var myBackdrop : GameObject; +private var myBackdropRenderer : Renderer; private var BackdropMist : GameObject; -BackdropMist = transform.FindChild("Cylinder").gameObject; + +private var myVRViewer : GameObject; + +private var holdTime : float = 1.5; // continuous hold time needed to trigger a return-to-menu +private var holdAccumTime : float = 0.0; +private var holdThresholdForShowingLoadingBar : float = 0.5; +private var touchHoldStartTime : float = 0.0; +private var isTouchingResetUI : boolean = false; var rb : Rigidbody; @@ -86,40 +139,120 @@ function Awake() { // if (iPhoneInput.orientation == iPhoneOrientation.LandscapeRight) { // flipMultiplier = -1; //} - myTransform = transform; + myTransform = transform; } function Start() { -// startingFogColor = RenderSettings.fogColor * 2; + fallingLaunch = GameObject.Find("LaunchGameObject"); + fallingLaunchComponent = fallingLaunch.GetComponent.(); + + if (!FallingLaunch.isVRMode) { + // In case the calculation in the start menu was wrong/outmoded: + fallingLaunchComponent.LockDeviceOrientation(1.0); + } + + myMainCamera = Camera.main; + // Go up one level; this is the Player-cameras container object, which will get rotated on tilt: + myMainCameraTransform = myMainCamera.gameObject.transform.parent; + myBackdrop = GameObject.Find("plane-close"); + BackdropMist = GameObject.Find("Cylinder"); + myBackdropRenderer = myBackdrop ? myBackdrop.GetComponent.() : null; + lifeCountdownScript = gameObject.GetComponent.(); + + if (FallingLaunch.isVRMode) { + + myVRViewer = GameObject.Find("GvrViewerMain"); + scoreUIVRRenderer = scoreUIVR.GetComponent.(); + scoreUIVRMatl = scoreUIVRRenderer.material; + scoreUIVRMatl.color.a = 0; + + whiteFadeUIVRRenderer = whiteFadeUIVR.GetComponent.(); + whiteFadeUIVRMatl = whiteFadeUIVRRenderer.material; + whiteFadeUIVRMatl.color.a = 0; + + if (whiteFadeEndGameUIVR) { + whiteFadeEndGameUIVRRenderer = whiteFadeEndGameUIVR.GetComponent.(); + whiteFadeEndGameUIVRMatl = whiteFadeEndGameUIVRRenderer.material; + whiteFadeEndGameUIVRMatl.color.a = 0; + } + + // Hack to have two separate death/fade-to-black sphere objects, + // but neither shader does everything. The inverted transparent shader occludes + // all physical objects, but the UIToolkit one is needed for covering light halos. + // The opaque and transparent materials have manual RenderQueue settings + // of 5000 (the official max) and 6000, respectively. + if (deathFadeUIVR && opaqueDeathFadeUIVR) { + deathFadeUIVRRenderer = deathFadeUIVR.GetComponent.(); + deathFadeUIVRMatl = deathFadeUIVRRenderer.material; + + opaqueDeathFadeUIVRRenderer = opaqueDeathFadeUIVR.GetComponent.(); + opaqueDeathFadeUIVRMatl = opaqueDeathFadeUIVRRenderer.material; + + if (deathFadeUIVRMatl.HasProperty("_Color")) { + deathFadeUIVRMatl.color.a = 0; + } + if (opaqueDeathFadeUIVRMatl.HasProperty("_TintColor")) { + var currentColor : Color = opaqueDeathFadeUIVRMatl.GetColor("_TintColor"); + currentColor.a = 0; + opaqueDeathFadeUIVRMatl.SetColor("_TintColor", currentColor); + } + } + + if (reticleVRUIObj) { + reticleVRUIScript = reticleVRUIObj.GetComponent.(); + } else { + Debug.LogError("You forgot to assign an object for the VR reticle... trying to look up manually"); + reticleVRUIScript = GameObject.Find("vr-radial-life-meter").GetComponent.(); + } + } + startingFogEndDistance = RenderSettings.fogEndDistance; - startingCameraFarClipPlane = myTransform.FindChild("Camera").GetComponent.().farClipPlane; - isAlive = 1; - UIscriptComponent = UIscriptName.GetComponent(fallingUITest); - lifeStartTime = Time.time; - levelStartTime = Time.time; - isExitingLevel = false; - FallingLaunch.thisLevel = Application.loadedLevelName; + startingFogStartDistance = RenderSettings.fogStartDistance; + + isAlive = 1; + UIscriptComponent = UIscriptName.GetComponent(fallingUITest); + lifeStartTime = Time.time; + levelStartTime = Time.time; + isExitingLevel = false; + FallingLaunch.thisLevel = Application.loadedLevelName; FallingLaunch.thisLevelArea = "0-start"; AudioListener.pause = false; myVol = audioScore.volume; peakVol = audioScore.volume; -// fadeInAudio (); - FadeAudio (0.1, FadeDir.In); - isPausable = false; + FadeAudio(0.1, FadeDir.In); + isPausable = false; rb = GetComponent.(); - rb.isKinematic = false; + if (FallingLaunch.isVRMode && levelStartUIVR && FallingLaunch.shouldShowVRIntroUI) { + levelStartUIVR.SetActive(true); + isAlive = 0; + rb.isKinematic = true; + } else { + isAlive = 1; + rb.isKinematic = false; + } + + // introComponent's existence is a proxy for level 1, + // where we don't want the reticle to be visible yet + // (resuming from a level 1 post-intro checkpoint + // is handled in Respawn.js (mainRespawnScript): if (!introComponent) { UIscriptComponent.UnhideGUI(); + + if (FallingLaunch.isVRMode) { + reticleVRUIScript.FadeReticleIn(1.5); + } } LevelStartFade(); } function LevelStartFade () { - if (PlayerPrefs.HasKey("LatestLevel") && PlayerPrefs.GetString("LatestLevel") == Application.loadedLevelName) - {FallingLaunch.LoadedLatestLevel = true;} + if (PlayerPrefs.HasKey("LatestLevel") && + PlayerPrefs.GetString("LatestLevel") == Application.loadedLevelName) { + FallingLaunch.LoadedLatestLevel = true; + } if (FallingLaunch.LoadedLatestLevel == false) { introFade(); @@ -136,77 +269,144 @@ function introFade() { function introNow() { LatestCheckpointRespawn(); - yield WaitForSeconds (3); + yield WaitForSeconds (3); FallingLaunch.LoadedLatestLevel = false; whiteFader = Camera.main.GetComponent(FadeInOutAlt); - whiteFader.enabled = false; + if (whiteFader) {whiteFader.enabled = false;} } -function FadeAudio (timer : float, fadeType : FadeDir) { +function FadeAudio(timer : float, fadeType : FadeDir) { - var start = fadeType == FadeDir.In? 0.0 : 1.0; - var end = fadeType == FadeDir.In? 1.0 : 0.0; - var i = 0.0; - var step = 1.0/timer; + var start = fadeType == FadeDir.In? 0.0 : 1.0; + var end = fadeType == FadeDir.In? 1.0 : 0.0; + var i = 0.0; + var step = 1.0/timer; - while (i <= 1.0) { - i += step * Time.deltaTime; - AudioListener.volume = Mathf.Lerp(start, end, i); - yield; - } + while (i <= 1.0) { + i += step * Time.deltaTime; + // var t : float = Mathf.Sin(i * Mathf.PI * 0.5f); // ease-out lerp + AudioListener.volume = Mathf.Lerp(start, end, i); + yield; + } +} + +function ShowDeathInterstitialVR() { + rb.isKinematic = true; + isAlive = 0; + + deathPauseUIVR.SetActive(true); + + yield DeathFadeVR(1.0, FadeDir.In); + // yield UIscriptComponent.fadeIn(false); + + // Managing isExitableFromVR gives finer control over the exit UI, + // preventing the player from tapping mid-respawn fadeout. + isExitableFromVR = true; + // yield WaitForSeconds(4); + + while (true && FallingLaunch.isVRMode && isAlive == 0 && Input.touchCount == 0 && + deathPauseUIVR.activeInHierarchy && isExitableFromVR && !isTouchingResetUI) { + yield WaitForSeconds(4); + if (isAlive == 0 && Input.touchCount == 0 && deathPauseUIVR.activeInHierarchy && + isExitableFromVR && !isTouchingResetUI) { + // Debug.Log("it's been enough time; auto-respawning"); + RespawnAfterDeathInterstitialVR(); + } + } + + // // Only execute this if it's been four seconds and a respawn is not already underway: + // if (isAlive == 0 && deathPauseUIVR.activeInHierarchy && isExitableFromVR) { + // RespawnAfterDeathInterstitialVR(); + // } } +function RespawnAfterDeathInterstitialVR() { + isExitableFromVR = false; + + yield DeathFadeVR(0.5, FadeDir.Out); + + rb.isKinematic = false; + + // TODO: Fade out material here instead of toggling the whole object outright? + deathPauseUIVR.SetActive(false); + + // resetting score to max here for VR, to avoid the score + // ticking away over the preceding ~4 WaitForSeconds. + script.ResetScore(); + + // In VR mode, we ignore fadeTime in favor of a longer fade-in + // matched to the longer waiting interval below: + FadeAudio(2.0, FadeDir.In); + + DeathFadeVR(1.0, FadeDir.In); + isPausable = true; + + // setting isAlive is order-dependent with lerpControlIn below + // (isAlive = 0 will break its loop): + isAlive = 1; + lerpControlIn(3.0); + + yield WaitForSeconds(1); + reticleVRUIScript.FadeReticleIn(1.5); +} function DeathRespawn () { - isPausable = false; - rb.isKinematic = true; - lifeStartTime = Time.time; - var respawnPosition = Respawn.currentRespawn.transform.position; - - UIscriptComponent.fadeOut(); -// Camera.main.SendMessage("fadeOut"); + isPausable = false; + rb.isKinematic = true; + lifeStartTime = Time.time; + var respawnPosition = Respawn.currentRespawn.transform.position; + + if (FallingLaunch.isVRMode) { + reticleVRUIScript.FadeReticleOut(0.5); + FadeAudio(1.5, FadeDir.Out); + yield DeathFadeVR(1.0, FadeDir.Out); + } else { + FadeAudio(fadeTime, FadeDir.Out); + yield UIscriptComponent.fadeOut(); + } - if (levelChangeBackdrop == true) { - changeLevelBackdrop (); - } - -// fadeOutAudio (); - FadeAudio ((fadeTime), FadeDir.Out); - - script.ResetScore(0); + if (levelChangeBackdrop == true) { + changeLevelBackdrop (); + } - yield WaitForSeconds(1); + // VR mode does its own score reset later, due to a longer fade interval/ + // interstitial 'back to menu' screen. + if (!FallingLaunch.isVRMode) { + script.ResetScore(); + } -// if you want to clear destroyed projectiles... - if (clearDestroyedObjects == true) { - Resources.UnloadUnusedAssets(); - } + // If you want to clear destroyed projectiles (set per-level)... + if (clearDestroyedObjects) { + Resources.UnloadUnusedAssets(); + } - isAlive = 1; - RenderSettings.fogEndDistance = startingFogEndDistance; - -// Camera.main.transform.position = respawnPosition - (transform.forward * 4) + Vector3.up; // reset camera too - GetComponent.().attachedRigidbody.transform.Translate(respawnPosition); - // Relocate the player. We need to do this or the camera will keep trying to focus on the (invisible) player where he's standing on top of the FalloutDeath box collider. - myTransform.position = respawnPosition; // + Vector3.up; -// Camera.main.SendMessage("fadeIn"); - - FadeAudio (fadeTime, FadeDir.In); -// thisOceanCamera.SendMessage("fadeIn"); - rb.isKinematic = false; -// isAlive = 1; - - MoveController.controlMultiplier = 1; - - lerpControlIn(3); - yield UIscriptComponent.fadeIn(true); -} + isAlive = 1; + RenderSettings.fogEndDistance = startingFogEndDistance; + RenderSettings.fogStartDistance = startingFogStartDistance; + + // Camera.main.transform.position = respawnPosition - (transform.forward * 4) + Vector3.up; // reset camera too + GetComponent.().attachedRigidbody.transform.Translate(respawnPosition); + // Relocate the player. We need to do this or the camera will keep trying to focus on the (invisible) player where he's standing on top of the FalloutDeath box collider. + myTransform.position = respawnPosition; // + Vector3.up; + + rb.isKinematic = false; + + MoveController.controlMultiplier = 1.0; + + if (FallingLaunch.isVRMode && deathPauseUIVR && deathFadeUIVR) { + ShowDeathInterstitialVR(); + } else { + FadeAudio(fadeTime, FadeDir.In); + lerpControlIn(3.0); + yield UIscriptComponent.fadeIn(true); + } +} function LatestCheckpointRespawn () { isPausable = false; rb.isKinematic = true; - var respawnPosition = Respawn.currentRespawn.transform.position; + var respawnPosition = Respawn.currentRespawn.transform.position; //UIscriptComponent.fadeOut(); if (levelChangeBackdrop == true) { @@ -214,106 +414,364 @@ function LatestCheckpointRespawn () { } // yield WaitForSeconds(1); - isAlive = 1; + // if in VR intro, don't set isAlive yet, since that will start the lifeCountdown timer ticking: + if (FallingLaunch.isVRMode && FallingLaunch.shouldShowVRIntroUI) { + isAlive = 0; + } else { + isAlive = 1; + } + RenderSettings.fogEndDistance = startingFogEndDistance; - + RenderSettings.fogStartDistance = startingFogStartDistance; + GetComponent.().attachedRigidbody.transform.Translate(respawnPosition); myTransform.position = respawnPosition; // + Vector3.up; - FadeAudio (fadeTime, FadeDir.In); - rb.isKinematic = false; - - MoveController.controlMultiplier = 1; - - lerpControlIn(3); - //yield UIscriptComponent.fadeIn(true); - UIscriptComponent.UnhideGUI(); -} + FadeAudio(fadeTime, FadeDir.In); + + if (!FallingLaunch.isVRMode) { + rb.isKinematic = false; + lerpControlIn(3.0); + UIscriptComponent.UnhideGUI(); + } +} function ShowDeathHelp() { - if (introComponent) { - introComponent.DeathHelp(); - } + if (introComponent) { + introComponent.DeathHelp(); + } } function changeLevelBackdrop () { - changeBackdrop.oceanCamera.GetComponent(Camera).enabled = false; - changeBackdrop.oceanRenderer.enabled = false; - changeBackdrop.cloudRenderer.enabled = false; - changeBackdrop.endSphereRenderer.enabled = false; + if (!FallingLaunch.isVRMode) { + if (changeBackdrop.oceanCameraVR) { + changeBackdrop.oceanCameraVR.GetComponent(Camera).enabled = false; + } + } + + // needed even in VR mode, so the ocean renderer disables on respawn: + if (changeBackdrop.oceanCamera) { + changeBackdrop.oceanCamera.GetComponent(Camera).enabled = false; + changeBackdrop.oceanRenderer.enabled = false; + } // the Fade argument below this breaks unpredictably if player gameobject lacks a Fade script component - // Fade.use.Colors(guiTexture, (RenderSettings.fogColor * 2), startingFogColor, 2.0); + // Fade.use.Colors(guiTexture, (RenderSettings.fogColor * 2), startingFogColor, 2.0); RenderSettings.fogEndDistance = startingFogEndDistance; - myTransform.FindChild("Camera").GetComponent.().farClipPlane = startingCameraFarClipPlane; - myTransform.FindChild("plane-close").GetComponent.().materials = [origMat]; - iTween.ColorTo(BackdropMist,{"a":startingCloudsAlpha,"time":.5}); - } - + RenderSettings.fogStartDistance = startingFogStartDistance; + + if (myMainCamera) { + // reset regular or VR cameras' clip planes (handles both cases internally): + changeBackdrop.ResetCameraClipPlane(); + } + if (myBackdropRenderer) { + myBackdropRenderer.materials = [origMat]; + } + if (BackdropMist) { + iTween.ColorTo(BackdropMist,{"a": startingCloudsAlpha,"time": .5}); + } +} + function Update () { - playerTilt (); + // playerTilt moves camera on device tilt. Enable if not in VR mode: + if (!FallingLaunch.isVRMode) { + playerTilt(); + } + + // disable VR mode and return to menu on screen touch while dead: + if (FallingLaunch.isVRMode) { + + if (FallingLaunch.showingVREndGameUI) { + for (var i3 = 0; i3 < Input.touchCount; ++i3) { + if (Input.GetTouch(i3).phase == TouchPhase.Ended && Input.GetTouch(i3).phase != TouchPhase.Canceled) { + // PlayerPrefs.DeleteKey("LatestCheckpoint"); + // PlayerPrefs.SetString("LatestLevel", "Falling-scene-tutorial"); + FallingLaunch.showingVREndGameUI = false; + Application.LoadLevel(homeLevel); + } + } + } + + if (isAlive == 0 && deathPauseUIVR.activeInHierarchy) { //} && isExitableFromVR) { + + if (Input.touchCount > 0) { + // Debug.Log("Starting touchHoldStartTime " + touchHoldStartTime); + // Debug.Log("Time.time " + Time.time); + + // as soon as any fingers are on screen, block the auto-respawning: + isExitableFromVR = false; + + if (Input.GetTouch(0).phase == TouchPhase.Began) { + touchHoldStartTime = Time.time; + isTouchingResetUI = true; + } + + // var adjustedHoldAccumTime : float = (touchHoldStartTime < Time.time) ? 0.0 : + var adjustedHoldAccumTime : float = !isTouchingResetUI ? 0.0 : + Mathf.Max(Time.time - touchHoldStartTime - holdThresholdForShowingLoadingBar, 0.0); + + // holdAccumTime += Input.GetTouch(0).deltaTime; + + // Old way, using accumulated touch time instead of subtractive via Time.time: + // var adjustedHoldAccumTime : float = (touchHoldStartTime < Time.time) ? 0.0 : + // Mathf.Max(holdAccumTime - holdThresholdForShowingLoadingBar, 0.0); + + if (adjustedHoldAccumTime > 0.0) { + // Debug.Log("Updating loading circle with adjustedHoldAccumTime " + adjustedHoldAccumTime); + // takes care of showing and updating filled 'loading' sprite: + reticleVRUIScript.UpdateLoadingCircle( + adjustedHoldAccumTime / holdTime + ); + } + + // Long tap (~2+ secs): + if (adjustedHoldAccumTime >= holdTime) { + // Debug.Log("long tap with adjustedHoldAccumTime " + adjustedHoldAccumTime); + reticleVRUIScript.HideLoadingCircle(); + isPausable = false; + fallingLaunchComponent.DisableVRMode(); + UIscriptComponent.SaveCheckpointVR(); + Application.LoadLevel(homeLevel); + } + + if (Input.GetTouch(0).phase == TouchPhase.Ended) { + reticleVRUIScript.HideLoadingCircle(); + + var actualTouchTime : float = !isTouchingResetUI ? 0.0 : Time.time - touchHoldStartTime; + // Short-ish tap (in practice, under ~.875 seconds): + if (actualTouchTime > 0.0 && adjustedHoldAccumTime <= holdTime / 4.0) { + // Debug.Log( + // "With adjustedHoldAccumTime " + adjustedHoldAccumTime + + // ", that counts as a short tap; time to respawn!" + // ); + // Debug.Log( + // "With actualTouchTime " + actualTouchTime + + // ", that counts as a short tap; time to respawn!" + // ); + RespawnAfterDeathInterstitialVR(); + } + + holdAccumTime = 0; + } + } else { + // holdAccumTime = 0; + isTouchingResetUI = false; + + // Once no fingers are touching, resetting this boolean will let the loop + // in ShowDeathInterstitialVR respawn the player after a 4-second delay. + isExitableFromVR = true; + } + } else { + isTouchingResetUI = false; + } + + if (levelStartUIVR.activeInHierarchy && FallingLaunch.shouldShowVRIntroUI) { + for (var i2 = 0; i2 < Input.touchCount; ++i2) { + if (Input.GetTouch(i2).phase == TouchPhase.Ended && Input.GetTouch(i2).phase != TouchPhase.Canceled) { + ContinueFromLevelStartVR(); + } + } + } + + } + //Debug.Log("slowdown is: " + MoveController.Slowdown + " and myVol is: " + myVol); //Debug.Log("your current acceleration is: " + FallingLaunch.accelerator); } - -function playerTilt () { + +function playerTilt() { if (isTiltable == true) { var dir : Vector3 = Vector3.zero; if (FallingLaunch.hasSetAccel == false) { FallingLaunch.accelerator = FallingLaunch.calibrationRotation * Input.acceleration; } - tiltAroundZ = FallingLaunch.invertHorizAxisVal * Mathf.Clamp((FallingLaunch.flipMultiplier * (-FallingLaunch.accelerator.y * tiltAngle)), -tiltAngle, tiltAngle); - tiltAroundX = FallingLaunch.invertVertAxisVal * Mathf.Clamp((FallingLaunch.flipMultiplier * (-FallingLaunch.accelerator.x * tiltAngle)), -tiltAngle, tiltAngle); + + tiltAroundX = FallingLaunch.invertVertAxisVal * Mathf.Clamp((FallingLaunch.flipMultiplier * (-FallingLaunch.accelerator.x * tiltAngle)), -tiltAngle, tiltAngle); + + tiltAroundZ = FallingLaunch.invertHorizAxisVal * Mathf.Clamp((FallingLaunch.flipMultiplier * (-FallingLaunch.accelerator.y * tiltAngle)), -tiltAngle, tiltAngle); - var target = Quaternion.Euler (tiltAroundX, 0, tiltAroundZ); - // Dampen towards the target rotation - myTransform.rotation = Quaternion.Lerp(myTransform.rotation, target, - Time.deltaTime * smooth); + var target : Quaternion = Quaternion.Euler (tiltAroundX, 0, tiltAroundZ); + // Dampen towards the target rotation + // Rotating the camera transform, not the Player transform itself, so the 3D clouds + // (which are the child of the Player object) have correct tilt context. + myMainCameraTransform.rotation = Quaternion.Lerp(myMainCameraTransform.rotation, target, + Time.deltaTime * smooth); } -} +} function lerpControlIn(timer : float) { - - //Debug.Log("your flip multiplier is " + FallingLaunch.flipMultiplier); - //Debug.Log("your control multiplier is " + MoveController.controlMultiplier); - + + // Debug.Log("your flip multiplier is " + FallingLaunch.flipMultiplier); + // Debug.Log("your control multiplier is " + MoveController.controlMultiplier); + var start = 0.0; - var end = MoveController.controlMultiplier; + var end = 1.0; // MoveController.controlMultiplier; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; MoveController.controlMultiplier = Mathf.Lerp(start, end, i); - if (isAlive == 0) {MoveController.controlMultiplier = end; break;} + if (isAlive == 0) {MoveController.controlMultiplier = end; break;} yield; - - if (i >= 1.0 || isAlive == 0) {MoveController.controlMultiplier = end; break;} + + if (i >= 1.0 || isAlive == 0) {MoveController.controlMultiplier = end; break;} } yield WaitForSeconds (timer); } function lerpControlOut(timer : float) { - var start = MoveController.controlMultiplier; - var end = 0.0; + var startControl : float = MoveController.controlMultiplier; + var end : float = 0.0; + var startMaxVelocity : float = simpleVelocityLimiterComponent.GetMaxVelocity(); + var endVelocity : float = 0; // startMaxVelocity * .15; // / 3; + + // timer 1 and 2 run sequentially via the two `yields` / + // inner `while` looops below, adding up to the overall `timer` argument: + var timer2 : float = 1.25; + var timer1 : float = timer - timer2; + + var i = 0.0; + var step = 1.0/timer1; + + while (i <= 1.0) { + i += step * Time.deltaTime; + + var controlT : float = Mathf.Sin(i * Mathf.PI * 0.5f); // ease-out lerp + + MoveController.controlMultiplier = Mathf.Lerp(startControl, end, controlT); + + if (isAlive == 0) { + MoveController.controlMultiplier = startControl; + simpleVelocityLimiterComponent.SetMaxVelocity(startMaxVelocity); + break; + } + + yield; + + // the && is because the smootherstep math can overshoot 1.0 on its own: + if (i >= 1.0 && isAlive == 0) { + MoveController.controlMultiplier = startControl; + simpleVelocityLimiterComponent.SetMaxVelocity(startMaxVelocity); + break; + } + } + + // In the final bit of time (timer2), lerp the speed cap down to zero: + var i2 : float = 0.0; + var step2 = 1.0/timer2; + + while (i2 <= 1.0) { + i2 += step2 * Time.deltaTime; + + // var maxVelocityT : float = i2*i2*i2 * (i2 * (6f*i2 - 15f) + 10f); // smootherstep lerp + var maxVelocityT : float = Mathf.Sin(i2 * Mathf.PI * 0.5f); // ease-out lerp + + var newMaxVelocity : float = Mathf.Lerp(startMaxVelocity, endVelocity, maxVelocityT); + + simpleVelocityLimiterComponent.SetMaxVelocity(newMaxVelocity); + + if (isAlive == 0) { + MoveController.controlMultiplier = startControl; + simpleVelocityLimiterComponent.SetMaxVelocity(startMaxVelocity); + break; + } + + yield; + + // the && is because the smootherstep math can overshoot 1.0 on its own: + if (i2 >= 1.0 && isAlive == 0) { + MoveController.controlMultiplier = startControl; + simpleVelocityLimiterComponent.SetMaxVelocity(startMaxVelocity); + break; + } + } +} + +function ScoreFlashVR (timer : float, fadeType : FadeDir) { + + var start = fadeType == FadeDir.In? 0.0 : peakScoreFlashValueVR; + var end = fadeType == FadeDir.In? peakScoreFlashValueVR : 0.0; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; - MoveController.controlMultiplier = Mathf.Lerp(start, end, i); - if (isAlive == 0) {MoveController.controlMultiplier = start; break;} - + scoreUIVRMatl.color.a = Mathf.Lerp(start, end, i); yield; + } +} - if (i >= 1.0 || isAlive == 0) {MoveController.controlMultiplier = start; break;} - } - yield WaitForSeconds (timer); +function DeathFadeVR (timer : float, fadeType : FadeDir) { + + var start = fadeType == FadeDir.In ? 1.0 : 0.0; + var end = fadeType == FadeDir.In ? 0.0 : 1.0; + var i = 0.0; + var step = 1.0/timer; + + while (i <= 1.0) { + i += step * Time.deltaTime; + // ease-out lerp, to match non-VR fade timing: + var t : float = Mathf.Sin(i * Mathf.PI * 0.5f); + + if (deathFadeUIVRMatl.HasProperty("_Color")) { + deathFadeUIVRMatl.color.a = Mathf.Lerp(start, end, t); + } + if (opaqueDeathFadeUIVRMatl.HasProperty("_TintColor")) { + var currentColor : Color = opaqueDeathFadeUIVRMatl.GetColor("_TintColor"); + currentColor.a = Mathf.Lerp(start, end, t); + opaqueDeathFadeUIVRMatl.SetColor("_TintColor", currentColor); + } + + yield; + } } - + +function WhiteFadeVR (timer : float, fadeType : FadeDir) { + + var start = fadeType == FadeDir.In ? 1.0 : 0.0; + var end = fadeType == FadeDir.In ? 0.0 : 1.0; + var i = 0.0; + var step = 1.0/timer; + + while (i <= 1.0) { + i += step * Time.deltaTime; + whiteFadeUIVRMatl.color.a = Mathf.Lerp(start, end, i); + yield; + } +} + +function WhiteFadeVREndGame (timer : float) { + + var start = 0.0; + var end = 0.66; + var i = 0.0; + var step = 1.0/timer; + + if (endGameUIObjVR) { + endGameUIObjVR.SetActive(true); + endGameUIVRRenderer = endGameUIObjVR.GetComponent.(); + endGameUIVRMatl = endGameUIVRRenderer.material; + } + + if (whiteFadeEndGameUIVR) { + whiteFadeEndGameUIVR.SetActive(true); + } + + while (i <= 1.0) { + i += step * Time.deltaTime; + whiteFadeEndGameUIVRMatl.color.a = Mathf.Lerp(start, end, i); + if (endGameUIVRMatl) {endGameUIVRMatl.color.a = Mathf.Lerp(start, end, i);} + yield; + } + + // this will allow screen taps to return to the main menu: + FallingLaunch.showingVREndGameUI = true; +} + function OnCollisionEnter (collision : Collision) { // Debug.Log("Hit something!" + collision.contacts[0].normal + dir.x + dir.z + Input.acceleration.x); // Screen.sleepTimeout = 0.0f; @@ -322,23 +780,26 @@ function OnCollisionEnter (collision : Collision) { if (isPausable == true || collision.gameObject.layer == 17 ) { isAlive = 0; isPausable = false; - lifeCountdown.LifeFlashTextureScript.FadeFlash (1, FadeDir.Out); - UIscriptComponent.HideGUI(); + + if (!FallingLaunch.isVRMode) { + lifeCountdown.LifeFlashTextureScript.FadeFlash(1, FadeDir.Out); + UIscriptComponent.HideGUI(); + } else { + lifeCountdownScript.FadeFlashVR(1.0, FadeDir.Out); + } + FallingLaunch.secondsAlive = (Time.time - lifeStartTime); - + if (audioDeath) {audioDeath.Play();} - - // GA.API.Design.NewEvent("Death:Collision:" + Application.loadedLevelName + ":" + FallingLaunch.thisLevelArea, FallingLaunch.secondsAlive, myTransform.position); - - //var deathCollideEvent : GAEvent = new GAEvent("Death", "Collision", FallingLaunch.thisLevelArea, FallingLaunch.secondsAlive); - //GoogleAnalytics.instance.Add(deathCollideEvent); - //GoogleAnalytics.instance.Dispatch(); + + FallingLaunch.Analytics.Event( + "Death:Collision:" + FallingLaunch.vrModeAnalyticsString + Application.loadedLevelName + ":" + FallingLaunch.thisLevelArea, + FallingLaunch.secondsAlive + ); //Debug.Log("you died in the area " + FallingLaunch.thisLevelArea); //Debug.Log("You died in a fatal collision with " + collision.gameObject); - + yield DeathRespawn (); - //isPausable = true; - //UIscriptComponent.UnhideGUI(); } } @@ -346,70 +807,98 @@ function OnCollisionEnter (collision : Collision) { function OnTriggerEnter (other : Collider) { if (other.gameObject.CompareTag ("Score")){ + // Debug.Log("You scored!"); -// Debug.Log("You scored!"); -// Camera.main.SendMessage("flashOut"); - ScoreFlashTextureScript.FadeFlash (0.8, FadeDir.Out); - - script.IncrementScore(6); - UIscriptComponent.flashProgressBar(1); - - if (audioScore) { - //Debug.Log(Random.Range(0,2)); - myVol = ((MoveController.Slowdown / MoveController.maxSlowdown) * peakVol); - clipToPlay = Random.Range(0.3f, 0.9f); - pitchRand = Random.Range(0.98f,1.03f); - - if (playAltScoreAudio) { - audioToPlay = audioScoreAlt; - playAltScoreAudio = false; - } - else { - audioToPlay = audioScore; - playAltScoreAudio = true; - } - - audioToPlay.pitch = pitchRand; - - //if (clipToPlay == 1) {audioToPlay = audioScoreAlt;} - if (clipToPlay > 0.6f) { - audioToPlay.panStereo = (-clipToPlay/2); - audioToPlay.volume = Mathf.Clamp(myVol, (peakVol/2), peakVol); - } - else { - audioToPlay.volume = clipToPlay; - audioToPlay.panStereo = (clipToPlay/2); - } - - //audioToPlay.volume = Mathf.Clamp(myVol, (peakVol * .5), peakVol); - audioToPlay.Play(); - } - - //yield WaitForSeconds(.2); - -// try using PlayClipAtPoint here so score sound fades away in 3D space as you fall? + if (FallingLaunch.isVRMode) { + ScoreFlashVR(0.8, FadeDir.Out); + } else { + ScoreFlashTextureScript.FadeFlash(0.8, FadeDir.Out); + } -// Camera.main.SendMessage("flashUp"); + script.IncrementScore(6); + UIscriptComponent.flashProgressBar(1); + + if (audioScore) { + //Debug.Log(Random.Range(0,2)); + myVol = ((MoveController.Slowdown / MoveController.maxSlowdown) * peakVol); + clipToPlay = Random.Range(0.3f, 0.9f); + pitchRand = Random.Range(0.98f,1.03f); + + if (playAltScoreAudio) { + audioToPlay = audioScoreAlt; + playAltScoreAudio = false; + } + else { + audioToPlay = audioScore; + playAltScoreAudio = true; + } + + audioToPlay.pitch = pitchRand; + + //if (clipToPlay == 1) {audioToPlay = audioScoreAlt;} + if (clipToPlay > 0.6f) { + audioToPlay.panStereo = (-clipToPlay/2); + audioToPlay.volume = Mathf.Clamp(myVol, (peakVol/2), peakVol); + } + else { + audioToPlay.volume = clipToPlay; + audioToPlay.panStereo = (clipToPlay/2); + } + + //audioToPlay.volume = Mathf.Clamp(myVol, (peakVol * .5), peakVol); + audioToPlay.Play(); + } + + //yield WaitForSeconds(.2); + + // try using PlayClipAtPoint here so score sound fades away in 3D space as you fall? + // Camera.main.SendMessage("flashUp"); } - + if (other.gameObject.CompareTag ("LevelEnd") && isExitingLevel == false) { isExitingLevel = true; - isPausable = false; - isNewGamePlus = (FallingLaunch.NewGamePlus) ? "new_game_plus" : "first_game"; - FallingLaunch.secondsInLevel = (Time.time - levelStartTime); - - // GA.API.Design.NewEvent("LevelComplete:" + isNewGamePlus, FallingLaunch.secondsInLevel, myTransform.position); - // TestFlightUnity.TestFlight.PassCheckpoint( "LevelComplete:" + Application.loadedLevelName ); - - // to keep you from dying after you strike the levelend trigger - script.IncrementScore(25); - - audioLevelEnd.Play(); - lerpControlOut(3); - //yield WaitForSeconds (audioLevelEnd.clip.length - 3); - //yield WaitForSeconds (1); - UIscriptComponent.LevelComplete(); - } + isPausable = false; + var isNewGamePlus = (FallingLaunch.NewGamePlus) ? "new_game_plus" : "first_game"; + FallingLaunch.secondsInLevel = (Time.time - levelStartTime); + + FallingLaunch.Analytics.Event( + "LevelComplete:" + FallingLaunch.vrModeAnalyticsString + SceneManagement.SceneManager.GetActiveScene().name + ":" + isNewGamePlus, + FallingLaunch.secondsInLevel + ); + + // reset the level area identifier for analytics purposes: + FallingLaunch.thisLevelArea = "0-start"; + + // TestFlightUnity.TestFlight.PassCheckpoint( "LevelComplete:" + Application.loadedLevelName ); + + // to keep you from dying after you strike the levelend trigger + script.IncrementScore(25); + + audioLevelEnd.Play(); + + // the lerpControlOut timer argument must be equal to, or just less than, + // the sum of levelComplete's first argument, + // in order to create a convincing slowdown lerp and UI/camera fadeout: + lerpControlOut(4.0); + + if (FallingLaunch.isVRMode) { + WhiteFadeVR(3.0, FadeDir.Out); + } + // Handles 2D (non-VR) UI logic in its own conditional, + // plus saves progress, loads the next level, etc. + UIscriptComponent.LevelComplete(3.0, 1.5); + } +} + +function ContinueFromLevelStartVR () { + FallingLaunch.shouldShowVRIntroUI = false; + + // TODO: Fade out material here instead of toggling the whole object outright? + levelStartUIVR.SetActive(false); + rb.isKinematic = false; + isAlive = 1; + isPausable = true; + lerpControlIn(1.5); } - -@script AddComponentMenu("Scripts/FallingPlayer") \ No newline at end of file + +@script AddComponentMenu("Scripts/FallingPlayer") diff --git a/FallingPlayerStart.js b/FallingPlayerStart.js index 14a14f6..cbd1697 100644 --- a/FallingPlayerStart.js +++ b/FallingPlayerStart.js @@ -1,156 +1,156 @@ -#pragma strict - - public var force:float = 1.0; - var dir : Vector3 = Vector3.zero; - public var touchingSomething:boolean = false; - -private var isLoading = false; -var levelToLoad : String = "scene-helix"; -var levelToLoad2 : String = "scene-bluesky"; -var levelToLoad3 : String = "falling-column-space"; -var levelToLoad4 : String = "scene-bluesky"; - -// Move object using accelerometer -var speed = 5.0; -var target : Transform; -var smooth = 2.0; -var tiltAngle = 30.0; - -var script : ScoreController; -script = GetComponent("ScoreController"); - -static var isAlive : boolean; - -function DeathRespawn () { - var respawnPosition = Respawn.currentRespawn.transform.position; - Camera.main.SendMessage("fadeOut"); - isAlive = true; - gameObject.SendMessage ("ResetScore", 0); - yield WaitForSeconds(1); -// gameObject.SendMessage ("DecrementScore"); -// gameObject.SendMessage ("ZeroScore", 1); - -// Camera.main.transform.position = respawnPosition - (transform.forward * 4) + Vector3.up; // reset camera too - GetComponent.().attachedRigidbody.transform.Translate(respawnPosition); - // Relocate the player. We need to do this or the camera will keep trying to focus on the (invisible) player where he's standing on top of the FalloutDeath box collider. - transform.position = respawnPosition; // + Vector3.up; - Camera.main.SendMessage("fadeIn"); - } +// #pragma strict + +// public var force:float = 1.0; +// var dir : Vector3 = Vector3.zero; +// public var touchingSomething:boolean = false; + +// private var isLoading = false; +// var levelToLoad : String = "scene-helix"; +// var levelToLoad2 : String = "scene-bluesky"; +// var levelToLoad3 : String = "falling-column-space"; +// var levelToLoad4 : String = "scene-bluesky"; + +// // Move object using accelerometer +// var speed = 5.0; +// var target : Transform; +// var smooth = 2.0; +// var tiltAngle = 30.0; + +// var script : ScoreController; +// script = GetComponent("ScoreController"); + +// static var isAlive : boolean; + +// function DeathRespawn () { +// var respawnPosition = Respawn.currentRespawn.transform.position; +// Camera.main.SendMessage("fadeOut"); +// isAlive = true; +// gameObject.SendMessage ("ResetScore", 0); +// yield WaitForSeconds(1); +// // gameObject.SendMessage ("DecrementScore"); +// // gameObject.SendMessage ("ZeroScore", 1); + +// // Camera.main.transform.position = respawnPosition - (transform.forward * 4) + Vector3.up; // reset camera too +// GetComponent.().attachedRigidbody.transform.Translate(respawnPosition); +// // Relocate the player. We need to do this or the camera will keep trying to focus on the (invisible) player where he's standing on top of the FalloutDeath box collider. +// transform.position = respawnPosition; // + Vector3.up; +// Camera.main.SendMessage("fadeIn"); +// } -function Awake () { - // Make the game run as fast as possible in the web player -// Application.targetFrameRate = 60; - Time.timeScale = 1.0; -} +// function Awake () { +// // Make the game run as fast as possible in the web player +// // Application.targetFrameRate = 60; +// Time.timeScale = 1.0; +// } -function Update () { - var dir : Vector3 = Vector3.zero; - - var tiltAroundZ = -Input.acceleration.y * tiltAngle; - var tiltAroundX = -Input.acceleration.x * tiltAngle; - var target = Quaternion.Euler (tiltAroundX, 0, tiltAroundZ); - - // Dampen towards the target rotation - transform.rotation = Quaternion.Slerp(transform.rotation, target, - Time.deltaTime * smooth);; - // Debug.Log(isAlive); -// Debug.Log(script.currentScore); - } +// function Update () { +// var dir : Vector3 = Vector3.zero; + +// var tiltAroundZ = -Input.acceleration.y * tiltAngle; +// var tiltAroundX = -Input.acceleration.x * tiltAngle; +// var target = Quaternion.Euler (tiltAroundX, 0, tiltAroundZ); + +// // Dampen towards the target rotation +// transform.rotation = Quaternion.Slerp(transform.rotation, target, +// Time.deltaTime * smooth);; +// // Debug.Log(isAlive); +// // Debug.Log(script.currentScore); +// } -// private var speed : Vector3 = Vector3 (3, 0, 0); -// var startingPosition = (0, 129, 0); -var deadlyObjectName : String = "DeathByFire"; -var initialRespawn : Respawn; // set this to the initial respawn point for the level. -// var damping:float = 0.7; // is this necessary? +// // private var speed : Vector3 = Vector3 (3, 0, 0); +// // var startingPosition = (0, 129, 0); +// var deadlyObjectName : String = "DeathByFire"; +// var initialRespawn : Respawn; // set this to the initial respawn point for the level. +// // var damping:float = 0.7; // is this necessary? -// textfield to hold the score and score variable -private var textfield:GUIText; -private var score:int; +// // textfield to hold the score and score variable +// private var textfield:GUIText; +// private var score:int; -public var simulateAccelerometer:boolean = false; +// public var simulateAccelerometer:boolean = false; -function OnCollisionEnter (collision : Collision) { -// Debug.Log("Hit something!" + collision.contacts[0].normal + dir.x + dir.z + Input.acceleration.x); - Screen.sleepTimeout = 0.0f; -// collider.attachedRigidbody.velocity.y *= damping; +// function OnCollisionEnter (collision : Collision) { +// // Debug.Log("Hit something!" + collision.contacts[0].normal + dir.x + dir.z + Input.acceleration.x); +// Screen.sleepTimeout = 0.0f; +// // collider.attachedRigidbody.velocity.y *= damping; -// collider.attachedRigidbody.AddForce(dir * force); +// // collider.attachedRigidbody.AddForce(dir * force); -// iPhoneUtils.Vibrate (); -// var relativeStartingPosition = transform.InverseTransformPoint(0, -500, 0); +// // iPhoneUtils.Vibrate (); +// // var relativeStartingPosition = transform.InverseTransformPoint(0, -500, 0); -// if (collision.gameObject.name == deadlyObjectName){ - if (collision.gameObject.CompareTag ("Death")) { - DeathRespawn (); - } +// // if (collision.gameObject.name == deadlyObjectName){ +// if (collision.gameObject.CompareTag ("Death")) { +// DeathRespawn (); +// } -// if (collision.gameObject.layer == 8){ -// collider.attachedRigidbody.transform.Translate(relativeStartingPosition); +// // if (collision.gameObject.layer == 8){ +// // collider.attachedRigidbody.transform.Translate(relativeStartingPosition); -// Destroy the projectile -// Destroy (gameObject); -//if (relativeStartingPosition.y > 100) -// Debug.Log("You've moved up more than 100 units"); +// // Destroy the projectile +// // Destroy (gameObject); +// //if (relativeStartingPosition.y > 100) +// // Debug.Log("You've moved up more than 100 units"); -} +// } -// function FixedUpdate () { -// rigidbody.MovePosition(rigidbody.position + speed * Time.deltaTime);} +// // function FixedUpdate () { +// // rigidbody.MovePosition(rigidbody.position + speed * Time.deltaTime);} -function OnTriggerEnter (other : Collider) { - if (other.gameObject.CompareTag ("Score")){ - // Debug.Log("You scored!"); - gameObject.SendMessage ("IncrementScore", 10); -// if (audio) -// { -// audio.Play(); -// } - } +// function OnTriggerEnter (other : Collider) { +// if (other.gameObject.CompareTag ("Score")){ +// // Debug.Log("You scored!"); +// gameObject.SendMessage ("IncrementScore", 10); +// // if (audio) +// // { +// // audio.Play(); +// // } +// } - if (other.gameObject.CompareTag ("CloudLevelSelect")){ - isLoading = true; - Camera.main.SendMessage("fadeOut"); - yield WaitForSeconds(1); +// if (other.gameObject.CompareTag ("CloudLevelSelect")){ +// isLoading = true; +// Camera.main.SendMessage("fadeOut"); +// yield WaitForSeconds(1); - Application.LoadLevel(levelToLoad); - } +// Application.LoadLevel(levelToLoad); +// } - if (other.gameObject.CompareTag ("SunsetLevelSelect")){ - isLoading = true; - Camera.main.SendMessage("fadeOut"); - yield WaitForSeconds(1); +// if (other.gameObject.CompareTag ("SunsetLevelSelect")){ +// isLoading = true; +// Camera.main.SendMessage("fadeOut"); +// yield WaitForSeconds(1); - Application.LoadLevel(levelToLoad2); - } +// Application.LoadLevel(levelToLoad2); +// } - if (other.gameObject.CompareTag ("SpaceLevelSelect")){ - isLoading = true; - Camera.main.SendMessage("fadeOut"); - yield WaitForSeconds(1); +// if (other.gameObject.CompareTag ("SpaceLevelSelect")){ +// isLoading = true; +// Camera.main.SendMessage("fadeOut"); +// yield WaitForSeconds(1); - Application.LoadLevel(levelToLoad3); - } +// Application.LoadLevel(levelToLoad3); +// } - if (other.gameObject.CompareTag ("SkyLevelSelect")){ - isLoading = true; - Camera.main.SendMessage("fadeOut"); - yield WaitForSeconds(1); +// if (other.gameObject.CompareTag ("SkyLevelSelect")){ +// isLoading = true; +// Camera.main.SendMessage("fadeOut"); +// yield WaitForSeconds(1); - Application.LoadLevel(levelToLoad4); - } +// Application.LoadLevel(levelToLoad4); +// } -} +// } -function OnGUI() { -if (isLoading) { -GUI.Label ( Rect( (Screen.width/2)-110, (Screen.height / 2) - 60, 400, 70), "Loading...", "mainMenuTitle"); } -} +// function OnGUI() { +// if (isLoading) { +// GUI.Label ( Rect( (Screen.width/2)-110, (Screen.height / 2) - 60, 400, 70), "Loading...", "mainMenuTitle"); } +// } -@script AddComponentMenu("Scripts/FallingPlayerStart") \ No newline at end of file +// @script AddComponentMenu("Scripts/FallingPlayerStart") \ No newline at end of file diff --git a/FallingStartMenu.js b/FallingStartMenu.js index 166e521..8f2b58c 100644 --- a/FallingStartMenu.js +++ b/FallingStartMenu.js @@ -45,8 +45,7 @@ private var mainCamera: Camera; var script : ScoreController; script = GetComponent("ScoreController"); -static var isAlive : int = 0; -isAlive = lifeCountdown.isAlive; +var isAlive : int = 1; static var isPausable : boolean = true; @@ -71,7 +70,6 @@ function Start() { isAlive = 1; UIscriptComponent = UIscriptName.GetComponent(fallingStartMenuUI); AudioListener.pause = false; -// fadeInAudio (); FadeAudio (0.1, FadeDir.In); isPausable = true; @@ -107,8 +105,7 @@ function DeathRespawn () { changeLevelBackdrop (); } -// fadeOutAudio (); - FadeAudio ((fadeTime/2), FadeDir.Out); + FadeAudio (fadeTime/2, FadeDir.Out); gameObject.SendMessage ("ResetScore", 0); yield WaitForSeconds(1); @@ -127,8 +124,6 @@ function DeathRespawn () { function changeLevelBackdrop () { changeBackdrop.oceanCamera.GetComponent(Camera).enabled = false; changeBackdrop.oceanRenderer.enabled = false; - changeBackdrop.cloudRenderer.enabled = false; - changeBackdrop.endSphereRenderer.enabled = false; // the Fade argument below this breaks unpredictably if player gameobject lacks a Fade script component // Fade.use.Colors(guiTexture, (RenderSettings.fogColor * 2), startingFogColor, 2.0); diff --git a/GUITextureLaunch.js b/GUITextureLaunch.js index aa60b83..666f730 100644 --- a/GUITextureLaunch.js +++ b/GUITextureLaunch.js @@ -10,7 +10,7 @@ function Start () { GetComponent.().color.a = 0.0; } -function FadeFlash (timer : float, fadeType : FadeDir) { +function FadeFlash(timer : float, fadeType : FadeDir) { var start = fadeType == FadeDir.In? 0.0 : peakValue; var end = fadeType == FadeDir.In? peakValue : 0.0; @@ -30,20 +30,20 @@ function LinesFlash (timer : float, fadeType : FadeDir) { var end = fadeType == FadeDir.In? peakValue : 0.0; var i = 0.0; var step = 1.0/timer; - + // if (controllerITween2.speedingUp == 2) { // if ((controllerITween2.speedingUp == 2) && (controllerITween2.Slowdown < 1)) { - while (i <= 1.0) { + while (i <= 1.0) { i += step * Time.deltaTime; GetComponent.().color.a = Mathf.Lerp(start, end, i); yield; - + if (MoveController.Slowdown < 1) {break;} } yield WaitForSeconds (timer); - MoveController.speedingUp = 1; + MoveController.speedingUp = 1; // } - + } function LinesFlashOut (timer : float, fadeType : FadeDir) { @@ -52,8 +52,8 @@ function LinesFlashOut (timer : float, fadeType : FadeDir) { var end = fadeType == FadeDir.In? GetComponent.().color.a : 0.0; var i = 0.0; var step = 1.0/timer; - - if (MoveController.speedingUp == 0) { + + if (MoveController.speedingUp == 0) { while (i <= 1.0) { i += step * Time.deltaTime; GetComponent.().color.a = Mathf.Lerp(end, start, i); @@ -62,7 +62,7 @@ function LinesFlashOut (timer : float, fadeType : FadeDir) { if (MoveController.Slowdown > 1) {break;} } yield WaitForSeconds (timer/3); - MoveController.speedingUp = 1; + MoveController.speedingUp = 1; } } @@ -76,13 +76,13 @@ function FadeOut (timer : float) { var end = 0.0; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; GetComponent.().color.a = Mathf.Lerp(start, end, i); yield; } - + yield WaitForSeconds (timer); - + } diff --git a/IntroEndTrigger.js b/IntroEndTrigger.js index ecb5533..3db6b2c 100644 --- a/IntroEndTrigger.js +++ b/IntroEndTrigger.js @@ -15,8 +15,8 @@ function Start () { function OnTriggerEnter (other : Collider) { if (other.gameObject.CompareTag ("Player") && activeIntro == false){ activeIntro = true; - FallingPlayer.ScoreFlashTextureScript.FadeFlash (3, FadeDir.Out); + FallingPlayer.ScoreFlashTextureScript.FadeFlash(3, FadeDir.Out); IntroScriptComponent.EndIntro(true); if (audioSource) {audioSource.Play();} } -} \ No newline at end of file +} diff --git a/IntroSequence.js b/IntroSequence.js index bbfa97b..2746785 100644 --- a/IntroSequence.js +++ b/IntroSequence.js @@ -5,8 +5,9 @@ var introCamera : GameObject; var mainCamera : GameObject; function Start () { - FallingPlayer.UIscriptComponent.HideGUI(); - + if (!FallingLaunch.isVRMode) { + FallingPlayer.UIscriptComponent.HideGUI(); + } } function EndIntro () { diff --git a/IntroSequence1stPerson.js b/IntroSequence1stPerson.js index f15e96d..c2a679c 100644 --- a/IntroSequence1stPerson.js +++ b/IntroSequence1stPerson.js @@ -15,38 +15,47 @@ function Start () { if (!FallingLaunch.NewGamePlus) { PlayerController.enabled = false; ScoreController.enabled = false; - FallingPlayer.UIscriptComponent.HideGUI(); - - for(var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) { - destructible = shard.GetComponent(ProjectileDestroy); - var shardRenderer : Renderer = shard.GetComponent.(); - shardRenderer.enabled = false; - shard.GetComponent.().isKinematic = true; - destructible.enabled = false; - shardColor = shardRenderer.material.color; - } - } - else if (FallingLaunch.NewGamePlus) { + + if (!FallingLaunch.isVRMode) { + FallingPlayer.UIscriptComponent.HideGUI(); + } + + } else if (FallingLaunch.NewGamePlus) { PlayerController.enabled = true; ScoreController.enabled = true; LifeController.enabled = true; - //FallingPlayer.UIscriptComponent.HideGUI(); - FallingPlayer.UIscriptComponent.UnhideGUI(); + + if (!FallingLaunch.isVRMode) { + FallingPlayer.UIscriptComponent.UnhideGUI(); + } } - + // Disable all shards' self-destruction scripts so they don't vanish + // before the player triggers their fall: + for (var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) { + destructible = shard.GetComponent(ProjectileDestroy); + var shardRenderer : Renderer = shard.GetComponent.(); + shardRenderer.enabled = false; + shard.GetComponent.().isKinematic = true; + destructible.enabled = false; + shardColor = shardRenderer.material.color; + } } function EndIntro (playAudio : boolean) { PlayerController.enabled = true; ScoreController.enabled = true; LifeController.enabled = true; - + if (!FallingLaunch.NewGamePlus) { FallingPlayer.UIscriptComponent.UnhideGUI(); } - - for(var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) { + + if (FallingLaunch.isVRMode) { + FallingPlayer.reticleVRUIScript.FadeReticleIn(1.5); + } + + for (var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) { destructible = shard.GetComponent(ProjectileDestroy); shard.GetComponent.().isKinematic = false; //yield WaitForSeconds(.25); @@ -56,20 +65,20 @@ function EndIntro (playAudio : boolean) { shard.GetComponent.().enabled = true; destructible.enabled = true; } - + var start = shardColor; var end = Color.black; var i = 0.0; var step = 1.0/5; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; for(var shard : GameObject in GameObject.FindGameObjectsWithTag("Shard")) shard.GetComponent.().material.color = Color.Lerp(start, end, i); yield; - } + } } function DeathHelp() { DeathGUITrigger.ShowHelpAfterDeath(); -} \ No newline at end of file +} diff --git a/IntroUITrigger.js b/IntroUITrigger.js index dbb7fe7..5751f5a 100644 --- a/IntroUITrigger.js +++ b/IntroUITrigger.js @@ -7,13 +7,14 @@ var fallingUI : GameObject; static var fallingUIComponent : fallingUITest; enum Triggers { -trigger1, -trigger2, -trigger3 + trigger1, + trigger2, + trigger3 }; var helpIcon: UISprite; var thisIcon : String; +var iconNameVR : String; var thisTimer : float = 8; var thisTrigger : Triggers; var tutorialSprite : UISprite; @@ -61,7 +62,7 @@ function Start () { helpIcon.pixelsFromBottom(textHeight); helpIcon.hidden = true; - + audioSource = GetComponent.(); } @@ -69,8 +70,12 @@ function Start () { function OnTriggerEnter (other : Collider) { if (other.gameObject.CompareTag ("Player") && activeIntro == false && FallingLaunch.NewGamePlus == false) { activeIntro = true; - fallingIntroUIComponent.ShowIcon(helpIcon, thisTimer, tutorialSprite); - tutorialSpritePosition(thisTimer); + if (FallingLaunch.isVRMode) { + fallingIntroUIComponent.ShowIconVR(iconNameVR, thisTimer); + } else { + fallingIntroUIComponent.ShowIcon(helpIcon, thisTimer, tutorialSprite); + tutorialSpritePosition(thisTimer); + } if (audioSource) {audioSource.Play();} } } @@ -93,6 +98,8 @@ function tutorialSpritePosition(timer : float) { } function ShowHelpAfterDeath() { + if (!FallingLaunch.isVRMode) { fallingIntroUIComponent.ShowIcon(helpIcon, 2, tutorialSprite); tutorialSpritePosition(2); + } } \ No newline at end of file diff --git a/MoveController.js b/MoveController.js index 25bdcc4..17845a4 100644 --- a/MoveController.js +++ b/MoveController.js @@ -1,29 +1,40 @@ #pragma strict -public var force:float = 1.0; -public var simulateAccelerometer:boolean = false; -public var touchedBy:boolean = false; -var dir : Vector3 = Vector3.zero; -var endPoint = 0.0; var touch : Touch; var fingerCount = 0; private var myTransform : Transform; private var startTime : float; -static var Slowdown : int = 0; +static var Slowdown : float = 0.0; static var maxSlowdown : float = 18000.0; -var speed : float = 2.4; -static var isSlowing : boolean = false; +private var maxSlowdownThreshold : float = maxSlowdown - 1; + +private var lateralSpeedBoost : float = 0.0; +private var maxLateralSpeed : float = 0.5; + +var forceComponent : ConstantForce; + +private var extraForceRaw = Vector3.zero; +var extraForce = Vector3.zero; +private var clampedModifierVR : float; + +private var dir = Vector3.zero; +private var speed : float = 2.4; + static var speedingUp : int = 1; -static var controlMultiplier : float = 1; +static var controlMultiplier : float = 1.0; +private var controlModifierTotal : float; -var mainCamera : GameObject; -var script : ScoreController; +private var mainCamera : Camera; +var mainCameraObj : GameObject; +var playerCamerasTransform : Transform; -var SpeedLinesTexture : GameObject; -var SpeedLinesTextureScript : GUITextureLaunch; +private var myHead : GvrHead; +var GvrViewerMainObject : GameObject; // In each scene, manually add the GvrViewerMain obj via Inspector + +var script : ScoreController; var SpeedLinesMesh : GameObject; static var SpeedLinesMeshScript : SpeedLines; @@ -31,322 +42,380 @@ static var SpeedLinesMeshScript : SpeedLines; var audioSource : AudioSource; var changingPitch : boolean = false; + +// this is on for all levels but lvl1/tutorial, which has music baked +// into the background wind sound, and thus shouldn't get pitch-shifted: var shouldChangePitch : boolean = true; +var maxDuckedVolume : float = 1.0; + static var pauseButtonArea : Rect; function Awake() { - myTransform = transform; - script = GetComponent("ScoreController"); - SpeedLinesTextureScript = SpeedLinesTexture.GetComponent("GUITextureLaunch"); - SpeedLinesMeshScript = SpeedLinesMesh.GetComponent("SpeedLines"); + myTransform = transform; + script = GetComponent("ScoreController"); + SpeedLinesMeshScript = SpeedLinesMesh.GetComponent("SpeedLines"); + forceComponent = GetComponent.(); } function Start() { + // Screen.sleepTimeout = 0.0f; + // deprecated, now should use NeverSleep + Screen.sleepTimeout = SleepTimeout.NeverSleep; + startTime = Time.time; + Slowdown = FallingLaunch.levelEndSlowdown; + + if (mainCameraObj) { + mainCamera = mainCameraObj.GetComponent.(); + } else { // if it wasn't set already via the Inspector UI... + // mainCameraObj = GameObject.FindWithTag("MainCamera"); + mainCamera = Camera.main; + mainCameraObj = Camera.main.gameObject; + } + + playerCamerasTransform = mainCameraObj.transform.parent; + audioSource = mainCamera.GetComponent.(); + + //Calibrate(); + + lerpSlowdown(.5); + + // resetting controlMultiplier in case it was zeroed from the previous level + // (since as a global/static var, it's cached across level loads); + // Also, since it was probably lerped down to zero at previous levelEnd, initialize it here, except in the case where . + if (FallingLaunch.shouldShowVRIntroUI && FallingLaunch.isVRMode) { + MoveController.controlMultiplier = 0.0; + } else { + MoveController.controlMultiplier = 1.0; + } + + if (!FallingLaunch.isVRMode) { + lerpControlIn(3.0); + } + + //pauseButtonArea = Rect(0, 0, Screen.width / 2, Screen.height / 2); + pauseButtonArea = Rect(Screen.width * .9, Screen.height * .8, Screen.width * .1, Screen.height * .2); -// Screen.sleepTimeout = 0.0f; -// deprecated, now should use NeverSleep - Screen.sleepTimeout = SleepTimeout.NeverSleep; - startTime = Time.time; - Slowdown = FallingLaunch.levelEndSlowdown; - - mainCamera = transform.FindChild("Camera").gameObject; - audioSource = mainCamera.GetComponent.(); - - //Calibrate(); - - lerpSlowdown(.5); - lerpControl(3); - //pauseButtonArea = Rect(0, 0, Screen.width / 2, Screen.height / 2); - pauseButtonArea = Rect(Screen.width * .9, Screen.height * .8, Screen.width * .1, Screen.height * .2); } function FixedUpdate () { - var dir : Vector3 = Vector3.zero; - -// if (simulateAccelerometer) -// { - // using joystick input instead of iPhone accelerometer -// dir.x = Input.GetAxis("Horizontal"); -// dir.z = Input.GetAxis("Vertical"); -// } -// else - - // we assume that device is held parallel to the ground - // and Home button is in the right hand - - // remap device acceleration axis to game coordinates - // 1) XY plane of the device is mapped onto XZ plane - // 2) rotated 90 degrees around Y axis - // dir.x = -Input.acceleration.y; -// dir.z = Input.acceleration.x; - -// print("Your X and Z accel are: " + dir.x + ", " + dir.z); - - // clamp acceleration vector to unit sphere -// if (dir.sqrMagnitude > 1) -// dir.Normalize(); - -if (FallingPlayer.isAlive == 1 && FallingLaunch.tiltable == true) { - - // Make it move 10 meters per second instead of 10 meters per frame... - // .:. not necessary in fixedupdate - // dir *= Time.deltaTime; - // print("Your dir is: " + dir); + dir = Vector3.zero; + + // Address any x/z movement due to device tilts or VR head gaze positon: + if (FallingPlayer.isAlive == 1 && FallingLaunch.tiltable == true) { + // In VR mode, use Cardboard gaze direction (e.g. as applied to head object) + // to determine any movement that's not downwards/gravity-driven: + if (FallingLaunch.isVRMode && GvrViewerMainObject) { + if (myHead) { MovePlayerVR(); } + } else { + // if not in VR mode, call movePlayer and honor the playerPrefs axis settings: + MovePlayer(FallingLaunch.invertHorizAxisVal, FallingLaunch.invertVertAxisVal); + } + } else { + dir = Vector3.zero; + } + + // Address any speedups due to screen presses in FixedUpdate, not here! + // FallingSpeed(); +} + +function MovePlayerVR () { + // Using TransformDirection so it's in world space, not local. + controlModifierTotal = FallingPlayer.isAlive * controlMultiplier * FallingLaunch.flipMultiplier; + dir.x = 3 * transform.TransformDirection(myHead.Gaze.direction).x * controlModifierTotal; + dir.z = 3 * transform.TransformDirection(myHead.Gaze.direction).z * controlModifierTotal; + + // Debug.Log('head direction: ' + myHead.Gaze.direction); + // Debug.Log('dir x pre-clamping ' + dir.x); + // Debug.Log('dir z pre-clamping ' + dir.z); + + // Only using X and Z: no y-traversal in world axis, + // since scene gravity handles the Y dimension. + dir.x = Mathf.Clamp(dir.x, -2.0, 2.0); + dir.z = Mathf.Clamp(dir.z, -2.0, 2.0); + + // Debug.Log('dir x final ' + dir.x); + // Debug.Log('dir z final ' + dir.z); + + var speedRatio : float = Slowdown / maxSlowdown; + + // Cap the lateral speed (it should be translation, not a force, + // so you don't keep moving after you lift the trigger). + // Distinguish between two categories of movement: + // while in boost mode and just afterwards (speedRatio > .25; value range is 1.25-2.4), + // vs. regular (speedRatio < .25) movement. + // The latter is more constrained (possible value range 1-1.5). + lateralSpeedBoost = speedRatio > .25 ? + Mathf.Max(1.25, speedRatio * speed) : 1.0 + (speedRatio * maxLateralSpeed); + + // Debug.Log('lateralSpeedBoost: ' + lateralSpeedBoost); + // Debug.Log('controlMultiplier: ' + controlMultiplier); - //myTransform.Translate (dir * speed, Space.World); + // Dir is clamped to +/-2 units/frame (and avoiding direct use of the speed multiplier) + // to obtain more 'realistic' 1:1 movement, with just a little amplification, + // and with lateralSpeedBoost as the extra if you're touching the screen. + // myTransform.Translate (dir * (1.0 + lateralSpeedBoost), Space.World); + // myTransform.Translate (dir * lateralSpeedBoost, Space.World); + myTransform.Translate (dir * lateralSpeedBoost * controlMultiplier, Space.World); +} + +function MovePlayer(horizAxisInversionVal: int, vertAxisInversionVal: int) { FallingLaunch.hasSetAccel = true; FallingLaunch.accelerator = FallingLaunch.calibrationRotation * Input.acceleration; - //Debug.Log(FallingLaunch.accelerator); - dir.x = 4 * FallingPlayer.isAlive * controlMultiplier * FallingLaunch.flipMultiplier * -((FallingLaunch.accelerator.y) * Mathf.Abs(FallingLaunch.accelerator.y)); - dir.z = 3 * FallingPlayer.isAlive * controlMultiplier * FallingLaunch.flipMultiplier * ((FallingLaunch.accelerator.x) * Mathf.Abs(FallingLaunch.accelerator.x)); - - dir.x = FallingLaunch.invertHorizAxisVal * Mathf.Clamp(dir.x, -2.0, 2.0); - dir.z = FallingLaunch.invertVertAxisVal * Mathf.Clamp(dir.z, -2.0, 2.0); - - myTransform.Translate (dir * speed, Space.World); -} -else {dir = Vector3.zero;} + // Debug.Log("MoveController FallingLaunch.calibrationRotation: " + FallingLaunch.calibrationRotation); + // Debug.Log("Input.acceleration: " + Input.acceleration); + // Debug.Log( "MoveController FallingLaunch.flipMultiplier: " + FallingLaunch.flipMultiplier ); -} + // Debug.Log("MoveController FallingLaunch.accelerator: " + FallingLaunch.accelerator); -function SmoothSlowdown () { + dir.x = 4 * FallingPlayer.isAlive * controlMultiplier * FallingLaunch.flipMultiplier * -((FallingLaunch.accelerator.y) * Mathf.Abs(FallingLaunch.accelerator.y)); + dir.z = 3 * FallingPlayer.isAlive * controlMultiplier * FallingLaunch.flipMultiplier * ((FallingLaunch.accelerator.x) * Mathf.Abs(FallingLaunch.accelerator.x)); - isSlowing = true; - iTween.ValueTo ( gameObject, - { - "from" : maxSlowdown, - "to" : 0, - "onupdate" : "ChangeSpeed", - "time" : 1, - "easetype": "easeOutExpo", - "oncomplete": "ResumeSpeed" - } - ); + dir.x = horizAxisInversionVal * Mathf.Clamp(dir.x, -2.0, 2.0); + dir.z = vertAxisInversionVal * Mathf.Clamp(dir.z, -2.0, 2.0); + // Debug.Log("dir.x final: " + dir.x); + // Debug.Log("dir.z final: " + dir.z); + myTransform.Translate (dir * speed, Space.World); } function ChangeSpeed ( i : int ) { -Slowdown = i; -// Debug.Log("Your current speed score is " + ScoreController.visibleScore); -} - -function ResumeSpeed () { -isSlowing = false; + Slowdown = i; + // Debug.Log("Your current speed score is " + ScoreController.visibleScore); } function Update () { - fallingSpeed(); -// Debug.Log("Slowdown = " + Slowdown); + // TODO: make coroutine instead? http://answers.unity3d.com/answers/1281517/view.html + // Find head for VR (can't live in Start because the GVR plugin takes > 1 frame to set up): + if (FallingLaunch.isVRMode && GvrViewerMainObject && !myHead) { + if (mainCameraObj.GetComponent.()) { + myHead = mainCameraObj.GetComponent.().Head; + } + } + + FallingSpeed(); + // Debug.Log("Slowdown = " + Slowdown); } +// Old perf note (moved fallingSpeed to fixedUpdate on 1/7/2017): // I also tried moving fallingSpeed function to fixedUpdate, but it actually made the game slower, // since iOS is usually 30fps and fixedUpdate needs to run at 50fps (0.02 fixed timestep) for // decent collision detection. -function fallingSpeed () { - - fingerCount = 0; - - if (FallingPlayer.isAlive == 1 && FallingPlayer.isPausable == true) { - //for (touch in Input.touches) { - // if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled) { - for (var i = 0; i < Input.touchCount; ++i) { - if (Input.GetTouch(i).phase != TouchPhase.Ended && Input.GetTouch(i).phase != TouchPhase.Canceled) { - fingerCount++; - - if (pauseButtonArea.Contains(Input.GetTouch(i).position)) { - // Debug.Log("Returning!"); - return; - } - - // if (pauseButtonArea.Contains(touch.position)) { - // Debug.Log("Touching pause area!"); - // } - // else { - // Debug.Log("Not in pause area."); - // } - } - } - - - if (fingerCount > 0) { - //speedUp(); - if (Slowdown < 1) {speedingUp = 2; Slowdown = maxSlowdown; speedsUp(); - //GA.API.Design.NewEvent("Control:SpeedBoost:Start:" + Application.loadedLevelName + ":" + FallingLaunch.thisLevelArea, FallingLaunch.secondsAlive, transform.position); - } - //if (Slowdown < 1) - //{speedingUp = 2; speedsUp(); Slowdown = maxSlowdown; } - - } - else if (fingerCount < 1) { - // slowDown(); - //if (Slowdown > 0) {speedDown(); yield;} - //Slowdown = 0; - if (Slowdown > 0) { speedingUp = 0; speedsUp(); lerpSlowdown(.5); } - //else if (Slowdown > 0) {speedingUp = 0; speedsUp(); } - } - } - - else { - Slowdown = 0; - speedingUp = 1; - //SpeedLinesTextureScript.LinesOff(); - SpeedLinesMeshScript.LinesOff(); - //mainCamera.audio.pitch = 1; - //mainCamera.audio.volume = 1; - if (shouldChangePitch == true && changingPitch == false) {lerpPitchDown(.5, 1, 1);} - dir = Vector3.zero; - FallingPlayer.UIscriptComponent.hideThreatBar(0.1); - } - -// Debug.Log("Slowdown = " + Slowdown + ", speedingUp = " + speedingUp ); -// Debug.Log("You have " + fingerCount + " fingers touching the screen." ); - - GetComponent.().relativeForce = (Vector3.down * Slowdown); -} +function FallingSpeed () { + // Debug.Log("FallingPlayer.isAlive: " + FallingPlayer.isAlive); + // Debug.Log('controlMultiplier: ' + controlMultiplier); + // Debug.Log("FallingPlayer.isPausable: " + FallingPlayer.isPausable); + fingerCount = 0; + + if (FallingPlayer.isAlive == 1 && FallingPlayer.isPausable == true) { + //for (touch in Input.touches) { + // if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled) { + for (var i = 0; i < Input.touchCount; ++i) { + if (Input.GetTouch(i).phase != TouchPhase.Ended && Input.GetTouch(i).phase != TouchPhase.Canceled) { + fingerCount++; + + if (pauseButtonArea.Contains(Input.GetTouch(i).position)) { + // Debug.Log("Returning!"); + return; + } + + // if (pauseButtonArea.Contains(touch.position)) { + // Debug.Log("Touching pause area!"); + // } + // else { + // Debug.Log("Not in pause area."); + // } + } + } + + + if (fingerCount > 0) { + if (Slowdown < 1) { + Slowdown = maxSlowdown; + speedingUp = 2; + speedsUp(); + // FallingLaunch.Analytics.Event( + // "Control:SpeedBoost:Start:" + Application.loadedLevelName + ":" + FallingLaunch.thisLevelArea, + // FallingLaunch.secondsAlive + // ); + } + } else if (fingerCount < 1) { + // rounding Slowdown, since as lerp approaches zero, floating-point errors creep in + if (Mathf.Round(Slowdown) > 0) { + speedingUp = 0; speedsUp(); lerpSlowdown(.5); + } else { + audioSource.volume = maxDuckedVolume; + } + } + } + + else { + Slowdown = 0; + speedingUp = 1; + SpeedLinesMeshScript.LinesOff(); + if (shouldChangePitch && !changingPitch) {lerpPitchDown(.5, 1, 1);} + dir = Vector3.zero; + if (!FallingLaunch.isVRMode && FallingPlayer.isPausable) { + FallingPlayer.UIscriptComponent.hideThreatBar(0.1); + } + } + + // Debug.Log("Slowdown = " + Slowdown + ", speedingUp = " + speedingUp ); + // Debug.Log("You have " + fingerCount + " fingers touching the screen." ); + + // In non-VR mode, relativeForce assumes the Player GameObject transform is tilted + // (by the device accelerometer) in space; it relies on device tilt + // to provide some worldspace lateral speedup to the local (relative) down vector. + + // In VR, the head's gaze direction supplies our y vector, which is attenuated + // based on the gaze x/z (clampedModifierVR). + // That vector is multiplied by Slowdown to get a final downwards force. + + // Any x/z movement during a speed boost is handled in MovePlayerVR, since applying + // sideways forces pushes the player too far away from the main level. + if (myHead) { + extraForceRaw = myHead.Gaze.direction; + // Debug.Log('extraForceRaw: ' + extraForceRaw); + // Debug.Log('myHead.Gaze.direction: ' + myHead.Gaze.direction); + + clampedModifierVR = + Mathf.Max(Mathf.Abs(myHead.Gaze.direction.x), Mathf.Abs(myHead.Gaze.direction.z)); + extraForce = Vector3.ClampMagnitude(extraForceRaw, (1.0 - clampedModifierVR)); + // Debug.Log('clampedModifierVR: ' + clampedModifierVR); + + // If you wanted to directly set the downward vector, + // you could use set extraForce.y to be myHead.Gaze.direction.y below... + // but the attenuated version is easier on the neck to control! + + // Mutate into a downwards vector that insists on negative y values + // (so you can't fly upwards). `controlMultiplier` is used so you + // can't reach max speed (Slowdown) while still lerping control in: + extraForce = Vector3(0, Mathf.Min(extraForce.y, 0.0) * Slowdown * controlMultiplier, 0); + } + else { + // Debug.Log("playerCamerasTransform.up " + playerCamerasTransform.up); + // Debug.Log("negative playerCamerasTransform.up " + -playerCamerasTransform.up); + // negative because we want to go "down" and not actually "up"; + // this corresponds (more or less) to the non-VR camera tilt at this moment. + extraForce = -playerCamerasTransform.up * Slowdown; + + // Old way (when we could assume this script's transform was already tilted): + // extraForce = Vector3.down * Slowdown; + } -function speedsUp () { - if (speedingUp == 2) { - speedingUp = 1; - //SpeedLinesTextureScript.LinesFlash (0.25, FadeDir.In); - SpeedLinesMeshScript.LinesFlash (0.25, FadeDir.In); - FallingPlayer.UIscriptComponent.showThreatBar(1); - if (audioSource && shouldChangePitch == true) {lerpPitchUp(.5, 2, .3);} - } - else { - //SpeedLinesTextureScript.LinesFlashOut (0.75, FadeDir.In); - SpeedLinesMeshScript.LinesFlashOut (0.5, FadeDir.In); - FallingPlayer.UIscriptComponent.hideThreatBar(.5); - if (audioSource && shouldChangePitch == true && changingPitch == false) {lerpPitchDown(1, 1, 1);} -} + // Debug.Log('extraForce: ' + extraForce); + forceComponent.relativeForce = extraForce; } -function speedUp () { - Slowdown = maxSlowdown; - Camera.main.SendMessage("speedLinesUp"); -// SendMessage is slow; rephrase if I ever use this speedUp method again. - -// UIscriptComponent.speedLinesNow(); - -// if (speedingUp == true) { -// SpeedLinesTextureScript.FadeFlash (0.25, FadeDir.In); -// yield WaitForSeconds(.25);} -// else { -// SpeedLinesTextureScript.FadeFlash (0.5, FadeDir.Out); -// yield WaitForSeconds(.5);} +function speedsUp () { + if (speedingUp == 2) { + speedingUp = 1; + SpeedLinesMeshScript.LinesFlash (0.25, FadeDir.In); + if (!FallingLaunch.isVRMode) { + FallingPlayer.UIscriptComponent.showThreatBar(1); + } + if (audioSource && shouldChangePitch) { + // a bit of randomness to vary the end wind-noise pitch; + // generally, we want a value near 2: + lerpPitchUp(.5, Random.Range(1.85, 2.25), .3); + } + } else { + SpeedLinesMeshScript.LinesFlashOut (0.5, FadeDir.In); + if (!FallingLaunch.isVRMode) { + FallingPlayer.UIscriptComponent.hideThreatBar(.5); + } + if (audioSource && shouldChangePitch && !changingPitch) { + lerpPitchDown(1, 1, 1); + } + } } -function speedDown () { - Slowdown = 0; - //SpeedLinesTextureScript.LinesFlash (1.0, FadeDir.Out); - SpeedLinesMeshScript.LinesFlash (1.0, FadeDir.Out); - yield WaitForSeconds(1.0); +function getMaxDuckedVolume() { + return maxDuckedVolume; } -function slowDown () { - if ((Slowdown > 0) && (isSlowing == false)) { - SmoothSlowdown (); - } - else {Slowdown = 0;} -// the above Slowdown = 0 statement breaks the tweened slowdown, but prevents a nasty bug where newly-loaded levels don't slow properly -// else { Camera.main.SendMessage("speedLinesDown"); } +function setMaxDuckedVolume(maxVol : float) { + maxDuckedVolume = maxVol; } function lerpSlowdown (timer : float) { - var start = Slowdown; var end = 0.0; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; Slowdown = Mathf.Lerp(start, end, i); yield; - - if (Slowdown > 17999) {break;} - } + + if (Slowdown > maxSlowdownThreshold) {break;} + } yield WaitForSeconds (timer); - //speedingUp = 1; - + } function lerpPitchUp (timer : float, endPitch : float, endVolume : float) { - + var startVol = audioSource.volume; var endVol = endVolume; - + var start = audioSource.pitch; var end = endPitch; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; audioSource.pitch = Mathf.Lerp(start, end, i); - audioSource.volume = Mathf.SmoothStep(startVol, endVol, i); + audioSource.volume = Mathf.SmoothStep(startVol, endVol * maxDuckedVolume, i); yield; - + if (Slowdown < 1) {break;} - } + } yield WaitForSeconds (timer); } function lerpPitchDown (timer : float, endPitch : float, endVolume : float) { - + changingPitch = true; var startVol = audioSource.volume; var endVol = endVolume; - + var start = audioSource.pitch; var end = endPitch; var i = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; audioSource.pitch = Mathf.Lerp(start, end, i); - audioSource.volume = Mathf.SmoothStep(startVol, endVol, i); + audioSource.volume = Mathf.SmoothStep(startVol, endVol * maxDuckedVolume, i); yield; - if (Slowdown > 17999) {changingPitch = false; break;} - } - - yield WaitForSeconds (timer); - changingPitch = false; -} + if (Slowdown > maxSlowdownThreshold) {changingPitch = false; break;} + } -function SpeedLinesOff (timer : float) { - SpeedLinesTextureScript.FadeOut (timer); - yield WaitForSeconds(timer); - SpeedLinesTextureScript.LinesOff(); + yield WaitForSeconds (timer); + changingPitch = false; } -function lerpControl(timer : float) { +function lerpControlIn(timer : float) { - var start = 0.0; - var end = controlMultiplier; - var i = 0.0; + var i : float = 0.0; var step = 1.0/timer; - - while (i <= 1.0) { + while (i <= 1.0) { i += step * Time.deltaTime; - controlMultiplier = Mathf.Lerp(start, end, i); + controlMultiplier = Mathf.Lerp(0.0, 1.0, i); yield; - //Debug.Log("My flipmultiplier is " + FallingLaunch.flipMultiplier + " and my end is " + end); - } + // Debug.Log("My controlMultiplier is " + controlMultiplier); + // Debug.Log("My flipmultiplier is " + FallingLaunch.flipMultiplier + " and my end is " + end); + } yield WaitForSeconds (timer); } - -function Calibrate () { - FallingLaunch.tiltable = false; - var acceleratorSnapshot = Input.acceleration; - FallingLaunch.calibrationRotation = Quaternion.FromToRotation(acceleratorSnapshot, FallingLaunch.restPosition); - FallingLaunch.tiltable = true; -} \ No newline at end of file diff --git a/ObjectDistanceFade.js b/ObjectDistanceFade.js index 8a085bf..e63ca7e 100644 --- a/ObjectDistanceFade.js +++ b/ObjectDistanceFade.js @@ -6,7 +6,7 @@ private var myTransform : Transform = null; private var myRendererMatl : Material; private var dist : Vector3; private var sqrLen : float; -private var sqrRtLen : float; +private var lenToObj : float; function Start () { myTransform = transform; @@ -18,16 +18,20 @@ function OnBecameVisible() { } function OnBecameInvisible() { + if (myRendererMatl) {myRendererMatl.color.a = 0.0;} isEnabled = false; } function Update () { - if (isEnabled == true) { - //var dist = Vector3.Distance(myTransform.position, other.position); + if (isEnabled) { dist = myTransform.position - other.position; sqrLen = dist.sqrMagnitude; - sqrRtLen = Mathf.Sqrt(sqrLen); - if (sqrLen < solidDistance*solidDistance) {sqrRtLen = solidDistance;} - myRendererMatl.color.a = solidDistance / sqrRtLen; + lenToObj = Mathf.Sqrt(sqrLen); + + if (sqrLen < solidDistance*solidDistance) { + lenToObj = solidDistance; + } + + myRendererMatl.color.a = solidDistance / lenToObj; } } \ No newline at end of file diff --git a/ProjectileDestroy.js b/ProjectileDestroy.js index 7b4fea2..9f02d95 100644 --- a/ProjectileDestroy.js +++ b/ProjectileDestroy.js @@ -13,10 +13,16 @@ function Start () { // this is so fireballs that hit the player don't interfere with newly-spawned ones in the scene. function OnCollisionEnter (collision : Collision) { if (collision.gameObject.CompareTag ("Player")) { -// throw an analytics event! - // GA.API.Design.NewEvent("Projectile:Collision:" + ProjectileName, FallingLaunch.secondsAlive, transform.position); - gameObject.GetComponent.().isKinematic = true; - Destroy(gameObject, 1); + + // throw an analytics event! + FallingLaunch.Analytics.Event( + "Projectile:Collision:" + FallingLaunch.vrModeAnalyticsString + ProjectileName, + FallingLaunch.secondsAlive + ); + + gameObject.GetComponent.().isKinematic = true; + + Destroy(gameObject, 1); } // but if one fireball hits another, destroy immediately. diff --git a/Respawn.js b/Respawn.js index 80998a1..807f15d 100644 --- a/Respawn.js +++ b/Respawn.js @@ -46,13 +46,13 @@ var mainRespawnScript : boolean = false; private var audioSource: AudioSource; function Start() -{ +{ // Get some of the objects we need later. - // This is often done in a script's Start function. That way, we've got all our initialization code in one place, + // This is often done in a script's Start function. That way, we've got all our initialization code in one place, // And can simply count on the code being fine. RespawnState = 0; - + // set up the looping "RespawnActive" sound, but leave it switched off for now: if (SFXRespawnActiveLoop) { @@ -61,17 +61,17 @@ function Start() audioSource.loop = true; audioSource.playOnAwake = false; } - + // Assign the respawn point to be this one - Since the player is positioned on top of a respawn point, it will come in and overwrite it. // This is just to make sure that we always have a respawn point. - //mainRespawnScript boolean is to keep multiple instances of Respawn from all trying to write - //to PlayerPrefs within a single Update call. - if (mainRespawnScript) { + // mainRespawnScript boolean is to keep multiple instances of Respawn from all trying to write + // to PlayerPrefs within a single Update call. + if (mainRespawnScript) { if (PlayerPrefs.HasKey("LatestLevel") && PlayerPrefs.GetString("LatestLevel") == Application.loadedLevelName) - { + { myCheckpoint = PlayerPrefs.GetString("LatestCheckpoint"); - currentRespawn = GameObject.Find(myCheckpoint).GetComponent(Respawn); + currentRespawn = myCheckpoint ? GameObject.Find(myCheckpoint).GetComponent(Respawn) : initialRespawn; var tempPlayer : GameObject = GameObject.Find("Player"); var tempPlayerComponent : FallingPlayer = tempPlayer.GetComponent("FallingPlayer"); var IntroScriptComponent : IntroSequence1stPerson = tempPlayer.GetComponent("IntroSequence1stPerson"); @@ -86,11 +86,8 @@ function Start() } else { currentRespawn = initialRespawn; - } + } } - // else { - // currentRespawn = initialRespawn; - // } SaveCheckpoint(); } @@ -102,14 +99,13 @@ function OnTriggerEnter(other : Collider) { // turn the old respawn point off //currentRespawn.SetInactive (); - + // play the "Activated" one-shot sound effect if one has been supplied: if (SFXRespawnActivate) AudioSource.PlayClipAtPoint(SFXRespawnActivate, transform.position, SFXVolume); - + // Set the current respawn point to be us and make it visible. currentRespawn = this; - //SetActive (); } } } @@ -120,6 +116,11 @@ function OnApplicationPause(pauseStatus: boolean) { } } +// NB: We currently only persistently save checkpoints on pause +// (including app-to-background auto-pausing) and level loading. +// Writing to PlayerPrefs can be slow and introduce visual stutter, so we do NOT +// save in prefs when you pass a checkpoint during gameplay, although we do update the global +// currentRespawn var, so respawn works. function SaveCheckpoint() { if (mainRespawnScript) { myCheckpoint = currentRespawn.transform.name; diff --git a/ScoreController.js b/ScoreController.js index 49dd6bf..1cd73fe 100644 --- a/ScoreController.js +++ b/ScoreController.js @@ -1,14 +1,14 @@ #pragma strict // Keep track of the player's main score -static var currentScore : float = 20f; -static var maxScore = 25f; +static var currentScore : float = 20.0; +static var maxScore : float = 25.0; // Keep track of the currently visible score -static var visibleScore : float = 20f; +static var visibleScore : float = 20.0; function Start() { - ResetScore (25); + ResetScore (); } function LerpVisibleScore (start : float, end : float, timer : float) { @@ -43,4 +43,6 @@ function ScoreUpdate ( timer : float) { // Debug.Log("Your visibleScore is: " + visibleScore + " and your currentScore is: " + currentScore); } -function ResetScore ( i : float ) {currentScore = maxScore;} \ No newline at end of file +function ResetScore () { + currentScore = maxScore; +} \ No newline at end of file diff --git a/SimpleVelocityLimiter.js b/SimpleVelocityLimiter.js index 8a94b74..a16e8db 100644 --- a/SimpleVelocityLimiter.js +++ b/SimpleVelocityLimiter.js @@ -29,7 +29,11 @@ function SetMaxVelocity(maxVelocity : float){ sqrMaxVelocity = maxVelocity * maxVelocity; } -// FixedUpdate is a built-in unity function that is called every fixed framerate frame. +function GetMaxVelocity() { + return maxVelocity; +} + +// FixedUpdate is a built-in Unity function that is called every fixed framerate frame. // We use FixedUpdate instead of Update here because the docs recommend doing so when // dealing with rigidbodies. // For more info, see: diff --git a/SpeedLines.js b/SpeedLines.js index e49eab8..0d9f286 100644 --- a/SpeedLines.js +++ b/SpeedLines.js @@ -31,46 +31,44 @@ function FadeFlash (timer : float, fadeType : FadeDir) { function LinesFlash (timer : float, fadeType : FadeDir) { - var start = fadeType == FadeDir.In? speedLinesMaterial.color.a : peakValue; - var end = fadeType == FadeDir.In? peakValue : 0.0; + var start = (fadeType == FadeDir.In) ? speedLinesMaterial.color.a : peakValue; + var end = (fadeType == FadeDir.In) ? peakValue : 0.0; var audioStart = speedLinesAudio2.volume; - var audioEnd = 1.0; + var audioEnd = 1.0; var i = 0.0; var step = 1.0/timer; - + speedLinesRenderer.enabled = true; -// if (controllerITween2.speedingUp == 2) { -// if ((controllerITween2.speedingUp == 2) && (controllerITween2.Slowdown < 1)) { if (i == 0.0) { if (!speedLinesAudio1.isPlaying) {speedLinesAudio1.Play();} if (!speedLinesAudio2.isPlaying) {speedLinesAudio2.Play();} } - - while (i <= 1.0) { + + while (i <= 1.0) { i += step * Time.deltaTime; speedLinesMaterial.color.a = Mathf.Lerp(start, end, i); - speedLinesAudio2.volume = Mathf.SmoothStep(audioStart, audioEnd, i); + speedLinesAudio2.volume = Mathf.SmoothStep(audioStart, audioEnd, i); yield; - + if (MoveController.Slowdown < 1) {break;} } yield WaitForSeconds (timer); - MoveController.speedingUp = 1; + MoveController.speedingUp = 1; // } - + } function LinesFlashOut (timer : float, fadeType : FadeDir) { - var start = fadeType == FadeDir.In? 0.0 : peakValue; - var end = fadeType == FadeDir.In? speedLinesMaterial.color.a : 0.0; + var start = (fadeType == FadeDir.In) ? 0.0 : peakValue; + var end = (fadeType == FadeDir.In) ? speedLinesMaterial.color.a : 0.0; var audioStart = speedLinesAudio2.volume; - var audioEnd = 0.0; + var audioEnd = 0.0; var i = 0.0; var step = 1.0/timer; - - if (MoveController.speedingUp == 0) { + + if (MoveController.speedingUp == 0) { while (i <= 1.0) { i += step * Time.deltaTime; speedLinesMaterial.color.a = Mathf.Lerp(end, start, i); @@ -78,7 +76,7 @@ function LinesFlashOut (timer : float, fadeType : FadeDir) { yield; if (MoveController.Slowdown > 1) {speedLinesRenderer.enabled = true; break;} - if (i >= 1.0) {speedLinesRenderer.enabled = false;} + if (i >= 1.0) {speedLinesRenderer.enabled = false;} } yield WaitForSeconds (timer/3); MoveController.speedingUp = 1; @@ -92,14 +90,14 @@ function LinesLerpOut (timer : float) { var start = speedLinesMaterial.color.a; var end = 0.0; var audioStart = speedLinesAudio2.volume; - var audioEnd = 0.0; + var audioEnd = 0.0; var i = 0.0; var step = 1.0/timer; while (i <= 1.0) { i += step * Time.deltaTime; speedLinesMaterial.color.a = Mathf.Lerp(start, end, i); - speedLinesAudio2.volume = Mathf.Lerp(audioStart, audioEnd, i); + speedLinesAudio2.volume = Mathf.Lerp(audioStart, audioEnd, i); yield; } } @@ -112,4 +110,4 @@ function LinesOff () { speedLinesAudio2.volume = 0; } else {return;} -} \ No newline at end of file +} diff --git a/VRLifeMeter.js b/VRLifeMeter.js new file mode 100644 index 0000000..88bedd2 --- /dev/null +++ b/VRLifeMeter.js @@ -0,0 +1,101 @@ +#pragma strict + +var thisImage : UnityEngine.UI.Image; +var loadingCircleVR : UnityEngine.UI.Image; +var loadingCircleVRObj : GameObject; + +// private var thisImageMatl : Material; +var fullColor: Color = Color32(255, 255, 255, 165); +var emptyColor: Color = Color.red; // Color32(156, 24, 24, 255); +private var lifePercentage : float = 1; + +private var peakOpacity : float = 1.0; + +private var isVisible : boolean = false; + +function Awake() { + peakOpacity = fullColor.a; +} + +function Start() { + if ( FallingLaunch.isVRMode && (!loadingCircleVR || !loadingCircleVRObj) ) { + loadingCircleVRObj = GameObject.Find("loading-bar"); + + var loadingObjTransform : Transform = + loadingCircleVRObj ? loadingCircleVRObj.transform : null; + + loadingCircleVR = // loadingCircleVR || + loadingObjTransform ? loadingObjTransform.GetComponent.() : null; + } + + if (FallingLaunch.isVRMode && loadingCircleVR) { + HideLoadingCircle(); + } +} + +function FadeReticle(timer : float, fadeType : FadeDir) { + + var start = fadeType == FadeDir.In ? 0.0 : peakOpacity; + var end = fadeType == FadeDir.In ? peakOpacity : 0.0; + var i = 0.0; + var step = 1.0/timer; + + while (i <= 1.0) { + i += step * Time.deltaTime; + thisImage.color.a = Mathf.Lerp(start, end, i); + // If you want to also change the color of the reticle center, modify the material + // instead of Sprite color, via: + // thisImageMatl.color.a = Mathf.Lerp(start, end, i); + + // Debug.Log('fading with fadeType ' + fadeType + ' and alpha ' + thisImageMatl.color.a); + yield; + } +} + +function FadeReticleIn (timer : float) { + isVisible = true; + yield FadeReticle(timer, FadeDir.In); +} + +function FadeReticleOut (timer : float) { + yield FadeReticle(timer, FadeDir.Out); + isVisible = false; +} + +function UpdateLoadingCircle (value : float) { + if (loadingCircleVRObj && loadingCircleVR) { + if (!loadingCircleVRObj.activeInHierarchy) { + loadingCircleVRObj.SetActive(true); + } + + loadingCircleVR.color.a = 1.0; + loadingCircleVR.fillAmount = value; + } +} + +function HideLoadingCircle () { + if (loadingCircleVRObj && loadingCircleVR) { + loadingCircleVR.color.a = 0; + loadingCircleVRObj.SetActive(false); + } +} + +function Update () { + // Deactivate the VR reticle and early return if we're not in VR mode. + if (!FallingLaunch.isVRMode) { + gameObject.SetActive(false); + return; + } + + if (FallingPlayer.isAlive == 1 && isVisible) { + lifePercentage = parseFloat(ScoreController.visibleScore)/parseFloat(ScoreController.maxScore); + thisImage.fillAmount = lifePercentage; + + // Fade reticle from white down to crimson once the player's life is below ~60%: + // For a fancier squared-ratio lerp (starts at roughly 2/3 life ratio): (lifePercentage*lifePercentage)*2 + thisImage.color = Color.Lerp(emptyColor, fullColor, Mathf.Clamp(lifePercentage*2 - .2, 0.0, 1.0) ); + } else { + thisImage.color.a = 0; + // loadingCircleVR.color.a = 0; + } +} diff --git a/WormDeath.js b/WormDeath.js index 8803c28..d4f7462 100644 --- a/WormDeath.js +++ b/WormDeath.js @@ -8,9 +8,9 @@ function Update () { var hit : RaycastHit; if (Physics.Raycast (transform.position, Vector3.up, hit, 100)) { //Debug.Log(hit.distance); - if (hit.rigidbody != null && lifeCountdown.isAlive == 1) { + if (hit.rigidbody != null && FallingPlayer.isAlive == 1) { Debug.Log(hit.distance); - lifeCountdown.isAlive = 0; + FallingPlayer.isAlive = 0; GetComponent(FallingPlayer).DeathRespawn (); } } diff --git a/changeBackdrop.js b/changeBackdrop.js index ea8fd49..51ec226 100644 --- a/changeBackdrop.js +++ b/changeBackdrop.js @@ -1,7 +1,6 @@ #pragma strict var newMat : Material; - var origMat : Material; var fadeTex : Texture2D; @@ -9,18 +8,42 @@ var fadeTex : Texture2D; var mainCamera : GameObject; var cam : Camera; -static var oceanCamera : GameObject; -var backdropMist : GameObject; -static var oceanRenderer : Renderer; -static var cloudRenderer : Renderer; -static var endSphereRenderer : Renderer; +var closePlaneTransform : Transform; +static var closePlaneRenderer : Renderer; +var cloudCylinderObj : GameObject; +static var cloudCylinderRenderer : Renderer; + +static var startingCloudAlpha : float; // Unity 4 used .39f (99 in RGBA) +var newCloudAlpha : float = .3f; +static var cloudOriginalMaterial : Material; + +var oceanCamera : GameObject; +var oceanCameraVR : GameObject; +private var oceanCameraVRHead : GvrHead; + +var backdropCameraObj : GameObject; +var backdropCamera : Camera; + +var backdropCameraVR : GameObject; +private var backdropCameraVRHead : GvrHead; + +var oceanRenderer : Renderer; +var cloudRenderer : Renderer; + +var eyeCamerasVR : Array; +var StereoControllerComponent : Component; + //var foo : Material; //set this in the editor //var bar : Material; //set this in the editor var oceanLevel : boolean = false; -var mistLevel : boolean = false; var ShouldUseOceanCamera : boolean = false; var ShouldChangeBackdrop : boolean = false; var FogOnly : boolean = false; + +private var origSkybox : Material; +var altSkybox : Material; + +var farClipPlaneValueOrig : int; var farClipPlaneValue : int = 2500; var fogEndValue : int = 3000; var farClipPlaneFadeTime : float = 3; @@ -30,82 +53,265 @@ var fogEndValue2 : int = 1500; var farClipPlaneFadeTime2 : float = 2; function Start () { - if (oceanLevel == true) { - mainCamera = transform.FindChild("Camera").gameObject; - - oceanCamera = transform.FindChild("Camera-for-ocean").gameObject; - backdropMist = transform.FindChild("Cylinder").gameObject; - + if (!mainCamera) { + mainCamera = Camera.main.gameObject; + // mainCamera = transform.Find("Player-cameras/Camera").gameObject; + } + + oceanCamera = + transform.Find("Player-cameras/Camera-for-ocean") ? + transform.Find("Player-cameras/Camera-for-ocean").gameObject : null; + + var oceanCameraVRTransform : Transform = mainCamera.transform.Find("Camera-for-ocean-VR"); + oceanCameraVR = oceanCameraVRTransform ? oceanCameraVRTransform.gameObject : null; + oceanRenderer = gameObject.Find("sky-water-ocean/Mesh").GetComponent.(); oceanRenderer.enabled = false; cloudRenderer = gameObject.Find("simple-cloud-plane/Mesh").GetComponent.(); cloudRenderer.enabled = false; - - endSphereRenderer = gameObject.Find("score-orbs-end/score-orb/Mesh").GetComponent.(); - endSphereRenderer.enabled = false; - } - - if (mistLevel == true) { - backdropMist = transform.FindChild("Cylinder").gameObject; - } + } + + if (ShouldChangeBackdrop) { + origSkybox = RenderSettings.skybox; + } + + var backdropCameraTransform : Transform = transform.Find("Player-cameras/Camera-for-backdrop"); + backdropCameraObj = backdropCameraTransform ? backdropCameraTransform.gameObject : null; + backdropCamera = backdropCameraObj.GetComponent.(); + + var backdropCameraVRTransform : Transform = mainCamera.transform.Find("Camera-for-bg-VR"); + backdropCameraVR = backdropCameraVRTransform ? backdropCameraVRTransform.gameObject : null; + cam = mainCamera.GetComponent.(); + + farClipPlaneValueOrig = cam.farClipPlane; + + // Warn re. plane-close/Cylinder if they haven't been manually associated via the Inspector: + if (ShouldChangeBackdrop || oceanLevel) { + if (!cloudCylinderObj && Debug.isDebugBuild) { + Debug.Log('Did you forget to link your cloudCylinderObj in the Inspector?'); + } + if (cloudCylinderObj) { + cloudCylinderRenderer = cloudCylinderObj.GetComponent.(); + cloudOriginalMaterial = cloudCylinderRenderer.material; + startingCloudAlpha = cloudOriginalMaterial.color.a; // Storing for later use. + } + + if (!closePlaneTransform && backdropCameraTransform) { + closePlaneTransform = backdropCameraTransform.Find("plane-close"); + } + if (closePlaneTransform) { + closePlaneRenderer = closePlaneTransform.GetComponent.(); + } + } + + // HACK: A coroutine to check for out-of-alignment sub-camera GvrHeads and fix them + // (Ocean and Backdrop cameras). A more robust solution would be to ensure that + // only one master GvrHead is applied to the scene at all, so we don't have to worry + // about manging its rotation and inherited stereo cameras' values. + if (FallingLaunch.isVRMode) { + CheckAndFixSecondaryVRCameras(1.5); + } else { + // if we want to keep the 'legacy' 2D rectangle-based backgrounds... + // SetupNonVRBackground(); + } + // For now, try using the same skybox for VR and regular play: + ClearNonVRBackground(); +} + +function Update () { + // Existence check required for StereoControllerComponent in Update() + // since it takes 1+ seconds to set up everything via GVR plugin: + if (FallingLaunch.isVRMode) { + if (mainCamera && !StereoControllerComponent) { + StereoControllerComponent = mainCamera.GetComponent.(); + } + } else { + return; + } +} + +function ClearNonVRBackground () { + if (cloudCylinderObj) { + Debug.Log("about to disable cloudCylinderObj " + cloudCylinderObj); + cloudCylinderObj.SetActive(false); + } + if (backdropCameraObj) { + Debug.Log("about to disable backdropCameraObj " + backdropCameraObj); + backdropCameraObj.SetActive(false); + } +} + +function SetupNonVRBackground () { + // backdropCamera starts as disabled, so it shouldn't get a stereoController or GvrHead + // auto-applied (and thus shouldn't need manual checking or rotation-fixing): + if (backdropCamera) {backdropCamera.enabled = true;} + + if (backdropCameraVR) {backdropCameraVR.SetActive(false);} +} + +function CheckAndFixSecondaryVRCameras (interval : float) { + MaintainOceanVRCamera(); + MaintainBackdropVRCamera(); + + while (true && FallingLaunch.isVRMode) { + yield WaitForSeconds(interval); + MaintainOceanVRCamera(); + MaintainBackdropVRCamera(); + } +} + +function MaintainBackdropVRCamera () { + if (!backdropCameraVRHead && backdropCameraVR && backdropCameraVR.GetComponent.()) { + backdropCameraVRHead = backdropCameraVR.GetComponent.(); + } + + if (backdropCameraVRHead) { + if (backdropCameraVRHead.trackRotation || + backdropCameraVR.transform.localRotation != Quaternion.identity + ) { + if (Debug.isDebugBuild) { + Debug.Log("backdropCameraVRHead.trackRotation value " + backdropCameraVRHead.trackRotation); + Debug.Log("backdropCameraVR.localRotation value " + backdropCameraVR.transform.localRotation); + Debug.Log("about to reset backdropCameraVR's rotation"); + } + // this GvrHead is already nested within the Player object, + // and the backdrop is meant to be static relative to the player, + // so therefore shouldn't independently track rotation: + backdropCameraVRHead.trackRotation = false; + backdropCameraVR.transform.localRotation = Quaternion.identity; + } + } +} + +function MaintainOceanVRCamera () { + if (oceanLevel && oceanCameraVR && !oceanCameraVRHead) { + if (oceanCameraVR.GetComponent.()) { + // See note in FallingPlayer.SetupVRUI() for explanation: + // oceanCameraVRHead = oceanCameraVR.GetComponent.().Head; + oceanCameraVRHead = oceanCameraVR.GetComponent.(); + + // this GvrHead is already nested within the Player camera's + // StereoController, so to stay aligned with its parent, + // it shouldn't independently track rotation: + oceanCameraVRHead.trackRotation = false; + } + } + + // Unfortunately necessary, since any object with a GvrHead could potentially get + // an out-of-whack rotation from player input for unknown causes, + // which causes dependent stereo cameras to have a rotational offset that needs zeroing. + // I thought it was caused by trackRotation ever being true (the default) after instantiation, + // but I've caught strange rotations in the Editor without the localRotation conditional + // ever logging as true... due to cached values persisting from GvrHead setup? + + // To correct for the potential race condition, we check whether trackRotation ever becomes true + // or if the ocean camera VR component's rotation is ever non-zero: + if (oceanLevel && oceanCameraVR && oceanCameraVRHead) { + if (oceanCameraVRHead.trackRotation || + oceanCameraVR.transform.localRotation != Quaternion.identity + ) { + if (Debug.isDebugBuild) { + Debug.Log("oceanCameraVRHead.trackRotation value " + oceanCameraVRHead.trackRotation); + Debug.Log("oceanCameraVR.localRotation value " + oceanCameraVR.transform.localRotation); + Debug.Log("about to reset oceanCameraVR's rotation"); + } + oceanCameraVR.transform.localRotation = Quaternion.identity; + } + } } function OnTriggerEnter (other : Collider) { if (other.gameObject.CompareTag ("changeBackdrop")) { -// not needed if not actually changing backdrop -// transform.Find("plane-close").renderer.materials = [newMat]; - if (ShouldChangeBackdrop == true) { - transform.Find("plane-close").GetComponent.().materials = [newMat];} + if (ShouldChangeBackdrop && altSkybox) { + RenderSettings.skybox = altSkybox; + } + + if (ShouldChangeBackdrop && closePlaneRenderer) { + closePlaneRenderer.materials = [newMat]; + } -// FadeBetweenCameras (); -// Enable the above method to re-add the fade 2d image backdrop on trigger enter. + if ((ShouldChangeBackdrop || oceanLevel) && cloudOriginalMaterial) { + iTween.ColorTo(cloudCylinderObj,{"a": newCloudAlpha, "time": 1}); + } -// Debug.Log("You hit a changeBackdrop trigger!"); + // Debug.Log("You hit a changeBackdrop trigger! " + other.gameObject); FadeCameraFarClipPlane (1); - if (FogOnly == true) {SmoothFogFade (1);} - if (ShouldUseOceanCamera == true) {enableOceanCamera(); SmoothFogFade (1);} - else if (mistLevel == true) {iTween.ColorTo(backdropMist,{"a":0.0f,"time":4});} + if (FogOnly) { SmoothFogFade (3); } + if (ShouldUseOceanCamera) { + if (FallingLaunch.isVRMode) { + EnableOceanCamera(true); + } else { + EnableOceanCamera(false); + } + SmoothFogFade (1); + } } else if (other.gameObject.CompareTag ("changeBackdrop2")) { - //Debug.Log("You hit an alt changeBackdrop trigger!"); + // Debug.Log("You hit an alt changeBackdrop trigger!"); + FadeCameraFarClipPlane (2); - if (FogOnly == true) {SmoothFogFade (2);} - if (ShouldUseOceanCamera == true) {enableOceanCamera(); SmoothFogFade (2);} - else if (mistLevel == true) {iTween.ColorTo(backdropMist,{"a":0.0f,"time":4});} + if (FogOnly) {SmoothFogFade (2);} + if (ShouldUseOceanCamera) { + if (FallingLaunch.isVRMode) { + EnableOceanCamera(true); + } else { + EnableOceanCamera(false); + } + SmoothFogFade (2); + } } } -function changeCameraFadeLayer() { - var cameraFadeObject : GameObject = GameObject.Find ("iTween Camera Fade"); - if(cameraFadeObject) - cameraFadeObject.layer = 4; +function OnTriggerExit (other : Collider) { + if (other.gameObject.CompareTag ("changeBackdrop") && cloudCylinderObj && + ShouldChangeBackdrop == true && closePlaneRenderer) { + closePlaneRenderer.materials = [origMat]; + + // Restore old clouds alpha on death: + if ((ShouldChangeBackdrop || oceanLevel) && cloudOriginalMaterial) { + iTween.ColorTo(cloudCylinderObj,{"a": startingCloudAlpha, "time": .5}); + } + } + + // Only used by level 1/tutorial ending 'dawn' skybox: + if (other.gameObject.CompareTag ("changeBackdrop") && ShouldChangeBackdrop) { + RenderSettings.skybox = origSkybox; + } } +// TODO: Switch iTween clip plane transitions to a regular lerp function FadeCameraFarClipPlane (type : int) { - if (type == 2) { + if (Debug.isDebugBuild) { + Debug.Log("calling FadeCameraFarClipPlane"); + } - iTween.ValueTo ( gameObject, - { - "from" : cam.farClipPlane, - "to" : farClipPlaneValue2, - "onupdate" : "ChangeCameraFarClipPlane", - "time" : farClipPlaneFadeTime2, - "easetype" : "easeInExpo" - }); - } + if (type == 2) { + iTween.ValueTo ( gameObject, + { + "from" : cam.farClipPlane, + "to" : farClipPlaneValue2, + "onstart" : "EnableStereoUpdatesVR", + "onupdate" : "ChangeCameraFarClipPlane", + "oncomplete" : "YieldDisableStereoUpdatesVR", + "time" : farClipPlaneFadeTime2, + "easetype" : "easeInExpo" + }); + } else { iTween.ValueTo ( gameObject, { "from" : cam.farClipPlane, "to" : farClipPlaneValue, + "onstart" : "EnableStereoUpdatesVR", "onupdate" : "ChangeCameraFarClipPlane", + "oncomplete" : "YieldDisableStereoUpdatesVR", "time" : farClipPlaneFadeTime, "easetype" : "easeInExpo" }); @@ -113,63 +319,164 @@ function FadeCameraFarClipPlane (type : int) { } function SmoothFogFade (type : int) { - if (type == 2) { - - iTween.ValueTo ( gameObject, - { - "from" : FallingPlayer.startingFogEndDistance, - "to" : fogEndValue2, - "onupdate" : "ChangeFogEndDistance", - "time" : farClipPlaneFadeTime2, - "easetype" : "easeInExpo" - }); - } - else { + if (type == 1) { + FogLerp(3.0, RenderSettings.fogEndDistance, fogEndValue); + } else if (type == 2) { + FogLerp(farClipPlaneFadeTime2, RenderSettings.fogStartDistance, fogEndValue2); + } else if (type == 3) { + // Effectively zeroes out fog via gentler distance dispersal. + // Assumes that fogEndValue is large enough that halving it + // will still place the fog start far from the camera. + var fogStartType3 : float = fogEndValue * .5; - iTween.ValueTo ( gameObject, - { - "from" : FallingPlayer.startingFogEndDistance, - "to" : fogEndValue, - "onupdate" : "ChangeFogEndDistance", - "time" : 3, - "easetype" : "easeInExpo" -// "oncomplete" : "CameraFadeEnd" - }); - } + FogLerp(10.0, fogStartType3, fogEndValue); + } } +function FogLerp (timer : float, startVal : float, endVal : float) { + var initStart = RenderSettings.fogStartDistance; + var initEnd = RenderSettings.fogEndDistance; + + var start = startVal; + var end = endVal; + var i = 0.0; + var step = 1.0/timer; + + while (i <= 1.0) { + i += step * Time.deltaTime; + var t : float = i*i * (3f - 2f*i); // smoothstep lerp + RenderSettings.fogStartDistance = Mathf.Lerp(initStart, start, t); + RenderSettings.fogEndDistance = Mathf.Lerp(initEnd, end, t); -function FadeBetweenCameras () { - iTween.CameraFadeAdd(fadeTex); - changeCameraFadeLayer(); - iTween.CameraFadeTo(0.75,.25); - yield WaitForSeconds(.25); - iTween.CameraFadeTo(0.0,3); + // Reset fog if player dies mid-fog-lerp: + if (FallingPlayer.isAlive == 0) { + RenderSettings.fogStartDistance = initStart; + RenderSettings.fogEndDistance = initEnd; + break; + } + + yield; + } } -function CameraFadeEnd () { - iTween.CameraFadeTo(0.0,1); +function ResetCameraClipPlane() { + if (Debug.isDebugBuild) { + Debug.Log("called ResetCameraClipPlane with current clip plane " + cam.farClipPlane); + Debug.Log("...and farClipPlaneValueOrig " + farClipPlaneValueOrig); + } + + // This function gets called on first level load (via LatestCheckpointRespawn), + // so we only want to proceed if the current camera clip value doesn't match + // the specified starting value. This should avoid having more than one iTween lerp + // occurring simultaneously and polluting each other. + // TODO: Switch iTween to regular lerps + if (FallingLaunch.isVRMode && farClipPlaneValueOrig != cam.farClipPlane) { + + if (Debug.isDebugBuild) { + Debug.Log("resetting main VR camera clip plane to " + farClipPlaneValueOrig); + } + + // Set the primary camera's draw distance (far clip plane), + // and enable the keepStereoUpdated boolean on the parent + // stereo controller, so the child eye cameras will update to match. + yield EnableStereoUpdatesVR(); + yield ResetFarClipPlane(); + yield DisableStereoUpdatesVR(); // Then disable `keepStereoUpdated` for performance + + } else if (cam && cam.farClipPlane != farClipPlaneValueOrig) { + cam.farClipPlane = farClipPlaneValueOrig; + } } -function ChangeFogEndDistance (i : int) { - RenderSettings.fogEndDistance = i; - //RenderSettings.fogStartDistance = .5*i; +// this gets yielded so we can be sure the new value is set before proceeding: +function ResetFarClipPlane() : IEnumerator { + cam.farClipPlane = farClipPlaneValueOrig; } function ChangeCameraFarClipPlane (i : int) { cam.farClipPlane = i; } -function enableOceanCamera () { - oceanCamera.GetComponent(Camera).enabled = true; +function EnableStereoUpdatesVR () { + if (Debug.isDebugBuild) { + Debug.Log("called EnableStereoUpdatesVR"); + } + // Existence check required for StereoControllerComponent since + // it takes 1+ seconds to instantiate via GVR plugin: + if (FallingLaunch.isVRMode && StereoControllerComponent) { + // Type coercion is required... details in setVRMode.Start(): + (StereoControllerComponent as StereoController).keepStereoUpdated = true; + if (Debug.isDebugBuild) { + Debug.Log("keepStereoUpdated is true"); + } + } + yield; +} + +// needed because iTween can't directly call a function that yields; +function YieldDisableStereoUpdatesVR () { + yield DisableStereoUpdatesVR(); +} + +function DisableStereoUpdatesVR () { + if (Debug.isDebugBuild) { + Debug.Log("DisableStereoUpdatesVR"); + } + // Existence check required for StereoControllerComponent since + // it takes 1+ seconds to instantiate via GVR plugin: + if (FallingLaunch.isVRMode && StereoControllerComponent) { + // Just to make sure the below parent camera alterations + // actually propagate to the relevant stereo cameras: + if ((StereoControllerComponent as StereoController).keepStereoUpdated == false) { + (StereoControllerComponent as StereoController).keepStereoUpdated = true; + } + + eyeCamerasVR = getMainChildVRCameras(mainCamera); + + for (var camera : Camera in eyeCamerasVR) { + if (Debug.isDebugBuild) { + Debug.Log("Setting camera " + camera + "'s farClipPlane to " + cam.farClipPlane); + } + camera.farClipPlane = cam.farClipPlane; + } + + // it takes at least one frame for the GVR plugin to update the relevant cameras + // based on the keepStereoUpdated boolean, so this assumes at least 2fps: + + // ...or handle StereoController existence check via a coroutine/callback? + yield WaitForSeconds(.5); + // Type coercion is required... details in setVRMode.Start(): + (StereoControllerComponent as StereoController).keepStereoUpdated = false; + } + return; +} + +function EnableOceanCamera (isVR: boolean) { + if (!isVR) { + oceanCamera.GetComponent(Camera).enabled = true; + } + oceanRenderer.enabled = true; - cloudRenderer.enabled = true; - endSphereRenderer.enabled = true; - iTween.ColorTo(backdropMist,{"a":0.0f,"time":4}); } -function OnTriggerExit (other : Collider) { - if (other.gameObject.CompareTag ("changeBackdrop") && ShouldChangeBackdrop == true) { - transform.Find("plane-close").GetComponent.().materials = [origMat]; - } + +function getMainChildVRCameras(obj : GameObject) : Array{ + var children : Array = new Array(); + for (var child : Transform in obj.transform) { + var eyeCam = child.GetComponent.(); + if (Debug.isDebugBuild) { + Debug.Log("eyeCam is " + eyeCam); + Debug.Log("with name " + child.gameObject.name); + } + + // HACK: Brittle attempt to filter by camera name to include only 'main' child cameras, + // and not those of VR UI, Ocean, or Backdrop cameras. + if (eyeCam && (child.gameObject.name == 'Camera Left' || child.gameObject.name == 'Camera Right')) { + if (Debug.isDebugBuild) { + Debug.Log("Adding this eyeCam to results: " + eyeCam); + } + children.Add(eyeCam); + } + } + return children; } \ No newline at end of file diff --git a/fallingIntroUI.js b/fallingIntroUI.js index eae4e05..e22a29b 100644 --- a/fallingIntroUI.js +++ b/fallingIntroUI.js @@ -2,9 +2,13 @@ var scriptName : GameObject; static var currentIcon : UISprite; +private var tutorialObjVR : GameObject; +private var iconVRMatl : Material; +private var iconVRRenderer : Renderer; function Start () { - } + tutorialObjVR = gameObject.Find("tutorial-vr-ui-group"); +} function ShowIcon(icon : UISprite, timer : float, bgIcon : UISprite) { // tutorialSpritePosition(timer); @@ -25,4 +29,46 @@ function ShowIcon(icon : UISprite, timer : float, bgIcon : UISprite) { icon.alphaTo( 2.0f, 0.0f, Easing.Sinusoidal.easeOut); yield WaitForSeconds (2); icon.hidden = true; +} + +function ShowIconVR(iconName : String, timer : float) { + // TODO: Improve perf by grabbing and caching these in Start? + // find corresponding gameObject in children: + // Debug.Log("Showing " + iconName); + var thisIcon : GameObject = tutorialObjVR.transform.Find(iconName).gameObject; + + if (thisIcon) { + thisIcon.SetActive(true); + iconVRRenderer = thisIcon.GetComponent.(); + iconVRMatl = iconVRRenderer.material; + // iconVRMatl.color.a = 1; + FadeIconVR(timer/4, FadeDir.In); + + yield WaitForSeconds (timer/2); + if (FallingPlayer.isAlive == 0) { + iconVRMatl.color.a = 0; thisIcon.SetActive(false); return; + } + yield WaitForSeconds (timer/4); + + FadeIconVR(timer/4, FadeDir.Out); + + yield WaitForSeconds (timer/4); + // iconVRMatl.color.a = 0; + thisIcon.SetActive(false); + } +} + +function FadeIconVR (timer : float, fadeType : FadeDir) { + + var start = fadeType == FadeDir.In ? 0.0 : 0.8; + var end = fadeType == FadeDir.In ? 0.8 : 0.0; + var i = 0.0; + var step = 1.0/timer; + + while (i <= 1.0) { + i += step * Time.deltaTime; + iconVRMatl.color.a = Mathf.Lerp(start, end, i); + yield; + if (FallingPlayer.isAlive == 0) {iconVRMatl.color.a = 0.0; break;} + } } \ No newline at end of file diff --git a/fallingStartMenuUI.js b/fallingStartMenuUI.js index fccf0fd..4fc91e3 100644 --- a/fallingStartMenuUI.js +++ b/fallingStartMenuUI.js @@ -56,6 +56,13 @@ var thinText : UIText; var text1 : UITextInstance; var text2 : UITextInstance; var text3 : UITextInstance; + +var appStoreButtonText : UITextInstance; +var appStoreButtonBg : UIButton; + +var appStoreButtonHomeText : UITextInstance; +var appStoreButtonHomeBg : UIButton; + var tiltText1 : UITextInstance; var tiltText2 : UITextInstance; var invertHorizAxisText : UITextInstance; @@ -70,6 +77,10 @@ var isSaving : boolean = false; var openSiteButtonText : UIButton; +var vrModeButton : UIButton; + +var vrModeLaunchButton : UIButton; +var vrExplanatoryText : UITextInstance; private var savedTimeScale:float; @@ -83,52 +94,68 @@ var bgCamera : Camera; var bgColor1 : Color; var bgColor2 : Color = Color.red; -var fallingLaunch : GameObject; -var fallingLaunchComponent : FallingLaunch; +private var fallingLaunch : GameObject; +private var fallingLaunchComponent : FallingLaunch; function Awake () { //Input.compensateSensors = true; - - Debug.Log("My orientation is " + Screen.orientation); - //Screen.orientation = ScreenOrientation.AutoRotation; - // if (FallingLaunch.hasSetOrientation == false) { - // AutoOrientToLandscape(); - // } + fallingLaunch = GameObject.Find("LaunchGameObject"); + fallingLaunchComponent = fallingLaunch.GetComponent.(); - if (!FallingLaunch.hasSetOrientation) { - if (Input.deviceOrientation == DeviceOrientation.LandscapeRight) { - FallingLaunch.flipMultiplier = FallingLaunch.flipMultiplier * -1; - //Debug.Log("I'm in LandscapeRight!"); - Screen.orientation = ScreenOrientation.LandscapeRight; - FallingLaunch.landscapeFlipped = true; - FallingLaunch.neutralPosTilted = FallingLaunch.neutralPosTiltedFlipped; - } - else { Screen.orientation = ScreenOrientation.LandscapeLeft; - FallingLaunch.flipMultiplier = FallingLaunch.flipMultiplier * 1; - //Debug.Log("I'm in LandscapeLeft, or Portrait, or FaceDown/Up!"); - FallingLaunch.neutralPosTilted = FallingLaunch.neutralPosTiltedRegular; - } + if (Debug.isDebugBuild) { + Debug.Log("My screen orientation is " + Screen.orientation); - FallingLaunch.hasSetOrientation = true; + Debug.Log("My Input.deviceOrientation orientation is " + Input.deviceOrientation); + Debug.Log("Cached FallingLaunch Input.deviceOrientation is " + FallingLaunch.initialInputDeviceOrientation); } - fallingLaunch = GameObject.Find("LaunchGameObject"); - fallingLaunchComponent = fallingLaunch.GetComponent("FallingLaunch"); + ScreenH = Screen.height; + ScreenW = Screen.width; screenAspectRatio = (ScreenH / ScreenW); } + function Start () { + // // Just to be safe, exclude portrait modes from potential autorotation: + // BUG: Causes crash if device actually is in portrait or portrait upside-down. + // Screen.autorotateToPortrait = false; + // Screen.autorotateToPortraitUpsideDown = false; + + // We have to use autoRotation here, due to crashes on force-changing Screen.orientation + // in conjunction with permitted-via-settings autoRotation + // (if app launches mid-screen-rotation?). + // Source: https://forum.unity.com/threads/unitydefaultviewcontroller-should-be-used-only-if-unity-is-set-to-autorotate.314542/#post-2833628 + Screen.orientation = ScreenOrientation.AutoRotation; + + // on iPhones, we could probably assume input to be landscape-left most of the time, + // unless the device is known to be in landscape-right + // (the edge cases are iPads lying on a flat surface, which could have either screen orientation): + + // This function waits an [arbitrary] second for iOS's autorotation to settle, then locks it. + // It's not yielded, so it doesn't delay execution of the below. + if (!FallingLaunch.isVRMode) { + fallingLaunchComponent.LockDeviceOrientation(1.0); + } + + if (Debug.isDebugBuild) { + Debug.Log("My final screen orientation is " + Screen.orientation); + } + + // resets all prefs on launch to simplify debugging: + // PlayerPrefs.DeleteAll(); if (PlayerPrefs.HasKey("HighestLevel") == false) { FallingLaunch.levelAchieved = Application.loadedLevel + 1; PlayerPrefs.SetInt("HighestLevel", FallingLaunch.levelAchieved); } - + FallingLaunch.levelAchieved = PlayerPrefs.GetInt("HighestLevel"); -// yield WaitForSeconds(0.5f); + // every return to the Start menu means re-entering VR mode + // should show the in-level intro UI: + FallingLaunch.shouldShowVRIntroUI = true; -// Testing to see if disabling this hard coded screen.orientation will allow auto detection of landscape +// Testing to see if disabling this hard coded screen.orientation will allow auto detection of landscape // right or left mode on startup. // Screen.orientation = ScreenOrientation.LandscapeLeft; @@ -148,7 +175,7 @@ function Start () { else if (FallingLaunch.levelAchieved == 4) { level2Unlocked = true; level3Unlocked = true; - } + } else if (FallingLaunch.levelAchieved == 3) { level2Unlocked = true; } @@ -158,7 +185,7 @@ function Start () { level3Unlocked = true; level4Unlocked = true; } - + bgSpriteStart = UIT.firstToolkit.addSprite( "menuBackground.png", 0, 0, 2 ); bgSpriteStart.positionCenter(); bgSpriteStart.scaleTo( 0.0001f, new Vector3( (Screen.width * 6), (Screen.height * 6), 1 ), Easing.Sinusoidal.easeOut); @@ -169,7 +196,7 @@ function Start () { bgSprite.scaleTo( 0.01f, new Vector3( (Screen.width * 6), (Screen.height * 6), 1 ), Easing.Sinusoidal.easeOut); bgSprite.alphaTo( 0.01f, 0.94f, Easing.Sinusoidal.easeOut); bgSprite.hidden = true; - + pauseButton = UIButton.create("pauseWhite.png","pauseGray.png", 0, 0); pauseButton.pixelsFromTopRight( 5, 5 ); pauseButton.highlightedTouchOffsets = new UIEdgeOffsets(30); @@ -178,15 +205,15 @@ function Start () { pauseButton.hidden = true; if (UIT.isHD == true) { - buttonScaleFactor = (((Screen.height / 2.0) - 100.0) / Screen.height); + buttonScaleFactor = (((Screen.height / 2.0) - 100.0) / Screen.height); } else { - buttonScaleFactor = (((Screen.height / 2.0) - 50.0) / Screen.height); + buttonScaleFactor = (((Screen.height / 2.0) - 50.0) / Screen.height); } boldText = new UIText( "font-bold", "font-bold.png" ); thinText = new UIText( "font-thin", "font-thin.png" ); - + boldText.alignMode = UITextAlignMode.Center; boldText.verticalAlignMode = UITextVerticalAlignMode.Middle; boldText.wrapMode = UITextLineWrapMode.MinimumLength; @@ -196,20 +223,87 @@ function Start () { thinText.wrapMode = UITextLineWrapMode.None; text1 = thinText.addTextInstance( "CREATED BY TYSON KUBOTA", 0, 0 ); - //text1.positionFromTop(.3f); - //text1.positionFromCenter(-.1f,0f); - text1.pixelsFromCenter( -25, 0 ); + text1.pixelsFromCenter( -55, 0 ); text2 = boldText.addTextInstance( "tysonkubota.net/skydrift", 0, 0); - text2.positionCenter(); + text2.pixelsFromCenter( -30, 0 ); + + text3 = thinText.addTextInstance( "MUSIC BY EVAN KUBOTA\n\nSOUND EFFECTS: freesound.org", 0, 0); + text3.pixelsFromCenter( 45, 0 ); + + openSiteButtonText = UIButton.create("tutorialBackground.png","tutorialBackground.png", 40, 40); + openSiteButtonText.positionFromCenter(0,0); + openSiteButtonText.onTouchUpInside += OpenFallingSite; + openSiteButtonText.scaleTo( 0.1f, new Vector3( (Screen.width), 3, 1 ), Easing.Sinusoidal.easeOut); + openSiteButtonText.alphaFromTo(0.1f, 0.0f, 0.0f, Easing.Sinusoidal.easeOut); - //text3 = thinText.addTextInstance( "Music by Evan Kubota\nTextures: nobiax\nSound effects: freesound.org", 0, 0 ); - text3 = thinText.addTextInstance( "MUSIC BY EVAN KUBOTA\n\nSOUND EFFECTS: freesound.org", - 0, 0, 0.8f, 1, Color.white, UITextAlignMode.Center, UITextVerticalAlignMode.Bottom ); - text3.positionFromBottom(.3f); + appStoreButtonText = boldText.addTextInstance( "WRITE A REVIEW...", 0, 0); + appStoreButtonText.positionFromBottom(.05); + // A transparent tappable background; chosen for its width: + appStoreButtonBg = UIButton.create("spheresText.png", "spheresText.png", 0,0); + appStoreButtonBg.positionFromBottom(.05); + appStoreButtonBg.onTouchUpInside += OpenAppStorePage; + appStoreButtonBg.alphaFromTo(0.1f, 0.0f, 0.0f, Easing.Sinusoidal.easeOut); + + appStoreButtonHomeText = boldText.addTextInstance( "WRITE A REVIEW...", 0, 0); + appStoreButtonHomeText.positionFromTop(.05); + + // A transparent tappable background; chosen for its width: + appStoreButtonHomeBg = UIButton.create("spheresText.png", "spheresText.png", 0,0); + appStoreButtonHomeBg.positionFromTop(.05); + appStoreButtonHomeBg.onTouchUpInside += OpenAppStorePage; + appStoreButtonHomeBg.alphaFromTo(0.1f, 0.0f, 0.0f, Easing.Sinusoidal.easeOut); + + + text1.hidden = true; + text2.hidden = true; + text3.hidden = true; + openSiteButtonText.hidden = true; + appStoreButtonText.hidden = true; + appStoreButtonHomeText.hidden = true; + appStoreButtonBg.hidden = true; + appStoreButtonHomeBg.hidden = true; + + // TODO: Use real VR Mode icon and button sprite here. + // HACK: reusing existing button sprite as a transparent background + // for the "VR Mode" text label (which is not clickable): + + // When this toggle is based on rendered pixels, only the larger iPhones should pass, + // e.g. the "Plus" lineup (6/7/8+) and iPhone X (https://developer.apple.com/library/content/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html): + var vrModeButtonSpriteString : String = Screen.width > 1700 ? "vrModeLarge.png" : "vrMode.png"; + vrModeButton = UIButton.create(vrModeButtonSpriteString, vrModeButtonSpriteString, 0,0); + + // bottom-left corner: + // vrModeButton.positionFromBottomLeft ( .05, (.05 * screenAspectRatio) ); + + // to center: + vrModeButton.positionFromBottom(.05); + + vrModeButton.normalTouchOffsets = new UIEdgeOffsets( 40 ); + vrModeButton.highlightedTouchOffsets = new UIEdgeOffsets( 40 ); + vrModeButton.onTouchUpInside += OpenVRModeMenu; + + vrModeLaunchButton = UIButton.create("startDown.png","startDown.png", 0, 0); + vrModeLaunchButton.positionFromCenter(.1, 0); + + vrModeLaunchButton.onTouchUpInside += LaunchVRMode; + vrModeLaunchButton.onTouchDown += fadeInVRLaunchButton; + vrModeLaunchButton.onTouchUp += fadeOutVRLaunchButton; + + var vrExplanatoryString : String = + "VR MODE REQUIRES GOOGLE CARDBOARD.\n\nPRESS PLAY BELOW, THEN PLACE IN HEADSET."; + + vrExplanatoryText = + thinText.addTextInstance( vrExplanatoryString, 0, 0); + vrExplanatoryText.positionFromCenter(-.2, 0); + + vrModeButton.hidden = true; + vrModeLaunchButton.hidden = true; + vrExplanatoryText.hidden = true; optionsButton = UIButton.create("options.png", "options.png", 0,0); + //optionsButton.positionFromBottomRight( .05f, .05f ); //optionsButton.pixelsFromBottomRight ( 14, 14 ); optionsButton.positionFromBottomRight ( .05f, (.05f * screenAspectRatio) ); @@ -223,8 +317,8 @@ function Start () { tiltText2.verticalAlignMode = UITextVerticalAlignMode.Bottom; tiltText2.positionFromRight( -.16f, .52f ); tiltText2.hidden = true; - //public UITextInstance addTextInstance( string text, float xPos, float yPos, - //float scale, int depth, Color color, UITextAlignMode alignMode, UITextVerticalAlignMode verticalAlignMode ) + //public UITextInstance addTextInstance( string text, float xPos, float yPos, + //float scale, int depth, Color color, UITextAlignMode alignMode, UITextVerticalAlignMode verticalAlignMode ) invertHorizAxisText = thinText.addTextInstance( "HORIZONTAL AXIS", 0, 0 ); invertHorizAxisText.verticalAlignMode = UITextVerticalAlignMode.Bottom; invertHorizAxisText.positionFromRight( .00f, .52f ); @@ -273,7 +367,7 @@ function Start () { if (PlayerPrefs.GetInt("invertHorizAxis", 0) == 1) {FallingLaunch.invertHorizAxisVal = -1;} else {FallingLaunch.invertHorizAxisVal = 1;} if (PlayerPrefs.GetInt("invertVertAxis", 0) == 1) {FallingLaunch.invertVertAxisVal = -1;} - else {FallingLaunch.invertVertAxisVal = 1;} + else {FallingLaunch.invertVertAxisVal = 1;} tiltText1 = thinText.addTextInstance( "CHOOSE A NEUTRAL TILT ANGLE", 0, 0 ); tiltText1.pixelsFromCenter( -40, 0 ); @@ -326,21 +420,9 @@ function Start () { verticalTiltChooser.onTouchUpInside += ToggleTiltNeutral; verticalTiltChooser.hidden = true; - - openSiteButtonText = UIButton.create("tutorialBackground.png","tutorialBackground.png", 40, 40); - openSiteButtonText.positionFromCenter(0,0); - openSiteButtonText.hidden = true; - openSiteButtonText.onTouchUpInside += OpenFallingSite; - openSiteButtonText.scaleTo( 0.1f, new Vector3( (Screen.width), 3, 1 ), Easing.Sinusoidal.easeOut); - openSiteButtonText.alphaFromTo(0.1f, 0.0f, 0.0f, Easing.Sinusoidal.easeOut); - - text1.hidden = true; - text2.hidden = true; - text3.hidden = true; - tiltWarning = UIButton.create("tiltwarning.png","tiltwarning.png", 0, 0); tiltWarning.positionFromTop(buttonScaleFactor); - + rightArrow = UIButton.create("startDown.png","startDown.png", 0, 0); rightArrow.positionFromTopRight(buttonScaleFactor,0.2f); rightArrow.onTouchUpInside += ResumeGame; @@ -353,31 +435,58 @@ function Start () { //Debug.Log ("your screen aspect ratio is " + screenAspectRatio); BackToPauseMenuButton.normalTouchOffsets = new UIEdgeOffsets( 30 ); BackToPauseMenuButton.highlightedTouchOffsets = new UIEdgeOffsets( 30 ); - + loadLevelOne = UIButton.create("level1.png","level1.png", 0, 0); loadLevelOne.positionFromTopLeft(buttonScaleFactor,0.05f); loadLevelOne.onTouchUpInside += LoadLevel1ViaStart; loadLevelOne.onTouchUp += upLevel1; loadLevelOne.onTouchDown += downLevel1; - + + var calculatedMiddleIconRatio : float = 0.0f; + + if (ScreenW > 2200) { + calculatedMiddleIconRatio = 0.36f; + } else if (ScreenW > 1600) { + calculatedMiddleIconRatio = 0.33f; + } else if (ScreenW > 1200) { + calculatedMiddleIconRatio = 0.32f; + } else if (ScreenW > 1000) { + calculatedMiddleIconRatio = 0.31f; + } else { + calculatedMiddleIconRatio = 0.3f; + } + + var middleIconAdjustRatio : float = UIT.isHD ? calculatedMiddleIconRatio : 0.3f; + + // Debug.Log("buttonScaleFactor: " + buttonScaleFactor); + // Debug.Log("ScreenW: " + ScreenW); + // Debug.Log("calculatedMiddleIconRatio: " + calculatedMiddleIconRatio); + // Debug.Log("middleIconAdjustRatio: " + middleIconAdjustRatio); + loadLevelTwo = UIButton.create("level2.png","level2.png", 0, 0); - loadLevelTwo.positionFromTopLeft(buttonScaleFactor,0.3f); + + loadLevelTwo.positionFromTopLeft(buttonScaleFactor, middleIconAdjustRatio); + if (level2Unlocked) { loadLevelTwo.onTouchUpInside += LoadLevel2ViaStart; loadLevelTwo.onTouchUp += upLevel2; loadLevelTwo.onTouchDown += downLevel2; } else {loadLevelTwo.onTouchUpInside += DoNothing;} - + loadLevelThree = UIButton.create("level3.png","level3.png", 0, 0); - loadLevelThree.positionFromTopRight(buttonScaleFactor,0.3f); + + // var level3Space : float = (ScreenW * 0.9f) / 3.0; + + loadLevelThree.positionFromTopRight(buttonScaleFactor, middleIconAdjustRatio); + if (level3Unlocked) { loadLevelThree.onTouchUpInside += LoadLevel3ViaStart; loadLevelThree.onTouchUp += upLevel3; - loadLevelThree.onTouchDown += downLevel3; + loadLevelThree.onTouchDown += downLevel3; } - else {loadLevelThree.onTouchUpInside += DoNothing;} - + else {loadLevelThree.onTouchUpInside += DoNothing;} + loadLevelFour = UIButton.create("level4.png","level4.png", 0, 0); loadLevelFour.positionFromTopRight(buttonScaleFactor,0.05f); if (level4Unlocked) { @@ -385,17 +494,17 @@ function Start () { loadLevelFour.onTouchUp += upLevel4; loadLevelFour.onTouchDown += downLevel4; } - else {loadLevelFour.onTouchUpInside += DoNothing;} + else {loadLevelFour.onTouchUpInside += DoNothing;} loadLevelOne.hidden = true; loadLevelTwo.hidden = true; loadLevelThree.hidden = true; loadLevelFour.hidden = true; - + leftArrow = UIButton.create("chooselevelDown.png","chooselevelDown.png", 0, 0); leftArrow.positionFromTopLeft(buttonScaleFactor,0.2f); leftArrow.hidden = true; - + if (level2Unlocked == true) { leftArrow.onTouchUpInside += LevelSelect; leftArrow.onTouchDown += fadeInLeftArrow; @@ -410,20 +519,20 @@ function Start () { tiltWarning.hidden = true; rightArrow.hidden = true; - BackToPauseMenuButton.onTouchUpInside += BackToPauseMenu; + BackToPauseMenuButton.onTouchUpInside += BackToPauseMenu; BackToPauseMenuButton.hidden = true; - + loadingLabel = UIButton.create("loading.png","loading.png", 20, 20); loadingLabel.positionFromCenter(0f, 0f); loadingLabel.hidden = true; - + loadNewLevelButton = UIButton.create("newlevel.png","newlevel.png", 40, 40); loadNewLevelButton.positionFromBottomLeft(.05f, .05f); loadNewLevelButton.normalTouchOffsets = new UIEdgeOffsets( 30 ); loadNewLevelButton.highlightedTouchOffsets = new UIEdgeOffsets( 30 ); loadNewLevelButton.onTouchUpInside += LevelSelect; loadNewLevelButton.hidden = true; - + aboutButtonStart = UIButton.create("aboutDots.png","aboutDots.png", 40, 40); aboutButtonStart.normalTouchOffsets = new UIEdgeOffsets( 30 ); aboutButtonStart.highlightedTouchOffsets = new UIEdgeOffsets( 30 ); @@ -431,7 +540,7 @@ function Start () { //aboutButtonStart.pixelsFromTopRight ( 14, 14 ); aboutButtonStart.positionFromTopRight ( .05f, (.05f * screenAspectRatio) ); aboutButtonStart.onTouchUpInside += OpenAbout; -// aboutButtonStart.onTouchUp += fadeOutAbout; +// aboutButtonStart.onTouchUp += fadeOutAbout; // aboutButtonStart.onTouchDown += fadeInAbout; aboutButtonStart.hidden = true; @@ -439,7 +548,7 @@ function Start () { howToButton.normalTouchOffsets = new UIEdgeOffsets( 30 ); howToButton.highlightedTouchOffsets = new UIEdgeOffsets( 30 ); howToButton.centerize(); - //howToButton.pixelsFromTopLeft ( 14, 14 ); + //howToButton.pixelsFromTopLeft ( 14, 14 ); howToButton.positionFromTopLeft ( .05f, (.05f * screenAspectRatio) ); howToButton.onTouchUpInside += OpenHowTo; howToButton.hidden = true; @@ -459,7 +568,7 @@ function Start () { yield WaitForSeconds (1); canShowStart = true; // ShowStart(); - } +} function ShowStart() { tiltWarning.hidden = true; @@ -469,14 +578,27 @@ function ShowStart() { optionsButton.alphaFromTo(2.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); } if (level2Unlocked) {leftArrow.hidden = false;} - + rightArrow.hidden = false; aboutButtonStart.hidden = false; howToButton.hidden = false; + + if (!FallingLaunch.isTablet) { + vrModeButton.hidden = false; + vrModeButton.alphaFromTo( 2.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); + } + + if (FallingLaunch.NewGamePlus) { + appStoreButtonHomeBg.hidden = false; + appStoreButtonHomeText.hidden = false; + appStoreButtonHomeText.alphaFromTo( 3.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); + } + rightArrow.alphaFromTo( 2.0f, 0.0f, 0.4f, Easing.Sinusoidal.easeIn); leftArrow.alphaFromTo( 2.0f, 0.0f, 0.4f, Easing.Sinusoidal.easeIn); aboutButtonStart.alphaFromTo( 2.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); howToButton.alphaFromTo( 2.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); + canShowStart = false; //yield FixWrongInitialScreenOrientation(); } @@ -505,13 +627,13 @@ function DisplayTiltChooser () { flatTiltChooser.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); } - tiltText2.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); + tiltText2.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); } function CheckTiltAngle() { canShowStart = false; - + yield WaitForSeconds (.75); if ((Mathf.Abs(Input.acceleration.x) < .75) && (Mathf.Abs(Input.acceleration.y) < .75)) { ShowStart();} @@ -520,11 +642,11 @@ function CheckTiltAngle() { function ShowTiltWarning() { canShowStart = false; - + tiltWarning.hidden = false; tiltWarning.alphaFromTo( 0.25f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); yield WaitForSeconds (.75); - tiltWarning.alphaFromTo( 0.25f, 1.0f, 0.0f, Easing.Sinusoidal.easeOut); + tiltWarning.alphaFromTo( 0.25f, 1.0f, 0.0f, Easing.Sinusoidal.easeOut); yield WaitForSeconds (.5); canShowStart = true; } @@ -534,18 +656,24 @@ function Update () { if ((canShowStart == true) && (Mathf.Abs(Input.acceleration.x) < .7) && (Mathf.Abs(Input.acceleration.y) < .7)) { CheckTiltAngle(); bgCamera.backgroundColor = bgColor1; - } - else if (canShowStart == true) { - ShowTiltWarning(); - - var duration = 1.0; - - bgCamera.backgroundColor = Color.Lerp (bgColor1, bgColor2, 1.0); + } else if (canShowStart) { + + // Only show tilt warning and lerp to red if it's presumed to be the player's + // first-ish session (Application.loadedLevel == 2 connotes the tutorial level, + // so levelAchieved < 3 means they haven't completed that level): + // TODO: Would it be less annoying to only show this on the first-ever app launch? + if (FallingLaunch.levelAchieved < 3) { + ShowTiltWarning(); + bgCamera.backgroundColor = Color.Lerp (bgColor1, bgColor2, 1.0); + } else { + // just show the start menu immediately if the player has made enough progress: + ShowStart(); + } - //var t : float = Mathf.Repeat (Time.time, duration) / duration; - - //var t : float = Mathf.PingPong (Time.time, duration) / duration; - //bgCamera.backgroundColor = Color.Lerp (bgColor1, bgColor2, t); + // var duration = 1.0; + // var t : float = Mathf.Repeat (Time.time, duration) / duration; + // var t : float = Mathf.PingPong (Time.time, duration) / duration; + // bgCamera.backgroundColor = Color.Lerp (bgColor1, bgColor2, t); } // Debug.Log ("your input accel y is " + Input.acceleration.y + " and input accel x is " + Input.acceleration.x); @@ -558,13 +686,13 @@ function PauseGame() { if (level2Unlocked) {leftArrow.hidden = false;} loadNewLevelButton.hidden = false; bgSprite.hidden = false; - + savedTimeScale = Time.timeScale; // scriptName.GetComponent(FallingPlayer).FadeAudio (.09, FadeDir.Out); yield WaitForSeconds (.1); Time.timeScale = 0; AudioListener.pause = true; - FallingPlayer.isPausable = true; + FallingPlayer.isPausable = true; } } @@ -578,9 +706,9 @@ function UnPauseGame(resume : boolean) { rightArrow.hidden = true; leftArrow.hidden = true; loadNewLevelButton.hidden = true; - FallingPlayer.isPausable = resume; + FallingPlayer.isPausable = resume; } - + function IsGamePaused() { return Time.timeScale==0; } @@ -603,12 +731,12 @@ function LevelSelect() { loadLevelTwo.hidden = false; loadLevelThree.hidden = false; loadLevelFour.hidden = false; - + HideStartMenuElements(); ShowBackButton(); fadeInLoadNewLevels(); - + loadNewLevelButton.hidden = true; } @@ -620,9 +748,15 @@ function BackToPauseMenu() { aboutButtonStart.alphaFromTo( 1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); howToButton.alphaFromTo( 1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); - + + if (!FallingLaunch.isTablet) { + vrModeLaunchButton.hidden = true; + vrExplanatoryText.hidden = true; + vrModeButton.hidden = false; + } + fadeInPauseMenu(); - + loadLevelOne.hidden = true; loadLevelTwo.hidden = true; loadLevelThree.hidden = true; @@ -637,6 +771,14 @@ function BackToPauseMenu() { text3.hidden = true; openSiteButtonText.hidden = true; + appStoreButtonBg.hidden = true; + appStoreButtonText.hidden = true; + + if (FallingLaunch.NewGamePlus) { + appStoreButtonHomeBg.hidden = false; + appStoreButtonHomeText.hidden = false; + } + HideOptions(); // if (PlayerPrefs.HasKey("LatestLevel")) { @@ -662,19 +804,26 @@ function FadeAudio (timer : float) { } function ResumeGame() { + // This means we just beat the game, and are now continuing via menu: + if (FallingLaunch.NewGamePlus && PlayerPrefs.GetString("LatestLevel") == level4) { + StartLevelLoad(level1); + } if (PlayerPrefs.HasKey("LatestLevel")) { StartLevelLoad(PlayerPrefs.GetString("LatestLevel")); - } - else { + } else if (FallingLaunch.isVRMode) { + StartLevelLoad(level1); + } else { + // Only show tilt options if if's the player's + // first session and they're not in VR mode: ShowTiltNeutralOptions(); } } function ToggleTiltNeutral () { if (TogglingTiltNeutral == false) { - + TogglingTiltNeutral = true; - + if (PlayerPrefs.GetInt("TiltNeutral", 0) == 1) { fallingLaunchComponent.ChangeTilt(2); flatTiltChooser.hidden = true; @@ -686,7 +835,7 @@ function ToggleTiltNeutral () { flatTiltChooser.hidden = false; angledTiltChooser.hidden = true; verticalTiltChooser.hidden = true; - } + } else { fallingLaunchComponent.ChangeTilt(1); flatTiltChooser.hidden = true; @@ -701,48 +850,48 @@ function ToggleTiltNeutral () { function FlatTiltNeutral () { if (TogglingTiltNeutral == false) { - + TogglingTiltNeutral = true; - + fallingLaunchComponent.ChangeTilt(0); flatTiltLabel.hidden = false; angledTiltLabel.hidden = true; verticalTiltLabel.hidden = true; TogglingTiltNeutral = false; - + fadeAndLoad(0); } } function AngledTiltNeutral () { if (TogglingTiltNeutral == false) { - + TogglingTiltNeutral = true; - + fallingLaunchComponent.ChangeTilt(1); angledTiltLabel.hidden = false; flatTiltLabel.hidden = true; verticalTiltLabel.hidden = true; TogglingTiltNeutral = false; - + fadeAndLoad(1); } } function VerticalTiltNeutral () { if (TogglingTiltNeutral == false) { - + TogglingTiltNeutral = true; - + fallingLaunchComponent.ChangeTilt(2); angledTiltLabel.hidden = true; flatTiltLabel.hidden = true; verticalTiltLabel.hidden = false; TogglingTiltNeutral = false; - + fadeAndLoad(2); } } @@ -765,29 +914,30 @@ function fadeAndLoad (flatNeutral : int) { } yield WaitForSeconds (1.0f); - + StartLevelLoad(level1); //below logic unnecessary for one-time fade and load check // if (PlayerPrefs.HasKey("LatestLevel")) { // StartLevelLoad(PlayerPrefs.GetString("LatestLevel")); // } - // else { + // else { // StartLevelLoad(level1); // } } function ShowTiltNeutralOptions () { + // yield FadeOutLevelButtons (fadeTime/2); + yield FadeOutAllStartMenuElements(fadeTime/2); + // yield WaitForSeconds(fadeTime/2) + HideStartMenuElements(); + flatTiltLabel.hidden = false; angledTiltLabel.hidden = false; // verticalTiltLabel.hidden = false; tiltText1.hidden = false; - rightArrow.hidden = true; - leftArrow.hidden = true; - aboutButtonStart.hidden = true; - howToButton.hidden = true; - optionsButton.hidden = true; + tiltText1.alphaFromTo(1.0f, 0.0f, 0.8f, Easing.Sinusoidal.easeOut); flatTiltLabel.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeOut); angledTiltLabel.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeOut); @@ -798,24 +948,43 @@ function ShowTiltNeutralOptions () { function StartLevelLoad(levelName: String) { //yield StopCompensatingSensors(); fallingLaunchComponent.Calibrate(); + if (aboutToLoad == false) { aboutToLoad = true; FadeAudio (fadeTime); - + yield FadeOutLevelButtons (fadeTime/2); yield WaitForSeconds(fadeTime); - + FallingLaunch.hasSetAccel = false; Application.LoadLevel(levelName); } } function FadeOutLevelButtons(timer : float) { + BackToPauseMenuButton.hidden = true; - loadLevelOne.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); - loadLevelTwo.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); - loadLevelThree.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); - loadLevelFour.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); + yield FadeOutAllStartMenuElements(timer); + // yield WaitForSeconds(timer); + + loadLevelOne.hidden = true; + loadLevelTwo.hidden = true; + loadLevelThree.hidden = true; + loadLevelFour.hidden = true; + + HideStartMenuElements(); + + loadingLabel.hidden = false; + loadingLabel.alphaFromTo(.5, 0.0f, 1.0f, Easing.Quartic.easeIn); + yield WaitForSeconds(.5); + +} + +function FadeOutAllStartMenuElements(timer: float) { + loadLevelOne.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); + loadLevelTwo.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); + loadLevelThree.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); + loadLevelFour.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); rightArrow.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); leftArrow.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); angledTiltChooser.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); @@ -824,22 +993,21 @@ function FadeOutLevelButtons(timer : float) { aboutButtonStart.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); howToButton.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); optionsButton.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); - - yield WaitForSeconds(timer); - - loadLevelOne.hidden = true; - loadLevelTwo.hidden = true; - loadLevelThree.hidden = true; - loadLevelFour.hidden = true; - HideStartMenuElements(); - - loadingLabel.hidden = false; - loadingLabel.alphaFromTo(.5, 0.0f, 1.0f, Easing.Quartic.easeIn); - yield WaitForSeconds(.5); - + if (FallingLaunch.NewGamePlus) { + appStoreButtonHomeText.alphaTo(timer, 0.0, Easing.Sinusoidal.easeOut); + } + + if (!FallingLaunch.isTablet) { + vrModeButton.alphaTo(timer, 0.0f, Easing.Sinusoidal.easeOut); + vrModeLaunchButton.alphaTo(timer, 0.0, Easing.Sinusoidal.easeOut); + vrExplanatoryText.alphaTo(timer, 0.0, Easing.Sinusoidal.easeOut); + } + + yield; } + function OpenHowTo() { HideStartMenuElements(); @@ -847,24 +1015,73 @@ function OpenHowTo() { helpIcon1.hidden = false; helpIcon2.hidden = false; - helpIcon3.hidden = false; + helpIcon3.hidden = false; helpIcon1.alphaFromTo(.5f, 0.0f, 0.9f, Easing.Sinusoidal.easeOut); helpIcon2.alphaFromTo(.75f, 0.0f, 0.9f, Easing.Sinusoidal.easeInOut); helpIcon3.alphaFromTo(1.5f, 0.0f, 0.9f, Easing.Sinusoidal.easeInOut); } function OpenAbout() { - + HideStartMenuElements(); ShowBackButton(); + + appStoreButtonBg.hidden = false; + appStoreButtonText.hidden = false; openSiteButtonText.hidden = false; text1.hidden = false; text2.hidden = false; text3.hidden = false; - text1.alphaFromTo(1.0f, 0.0f, 0.8f, Easing.Sinusoidal.easeOut); - text2.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeOut); - text3.alphaFromTo(1.5f, 0.0f, 0.6f, Easing.Sinusoidal.easeInOut); + text1.alphaFromTo(1.0, 0.0, 0.8, Easing.Sinusoidal.easeOut); + text2.alphaFromTo(1.0, 0.0, 1.0, Easing.Sinusoidal.easeOut); + text3.alphaFromTo(1.5, 0.0, 0.6, Easing.Sinusoidal.easeInOut); + appStoreButtonText.alphaFromTo(2.5, 0.0, 1.0, Easing.Sinusoidal.easeIn); +} + +function OpenVRModeMenu() { + // This user shouldn't be able to trigger this OpenVRModeMenu + // function on a tablet, but just to be safe... + if (!FallingLaunch.isTablet) { + FallingLaunch.Analytics.Event( + "VRModeMenuOpen:" + FallingLaunch.vrModeAnalyticsString + + Screen.orientation, + FallingLaunch.levelAchieved + ); + + HideStartMenuElements(); + ShowBackButton(); + + vrExplanatoryText.hidden = false; + vrModeLaunchButton.hidden = false; + vrExplanatoryText.alphaFromTo(1.0f, 0.0f, 0.8f, Easing.Sinusoidal.easeOut); + vrModeLaunchButton.alphaFromTo( 1.0f, 0.0f, 0.4f, Easing.Sinusoidal.easeInOut); + } else { + return; + } +} + +function LaunchVRMode() { + fallingLaunchComponent.EnableVRMode(); + + FallingLaunch.Analytics.Event( + "VRModeEnter:" + FallingLaunch.vrModeAnalyticsString + + Screen.orientation, + FallingLaunch.levelAchieved + ); + + // NB: If your phone is tilted a little beyond flat (away from you) on level load, + // then all other game objects will be behind you when you look up: 180deg wrong + // in the Z direction (e.g. 90 vs -90 (aka 270) degrees). May need to apply an inverse + // quaternion in some cases based on Head gaze direction/ gameObj position, + // or in the menu UI, ensure the phone orientation is not flat before + // letting the user load the scene. + + // HACK: But as a temporary workaround, force landscape left orientation + // in VR for Cardboard compatibility (Google's SDK also enforces this mode + // with 'tilt your phone' UI when device is in landscape right): + fallingLaunchComponent.LockLandscapeLeftOrientation(FallingLaunch.isVRMode); + ResumeGame(); } function ShowOptions() { @@ -887,8 +1104,8 @@ function HideOptions() { angledTiltChooser.hidden = true; flatTiltChooser.hidden = true; verticalTiltChooser.hidden = true; - - if (PlayerPrefs.HasKey("LatestLevel")) { + + if (PlayerPrefs.HasKey("LatestLevel")) { optionsButton.hidden = false; optionsButton.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeOut); } @@ -901,10 +1118,10 @@ function fadeInOptions() { tiltText2.hidden = false; invertHorizAxisText.hidden = false; invertVertAxisText.hidden = false; - + invertHorizAxisText.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); invertVertAxisText.alphaFromTo(1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); - + if (FallingLaunch.invertVertAxisVal == -1) { invertVertAxisTextNo.hidden = true; invertVertAxisTextYes.hidden = false; @@ -926,7 +1143,7 @@ function fadeInOptions() { invertHorizAxisTextYes.hidden = true; invertHorizAxisTextNo.alphaFromTo(1.0f, 0.0f, 0.4f, Easing.Sinusoidal.easeIn); } - + } function SaveAxesPrefs( invert : int) { @@ -985,7 +1202,11 @@ function HideStartMenuElements() { aboutButtonStart.hidden = true; howToButton.hidden = true; optionsButton.hidden = true; - + + vrModeButton.hidden = true; + + appStoreButtonHomeBg.hidden = true; + appStoreButtonHomeText.hidden = true; //angledTiltChooser.hidden = true; //flatTiltChooser.hidden = true; } @@ -1016,7 +1237,17 @@ function LoadLevel4ViaStart() { } function OpenFallingSite() { - Application.OpenURL ("http://tysonkubota.net/skydrift?utm_source=skydrift-game&utm_medium=ios&utm_campaign=skydrift-gui"); + var urlToOpen : String = "http://tysonkubota.net/skydrift?utm_source=skydrift-game&utm_medium=ios&utm_campaign=skydrift-gui"; + // use a float instead of an int, as required by the GameAnalytics SDK: + FallingLaunch.Analytics.Event("OpenURL:FallingSite", FallingLaunch.levelAchieved*1.0); + Application.OpenURL(urlToOpen); +} + +function OpenAppStorePage() { + var urlToOpen : String = "https://itunes.apple.com/us/app/skydrift/id728636851?action=write-review&mt=8"; + // use a float instead of an int, as required by the GameAnalytics SDK: + FallingLaunch.Analytics.Event("OpenURL:AppStorePage", FallingLaunch.levelAchieved*1.0); + Application.OpenURL(urlToOpen); } function HideGUI() { @@ -1044,159 +1275,86 @@ function fadeOutLeftArrow() { leftArrow.alphaTo(.25f, 0.4f, Easing.Sinusoidal.easeOut); } +function fadeInVRLaunchButton() { + vrModeLaunchButton.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); +} + +function fadeOutVRLaunchButton() { + vrModeLaunchButton.alphaTo(.25f, 0.4f, Easing.Sinusoidal.easeOut); +} + function fadeInLoadNewLevels() { loadLevelOne.alphaFromTo(.5f, 0.0f, 0.4f, Easing.Sinusoidal.easeOut); - if (level2Unlocked) {loadLevelTwo.alphaFromTo(.5f, 0.0f, 0.4f, Easing.Sinusoidal.easeOut);} + if (level2Unlocked) {loadLevelTwo.alphaFromTo(.5f, 0.0f, 0.4f, Easing.Sinusoidal.easeOut);} else {loadLevelTwo.alphaFromTo(.25f, 0.0f, 0.05f, Easing.Sinusoidal.easeOut);} if (level3Unlocked) {loadLevelThree.alphaFromTo(.5f, 0.0f, 0.4f, Easing.Sinusoidal.easeOut);} else {loadLevelThree.alphaFromTo(.25f, 0.0f, 0.05f, Easing.Sinusoidal.easeOut);} - + if (level4Unlocked) {loadLevelFour.alphaFromTo(.5f, 0.0f, 0.4f, Easing.Sinusoidal.easeOut);} else {loadLevelFour.alphaFromTo(.25f, 0.0f, 0.05f, Easing.Sinusoidal.easeOut);} } function fadeInPauseMenu() { - rightArrow.alphaFromTo( 0.5f, 0.0f, 0.4f, Easing.Sinusoidal.easeInOut); - leftArrow.alphaFromTo( 0.5f, 0.0f, 0.4f, Easing.Sinusoidal.easeInOut); - aboutButtonStart.alphaFromTo( 0.5f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); - howToButton.alphaFromTo( 0.5f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); + rightArrow.alphaFromTo( 0.5, 0.0, 0.4, Easing.Sinusoidal.easeInOut); + leftArrow.alphaFromTo( 0.5, 0.0, 0.4, Easing.Sinusoidal.easeInOut); + aboutButtonStart.alphaFromTo( 0.5, 0.0, 1.0, Easing.Sinusoidal.easeIn); + howToButton.alphaFromTo( 0.5, 0.0, 1.0, Easing.Sinusoidal.easeIn); + + if (!FallingLaunch.isTablet) { + vrModeButton.alphaFromTo( 0.5, 0.0, 1.0, Easing.Sinusoidal.easeIn); + } + + if (FallingLaunch.NewGamePlus) { + appStoreButtonHomeText.alphaFromTo( 1.0, 0.0, 1.0, Easing.Sinusoidal.easeIn); + } } function downLevel1() { if (aboutToLoad == false) { - loadLevelOne.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); + loadLevelOne.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); } } function downLevel2() { if (aboutToLoad == false) { - loadLevelTwo.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); + loadLevelTwo.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); } } function downLevel3() { if (aboutToLoad == false) { - loadLevelThree.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); + loadLevelThree.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); } } function downLevel4() { if (aboutToLoad == false) { - loadLevelFour.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); + loadLevelFour.alphaTo(.05f, 1.0f, Easing.Sinusoidal.easeOut); } } - function upLevel1() { if (aboutToLoad == false) { - loadLevelOne.alphaTo(.25f, 0.8f, Easing.Sinusoidal.easeOut); + loadLevelOne.alphaTo(.25f, 0.8f, Easing.Sinusoidal.easeOut); } } function upLevel2() { if (aboutToLoad == false) { - loadLevelTwo.alphaTo(.25f, 0.8f, Easing.Sinusoidal.easeOut); + loadLevelTwo.alphaTo(.25f, 0.8f, Easing.Sinusoidal.easeOut); } } function upLevel3() { if (aboutToLoad == false) { - loadLevelThree.alphaTo(.25f, 0.8f, Easing.Sinusoidal.easeOut); + loadLevelThree.alphaTo(.25f, 0.8f, Easing.Sinusoidal.easeOut); } } function upLevel4() { if (aboutToLoad == false) { - loadLevelFour.alphaTo(.25f, 0.8f, Easing.Sinusoidal.easeOut); + loadLevelFour.alphaTo(.25f, 0.8f, Easing.Sinusoidal.easeOut); } } - -function SetOrientationNow() { - if (Input.deviceOrientation == DeviceOrientation.LandscapeRight) { - Screen.orientation = ScreenOrientation.LandscapeRight; - FallingLaunch.flipMultiplier = -1; - Debug.Log("I'm in LandscapeRight!"); - FallingLaunch.neutralPosTilted = FallingLaunch.neutralPosTiltedFlipped; - } - else if (Input.deviceOrientation == DeviceOrientation.LandscapeLeft){ - Screen.orientation = ScreenOrientation.LandscapeLeft; - FallingLaunch.flipMultiplier = 1; - Debug.Log("I'm in LandscapeLeft, or Portrait, or FaceDown/Up!"); - FallingLaunch.neutralPosTilted = FallingLaunch.neutralPosTiltedRegular; - } - - //this is necessary to override Unity 4's auto-orientation code - Input.compensateSensors = false; - yield; - return; -} - - -function FixWrongInitialScreenOrientation () { - if ( (Screen.height > Screen.width && Input.deviceOrientation.ToString().ToLower().StartsWith("landscape")) - || (Screen.width > Screen.height && Input.deviceOrientation.ToString().ToLower().StartsWith("portrait")) - ) { - Debug.LogWarning("Fixing wrong screen orientation ("+ Screen.orientation +") to right device orientation: "+ Input.deviceOrientation); - switch (Input.deviceOrientation) { - case DeviceOrientation.LandscapeLeft: - Screen.orientation = ScreenOrientation.LandscapeLeft; - break; - case DeviceOrientation.LandscapeRight: - Screen.orientation = ScreenOrientation.LandscapeRight; - break; - case DeviceOrientation.PortraitUpsideDown: - Screen.orientation = ScreenOrientation.PortraitUpsideDown; - break; - case DeviceOrientation.Portrait: - Screen.orientation = ScreenOrientation.Portrait; - break; - } - } - yield; -} - -function AutoOrientToLandscape () { - - // if (Input.deviceOrientation == DeviceOrientation.FaceUp) { - // if (Screen.orientation == ScreenOrientation.LandscapeRight) { - // Debug.Log("Device is FaceUp, and ScreenOrientation is LandscapeRight"); - // FallingLaunch.flipMultiplier = FallingLaunch.flipMultiplier * -1; - // FallingLaunch.neutralPosTilted = FallingLaunch.neutralPosTiltedFlipped; - // } - // else { - // Debug.Log("Device is FaceUp, and ScreenOrientation is NOT LandscapeRight"); - // FallingLaunch.flipMultiplier = FallingLaunch.flipMultiplier * 1; - // FallingLaunch.neutralPosTilted = FallingLaunch.neutralPosTiltedRegular; - // } - - // Screen.autorotateToLandscapeRight = false; - // Screen.autorotateToLandscapeLeft = false; - // Screen.autorotateToPortrait = false; - // Screen.autorotateToPortraitUpsideDown = false; - - // } - - if (Vector3.Dot(Input.acceleration.normalized, Vector3(1,0,0)) > 0) - //else if (Input.deviceOrientation == DeviceOrientation.LandscapeRight) - { - Screen.orientation = ScreenOrientation.LandscapeRight; - FallingLaunch.flipMultiplier = FallingLaunch.flipMultiplier * -1; - FallingLaunch.neutralPosTilted = FallingLaunch.neutralPosTiltedFlipped; - } - else if(Vector3.Dot(Input.acceleration.normalized, Vector3(-1,0,0)) > 0) - //else if (Input.deviceOrientation == DeviceOrientation.LandscapeLeft) - { - Screen.orientation = ScreenOrientation.LandscapeLeft; - FallingLaunch.flipMultiplier = FallingLaunch.flipMultiplier * 1; - FallingLaunch.neutralPosTilted = FallingLaunch.neutralPosTiltedRegular; - } - FallingLaunch.hasSetOrientation = true; -} - -function StopCompensatingSensors() { - //this is necessary to override Unity 4's auto-orientation code - Input.compensateSensors = false; - yield; -} \ No newline at end of file diff --git a/fallingUITest.js b/fallingUITest.js index af049e2..796c00c 100644 --- a/fallingUITest.js +++ b/fallingUITest.js @@ -8,7 +8,7 @@ var fallingLaunchComponent : FallingLaunch; var value : float = 0.5f; var bgSprite : UISprite; //static var tutorialSprite : UISprite; -static var tutorialSpriteExtraTimer : float = 0; +static var tutorialSpriteExtraTimer : float = 0; var fadeSprite : UISprite; var pauseButton : UIButton; var circleReticle: UIButton; @@ -16,7 +16,6 @@ var lifeBarOutline : UIProgressBar; var lifeBar : UIProgressBar; var lifeBarThreat : UIProgressBar; var rightArrow : UIButton; -var leftArrow : UIButton; var loadNewLevelButton : UIButton; var loadLevelOne : UIButton; var loadLevelTwo : UIButton; @@ -74,31 +73,49 @@ var level4Unlocked : boolean = false; static var holdingPauseButton : boolean = false; static var origPauseButtonArea : Rect; -private var savedTimeScale:float; +private var savedTimeScale : float; //var x:float; //var y:float; // private var lifeBar = UIProgressBar.create( "lifeBarRedTest.png", 0, 0 ); function Awake () { + ScreenH = Screen.height; + ScreenW = Screen.width; screenAspectRatio = (ScreenH / ScreenW); } function Start () { // yield WaitForSeconds(0.5f); -// Testing to see if disabling this hard coded screen.orientation will allow auto detection of landscape +// Testing to see if disabling this hard coded screen.orientation will allow auto detection of landscape // right or left mode on startup. // Screen.orientation = ScreenOrientation.LandscapeLeft; // if (iPhoneInput.orientation == iPhoneOrientation.LandscapeRight) { // Screen.orientation = ScreenOrientation.LandscapeRight;} // else {Screen.orientation = ScreenOrientation.LandscapeLeft;} - + fallingPlayerComponent = player.GetComponent("FallingPlayer"); //moveControllerComponent = player.GetComponent("MoveController"); fallingLaunch = GameObject.Find("LaunchGameObject"); fallingLaunchComponent = fallingLaunch.GetComponent("FallingLaunch"); - + + // VR mode is incompatible with orthographic cameras, and thus doesn't use UI Toolkit. + if (!FallingLaunch.isVRMode) { + SetupLevelUI(); + } else { + FallingLaunch.Analytics.Event( + "LevelBegin:" + + FallingLaunch.vrModeAnalyticsString + + SceneManagement.SceneManager.GetActiveScene().name + ":" + + FallingLaunch.thisLevelArea, + FallingLaunch.secondsInLevel + ); + return; + } +} + +function SetupLevelUI() { bgSprite = UIT.firstToolkit.addSprite( "menuBackground.png", 0, 0, 2 ); bgSprite.positionCenter(); bgSprite.scaleTo( 0.01f, new Vector3( (Screen.width * 6), (Screen.height * 6), 1 ), Easing.Linear.easeIn); @@ -106,8 +123,7 @@ function Start () { bgSprite.hidden = true; //Debug.Log("your highest level achieved is " + FallingLaunch.levelAchieved); - if (FallingLaunch.levelAchieved == 5) { - //loadLevelTwo.alphaTo(0.01f, 0.0f, Easing.Sinusoidal.easeOut); + if (FallingLaunch.debugMode || FallingLaunch.levelAchieved == 5) { level2Unlocked = true; level3Unlocked = true; level4Unlocked = true; @@ -115,15 +131,9 @@ function Start () { else if (FallingLaunch.levelAchieved == 4) { level2Unlocked = true; level3Unlocked = true; - } - else if (FallingLaunch.levelAchieved == 3) { - level2Unlocked = true; } - - if (FallingLaunch.debugMode) { + else if (FallingLaunch.levelAchieved == 3) { level2Unlocked = true; - level3Unlocked = true; - level4Unlocked = true; } var tiltPlacementRatio : float; @@ -141,7 +151,7 @@ function Start () { boldText = new UIText( "font-bold", "font-bold.png" ); thinText = new UIText( "font-thin", "font-thin.png" ); - + boldText.alignMode = UITextAlignMode.Center; boldText.verticalAlignMode = UITextVerticalAlignMode.Middle; boldText.wrapMode = UITextLineWrapMode.MinimumLength; @@ -150,12 +160,12 @@ function Start () { thinText.verticalAlignMode = UITextVerticalAlignMode.Middle; thinText.wrapMode = UITextLineWrapMode.None; - + // var tutorialHeight = 1.25 * spriteEdgeSize; // tutorialSprite = UIT.firstToolkit.addSprite( "tutorialBackground.png", 0, 0, 4 ); // tutorialSprite.hidden = true; // tutorialSprite.scaleTo( 0.1f, new Vector3( (Screen.width), 3, 1 ), Easing.Sinusoidal.easeOut); - + fadeSprite = UIT.firstToolkit.addSprite( "menuBackgroundBlack.png", 0, 0, -1 ); fadeSprite.positionCenter(); fadeSprite.scaleTo( 0.01f, new Vector3( (Screen.width * 6), (Screen.height * 6), 1 ), Easing.Linear.easeIn); @@ -175,19 +185,14 @@ function Start () { rightArrow.positionFromTopRight(buttonScaleFactor,0.2f); rightArrow.onTouchUpInside += PauseGameCheck; - leftArrow = UIButton.create("restart.png","restart.png", 0, 0); - leftArrow.positionFromBottomLeft(.05f, .05f); - leftArrow.onTouchUpInside += RestartLevel; - rightArrow.hidden = true; - leftArrow.hidden = true; - + BackToPauseMenuButton = UIButton.create("back.png","back.png", 40, 40); BackToPauseMenuButton.positionFromBottomLeft ( .05f, (.05f * screenAspectRatio) ); //BackToPauseMenuButton.pixelsFromBottomLeft ( 14, 14 ); BackToPauseMenuButton.normalTouchOffsets = new UIEdgeOffsets( 30 ); - BackToPauseMenuButton.highlightedTouchOffsets = new UIEdgeOffsets( 30 ); - BackToPauseMenuButton.onTouchUpInside += BackToPauseMenu; + BackToPauseMenuButton.highlightedTouchOffsets = new UIEdgeOffsets( 30 ); + BackToPauseMenuButton.onTouchUpInside += BackToPauseMenu; BackToPauseMenuButton.hidden = true; BackToHomeMenuButton = UIButton.create("homeArrows.png","homeArrows.png", 40, 40); @@ -202,36 +207,52 @@ function Start () { nextLevelLabel = UIT.firstToolkit.addSprite( "level2.png", 0, 0, 0 ); } else if (level2 == SceneManagement.SceneManager.GetActiveScene().name) { - nextLevelLabel = UIT.firstToolkit.addSprite( "level3.png", 0, 0, 0 ); + nextLevelLabel = UIT.firstToolkit.addSprite( "level3.png", 0, 0, 0 ); } else if (level3 == SceneManagement.SceneManager.GetActiveScene().name) { - nextLevelLabel = UIT.firstToolkit.addSprite( "level4.png", 0, 0, 0 ); + nextLevelLabel = UIT.firstToolkit.addSprite( "level4.png", 0, 0, 0 ); } else if (level4 == SceneManagement.SceneManager.GetActiveScene().name) { - nextLevelLabel = UIT.firstToolkit.addSprite( "level1.png", 0, 0, 0 ); + nextLevelLabel = UIT.firstToolkit.addSprite( "level1.png", 0, 0, 0 ); } //nextLevelLabel.positionFromCenter(.0f); nextLevelLabel.positionCenter(); nextLevelLabel.hidden = true; + var calculatedMiddleIconRatio : float = 0.0f; + + if (ScreenW > 2200) { + calculatedMiddleIconRatio = 0.36f; + } else if (ScreenW > 1600) { + calculatedMiddleIconRatio = 0.33f; + } else if (ScreenW > 1200) { + calculatedMiddleIconRatio = 0.32f; + } else if (ScreenW > 1000) { + calculatedMiddleIconRatio = 0.31f; + } else { + calculatedMiddleIconRatio = 0.3f; + } + + var middleIconAdjustRatio : float = UIT.isHD ? calculatedMiddleIconRatio : 0.3f; + if (level1 == SceneManagement.SceneManager.GetActiveScene().name) { loadLevelOne = UIButton.create("level1.png","level1.png", 0, 0); loadLevelOne.alphaTo( 0.01f, 0.75f, Easing.Sinusoidal.easeOut); } - else { + else { loadLevelOne = UIButton.create("level1.png","level1.png", 0, 0); loadLevelOne.alphaTo( 0.01f, 0.4f, Easing.Sinusoidal.easeOut); } loadLevelOne.positionFromTopLeft(buttonScaleFactor,0.05f); loadLevelOne.onTouchUpInside += LoadLevel1ViaMenu; - + if (level2 == SceneManagement.SceneManager.GetActiveScene().name) { loadLevelTwo = UIButton.create("level2.png","level2.png", 0, 0); loadLevelTwo.alphaTo( 0.01f, 0.75f, Easing.Sinusoidal.easeOut); loadLevelTwo.onTouchUpInside += LoadLevel2ViaMenu; } - else { + else { loadLevelTwo = UIButton.create("level2.png","level2.png", 0, 0); if (level2Unlocked == false) { loadLevelTwo.alphaTo( 0.01f, 0.05f, Easing.Sinusoidal.easeOut); @@ -241,14 +262,14 @@ function Start () { loadLevelTwo.onTouchUpInside += LoadLevel2ViaMenu; } } - loadLevelTwo.positionFromTopLeft(buttonScaleFactor,0.3f); - + loadLevelTwo.positionFromTopLeft(buttonScaleFactor, middleIconAdjustRatio); + if (level3 == SceneManagement.SceneManager.GetActiveScene().name) { loadLevelThree = UIButton.create("level3.png","level3.png", 0, 0); loadLevelThree.alphaTo( 0.01f, 0.75f, Easing.Sinusoidal.easeOut); loadLevelThree.onTouchUpInside += LoadLevel3ViaMenu; } - else { + else { loadLevelThree = UIButton.create("level3.png","level3.png", 0, 0); if (level3Unlocked == false) { loadLevelThree.alphaTo( 0.01f, 0.05f, Easing.Sinusoidal.easeOut); @@ -258,14 +279,14 @@ function Start () { loadLevelThree.onTouchUpInside += LoadLevel3ViaMenu; } } - loadLevelThree.positionFromTopRight(buttonScaleFactor,0.3f); - + loadLevelThree.positionFromTopRight(buttonScaleFactor, middleIconAdjustRatio); + if (level4 == SceneManagement.SceneManager.GetActiveScene().name) { loadLevelFour = UIButton.create("level4.png","level4.png", 0, 0); loadLevelFour.alphaTo( 0.01f, 0.75f, Easing.Sinusoidal.easeOut); loadLevelFour.onTouchUpInside += LoadLevel4ViaMenu; } - else { + else { loadLevelFour = UIButton.create("level4.png","level4.png", 0, 0); if (level4Unlocked == false) { loadLevelFour.alphaTo( 0.01f, 0.05f, Easing.Sinusoidal.easeOut); @@ -281,11 +302,11 @@ function Start () { loadLevelTwo.hidden = true; loadLevelThree.hidden = true; loadLevelFour.hidden = true; - + loadingLabel = UIButton.create("loading.png","loading.png", 20, 20); loadingLabel.positionCenter(); loadingLabel.hidden = true; - + loadNewLevelButton = UIButton.create("chooselevel.png","chooselevelDown.png", 40, 40); loadNewLevelButton.positionFromTopLeft(buttonScaleFactor,0.2f); loadNewLevelButton.normalTouchOffsets = new UIEdgeOffsets( 30 ); @@ -311,8 +332,8 @@ function Start () { tiltText2.verticalAlignMode = UITextVerticalAlignMode.Bottom; tiltText2.positionFromRight( -.16f, .52f ); tiltText2.hidden = true; - //public UITextInstance addTextInstance( string text, float xPos, float yPos, - //float scale, int depth, Color color, UITextAlignMode alignMode, UITextVerticalAlignMode verticalAlignMode ) + //public UITextInstance addTextInstance( string text, float xPos, float yPos, + //float scale, int depth, Color color, UITextAlignMode alignMode, UITextVerticalAlignMode verticalAlignMode ) invertHorizAxisText = thinText.addTextInstance( "HORIZONTAL AXIS", 0, 0 ); invertHorizAxisText.verticalAlignMode = UITextVerticalAlignMode.Bottom; invertHorizAxisText.positionFromRight( .00f, .52f ); @@ -363,7 +384,7 @@ function Start () { angledTiltLabel = UIButton.create("neutralAngle45.png","neutralAngle45.png", 0, 0 ); angledTiltLabel.normalTouchOffsets = new UIEdgeOffsets( 30 ); angledTiltLabel.highlightedTouchOffsets = new UIEdgeOffsets( 30 ); - angledTiltLabel.positionFromLeft( -.16f, .52f ); + angledTiltLabel.positionFromLeft( -.16f, .52f ); angledTiltLabel.onTouchUpInside += ToggleTiltNeutral; angledTiltLabel.hidden = true; @@ -384,7 +405,7 @@ function Start () { circleReticle = UIButton.create("circle-reticle.png","circle-reticle.png", 0, 0); circleReticle.positionCenter(); - + lifeBarOutline = UIProgressBar.create( "lifeBarOutline.png", 0, 0 ); lifeBarOutline.pixelsFromTopLeft ( 8, 8 ); lifeBarOutline.value = 1f; @@ -398,40 +419,65 @@ function Start () { // animateThreatBar (lifeBarThreat); lifeBarThreat.hidden = true; lifeBarThreat.alphaFromTo( 0.01f, 0f, 0f, Easing.Sinusoidal.easeOut); - + lifeBar = UIProgressBar.create( "lifeBarWhite.png", 0, 0 ); lifeBar.pixelsFromTopLeft ( 10, 10 ); lifeBar.resizeTextureOnChange = true; - lifeBar.value = 0.67f; + lifeBar.value = 0.67f; animateProgressBar (lifeBar); // Loop (); - // GA.API.Design.NewEvent("LevelBegin:" + SceneManagement.SceneManager.GetActiveScene().name + ":" + FallingLaunch.thisLevelArea, FallingLaunch.secondsInLevel, transform.parent.position); + FallingLaunch.Analytics.Event( + "LevelBegin:" + FallingLaunch.vrModeAnalyticsString + + SceneManagement.SceneManager.GetActiveScene().name + ":" + + FallingLaunch.thisLevelArea, + FallingLaunch.secondsInLevel + ); + // Analytics reporting for tilt prefs, and horizontal/vertical axis prefs, respectively: if (FallingLaunch.restPosition == FallingLaunch.neutralPosFlat) { - // GA.API.Design.NewEvent("TiltPreference:" + SceneManagement.SceneManager.GetActiveScene().name, 0.0f, transform.parent.position); - } - else if (FallingLaunch.restPosition == FallingLaunch.neutralPosVertical) { - // GA.API.Design.NewEvent("TiltPreference:" + SceneManagement.SceneManager.GetActiveScene().name, 90.0f, transform.parent.position); - } - else { - // GA.API.Design.NewEvent("TiltPreference:" + SceneManagement.SceneManager.GetActiveScene().name, 45.0f, transform.parent.position); + FallingLaunch.Analytics.Event( + "TiltPreference:" + SceneManagement.SceneManager.GetActiveScene().name, + 0.0 + ); + } else if (FallingLaunch.restPosition == FallingLaunch.neutralPosVertical) { + FallingLaunch.Analytics.Event( + "TiltPreference:" + SceneManagement.SceneManager.GetActiveScene().name, + 90.0f + ); + } else { + FallingLaunch.Analytics.Event( + "TiltPreference:" + SceneManagement.SceneManager.GetActiveScene().name, + 45.0f + ); } + if (FallingLaunch.invertHorizAxisVal == 1) { - // GA.API.Design.NewEvent("AxesPreference:Horizontal:" + SceneManagement.SceneManager.GetActiveScene().name, 1.0f, transform.parent.position); + FallingLaunch.Analytics.Event( + "AxesPreference:Horizontal:" + SceneManagement.SceneManager.GetActiveScene().name, + 1.0f + ); + } else if (FallingLaunch.invertHorizAxisVal == -1) { + FallingLaunch.Analytics.Event( + "AxesPreference:Horizontal:" + SceneManagement.SceneManager.GetActiveScene().name, + -1.0f + ); } - else if (FallingLaunch.invertHorizAxisVal == -1) { - // GA.API.Design.NewEvent("AxesPreference:Horizontal:" + SceneManagement.SceneManager.GetActiveScene().name, -1.0f, transform.parent.position); - } - if (FallingLaunch.invertVertAxisVal == -1) { - // GA.API.Design.NewEvent("AxesPreference:Vertical:" + SceneManagement.SceneManager.GetActiveScene().name, -1.0f, transform.parent.position); - } - else if (FallingLaunch.invertVertAxisVal == 1) { - // GA.API.Design.NewEvent("AxesPreference:Vertical:" + SceneManagement.SceneManager.GetActiveScene().name, 1.0f, transform.parent.position); - } + if (FallingLaunch.invertVertAxisVal == -1) { + FallingLaunch.Analytics.Event( + "AxesPreference:Vertical:" + SceneManagement.SceneManager.GetActiveScene().name, + -1.0f + ); + } else if (FallingLaunch.invertVertAxisVal == 1) { + FallingLaunch.Analytics.Event( + "AxesPreference:Vertical:" + SceneManagement.SceneManager.GetActiveScene().name, + 1.0f + ); } +} + function animateProgressBar(lifeBar : UIProgressBar) { while (true) { @@ -443,49 +489,60 @@ function animateProgressBar(lifeBar : UIProgressBar) { } } -function animateThreatBar(lifeBar : UIProgressBar) { - while (true) - { - lifeBar.value = (1 - (parseFloat(ScoreController.visibleScore)/parseFloat(ScoreController.maxScore))); - yield 0; - } -} +// function animateThreatBar(lifeBar : UIProgressBar) { +// while (true) +// { +// lifeBar.value = (1 - (parseFloat(ScoreController.visibleScore)/parseFloat(ScoreController.maxScore))); +// yield 0; +// } +// } function flashProgressBar(delay : float) { - lifeBar.alphaTo( 0.01f, 1.0f, Easing.Sinusoidal.easeOut); - yield WaitForSeconds(.25); - lifeBar.alphaTo( delay, 0.5f, Easing.Sinusoidal.easeInOut); + if (!FallingLaunch.isVRMode) { + lifeBar.alphaTo( 0.01f, 1.0f, Easing.Sinusoidal.easeOut); + yield WaitForSeconds(.25); + lifeBar.alphaTo( delay, 0.5f, Easing.Sinusoidal.easeInOut); + } } function showThreatBar(delay : float) { - lifeBarThreat.hidden = false; - lifeBarThreat.alphaTo( delay, 0.25f, Easing.Sinusoidal.easeInOut); + if (!FallingLaunch.isVRMode) { + lifeBarThreat.hidden = false; + lifeBarThreat.alphaTo( delay, 0.25f, Easing.Sinusoidal.easeInOut); + } } function hideThreatBar(delay : float) { - lifeBarThreat.alphaTo( delay, 0.0f, Easing.Sinusoidal.easeInOut); + if (!FallingLaunch.isVRMode) { + lifeBarThreat.alphaTo( delay, 0.0f, Easing.Sinusoidal.easeInOut); + } } function flashThreatBar(delay : float) { - lifeBarThreat.hidden = false; - lifeBarThreat.alphaFromTo( delay, 1.0f, 0.0f, Easing.Sinusoidal.easeInOut); - yield WaitForSeconds(delay); -// lifeBarThreat.hidden = true; + if (!FallingLaunch.isVRMode) { + lifeBarThreat.hidden = false; + lifeBarThreat.alphaFromTo( delay, 1.0f, 0.0f, Easing.Sinusoidal.easeInOut); + yield WaitForSeconds(delay); + } } function PauseGame() { - if (FallingPlayer.isPausable == true) { + if (FallingPlayer.isPausable) { FallingPlayer.isPausable = false; - + FallingLaunch.secondsInLevel = (Time.time - FallingPlayer.levelStartTime); - // GA.API.Design.NewEvent("GUI:PauseGame:" + SceneManagement.SceneManager.GetActiveScene().name + ":" + FallingLaunch.thisLevelArea, FallingLaunch.secondsInLevel, transform.parent.position); + + FallingLaunch.Analytics.Event( + "GUI:PauseGame:" + SceneManagement.SceneManager.GetActiveScene().name + ":" + FallingLaunch.thisLevelArea, + FallingLaunch.secondsInLevel + ); //Debug.Log("you paused at " + transform.parent.position); - + circleReticle.hidden = true; lifeBar.hidden = true; lifeBarOutline.hidden = true; lifeBarThreat.hidden = true; - + origPauseButtonArea = MoveController.pauseButtonArea; MoveController.pauseButtonArea = Rect(0, 0, Screen.width, Screen.height); @@ -496,21 +553,19 @@ function PauseGame() { AudioListener.pause = true; rightArrow.hidden = false; - //leftArrow.hidden = false; if (level2Unlocked) {loadNewLevelButton.hidden = false;} BackToHomeMenuButton.hidden = false; optionsButton.hidden = false; bgSprite.hidden = false; - //DisplayTiltOnPause(); - - //clear any unused stuff in pause menu. - //audio and video should be stopped, so any hiccuping won't be as obvious. + // Clear any unused stuff in pause menu. + // Audio and video should be stopped, so any hiccuping won't be as obvious. Resources.UnloadUnusedAssets(); initialRespawn.SaveCheckpoint(); FallingPlayer.isPausable = true; + return; } } @@ -523,10 +578,10 @@ function UnPauseGame(resume : boolean) { lifeBar.hidden = false; lifeBarOutline.hidden = false; lifeBarThreat.hidden = false; - + bgSprite.hidden = true; rightArrow.hidden = true; - leftArrow.hidden = true; + loadNewLevelButton.hidden = true; BackToHomeMenuButton.hidden = true; HideOptionsButton(); @@ -535,107 +590,117 @@ function UnPauseGame(resume : boolean) { flatTiltLabel.hidden = true; verticalTiltLabel.hidden = true; - FallingPlayer.isPausable = resume; + FallingPlayer.isPausable = resume; holdingPauseButton = false; MoveController.pauseButtonArea = origPauseButtonArea; - } - +} + function IsGamePaused() { return Time.timeScale==0; } function PauseGameCheck() { + if (!FallingLaunch.isVRMode) { + holdingPauseButton = true; - holdingPauseButton = true; - - if (FallingPlayer.isPausable == true) { - if (Time.timeScale == 0) { - // if (AudioListener.pause == true) { - UnPauseGame(true); - } - else { - PauseGame(); + if (FallingPlayer.isPausable == true) { + if (Time.timeScale == 0) { + // if (AudioListener.pause == true) { + UnPauseGame(true); + } + else { + PauseGame(); + } } } } function RestartLevel() { - FallingPlayer.isPausable = false; + FallingPlayer.isPausable = false; // Camera.main.SendMessage("fadeOut"); //fadeOut(); - - // GA.API.Design.NewEvent("GUI:RestartLevel:" + SceneManagement.SceneManager.GetActiveScene().name + ":" + FallingLaunch.thisLevelArea, FallingLaunch.secondsInLevel, transform.parent.position); - + + FallingLaunch.Analytics.Event( + "GUI:RestartLevel:" + SceneManagement.SceneManager.GetActiveScene().name + ":" + FallingLaunch.thisLevelArea, + FallingLaunch.secondsInLevel + ); + Respawn.currentRespawn = initialRespawn; HideGUI(); fallingPlayerComponent.DeathRespawn (); UnPauseGame(false); } -function LevelComplete() { - HideGUI(); +function LevelComplete(timer1 : float, timer2 : float) { + if (!FallingLaunch.isVRMode) { + HideGUI(); + } FallingPlayer.isPausable = false; MoveController.Slowdown = 0; - bgSprite.hidden = false; - bgSprite.alphaFromTo( 3.0f, 0.0f, 0.97f, Easing.Sinusoidal.easeIn); + + if (!FallingLaunch.isVRMode && bgSprite) { + bgSprite.hidden = false; + bgSprite.alphaFromTo( timer1, 0.0f, 0.97f, Easing.Sinusoidal.easeIn); + } FallingLaunch.levelEndSlowdown = MoveController.Slowdown; - - yield WaitForSeconds (3); -// fade in congrats menu / buttons here + yield WaitForSeconds(timer1); + + // fade in congrats menu / buttons here savedTimeScale = Time.timeScale; //loadingLabel.hidden = false; - //loadingLabel.alphaFromTo( 0.75f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); - nextLevelLabel.hidden = false; - nextLevelLabel.alphaFromTo( 1.0f, 0.0f, 0.75f, Easing.Sinusoidal.easeIn); - fallingPlayerComponent.FadeAudio (.9, FadeDir.Out); - yield WaitForSeconds (1); -// Time.timeScale = 0; + //loadingLabel.alphaFromTo( 0.75f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); + if (!FallingLaunch.isVRMode && nextLevelLabel) { + nextLevelLabel.hidden = false; + nextLevelLabel.alphaFromTo( timer2, 0.0f, 0.75f, Easing.Sinusoidal.easeIn); + } + + fallingPlayerComponent.FadeAudio (.9 * timer2, FadeDir.Out); + + yield WaitForSeconds (timer2); + + // Time.timeScale = 0; player.GetComponent.().isKinematic = true; AudioListener.pause = true; - Application.LoadLevel(levelToLoad); -// not necessary because Respawn.js resets the latest checkpoint in its Start -// PlayerPrefs.SetString("LatestLevel", levelToLoad); - FallingLaunch.levelAchieved = (Application.loadedLevel + 1); - PlayerPrefs.SetInt("HighestLevel", (Application.loadedLevel + 1)); + + // Only increment `HighestLevel` pref if it's higher than the current `levelAchieved` value + // (fixes bug where beaten levels reset on beating level one of New Game Plus): + if ((Application.loadedLevel + 1) > FallingLaunch.levelAchieved) { + FallingLaunch.levelAchieved = (Application.loadedLevel + 1); + PlayerPrefs.SetInt("HighestLevel", (Application.loadedLevel + 1)); + } + Time.timeScale = savedTimeScale; + Application.LoadLevel(levelToLoad); + + // Calling Save right after loadLevel, since saving to disk can cause a potential FPS hiccup: PlayerPrefs.Save(); } function BeginOutroUI() { FadeOutGUI(); - FallingPlayer.isPausable = false; - player.GetComponent.().isKinematic = true; -} - -function OldGameCompleteUI() { - bgSprite.hidden = false; - bgSprite.alphaFromTo( 4.5f, 0.0f, 0.99f, Easing.Sinusoidal.easeInOut); - fallingPlayerComponent.FadeAudio (2.0, FadeDir.Out); - yield WaitForSeconds (1.0); - yield WaitForSeconds (2.0); } -function GameComplete() { - bgSprite.hidden = false; - bgSprite.alphaFromTo( 1.5f, 0.0f, 0.90f, Easing.Sinusoidal.easeIn); - fallingPlayerComponent.FadeAudio (1.5, FadeDir.Out); - yield WaitForSeconds (.5); - savedTimeScale = Time.timeScale; -// loadingLabel.hidden = false; -// loadingLabel.alphaFromTo( 1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); - yield WaitForSeconds (1); - AudioListener.pause = true; - FallingPlayer.isTiltable = true; - Application.LoadLevel(levelToLoad); - Time.timeScale = savedTimeScale; -} +// function GameComplete() { +// bgSprite.hidden = false; +// bgSprite.alphaFromTo( 1.5f, 0.0f, 0.90f, Easing.Sinusoidal.easeIn); +// fallingPlayerComponent.FadeAudio (1.5, FadeDir.Out); +// yield WaitForSeconds (.5); +// savedTimeScale = Time.timeScale; +// // loadingLabel.hidden = false; +// // loadingLabel.alphaFromTo( 1.0f, 0.0f, 1.0f, Easing.Sinusoidal.easeIn); +// yield WaitForSeconds (1); +// AudioListener.pause = true; +// FallingPlayer.isTiltable = true; +// Application.LoadLevel(levelToLoad); +// Time.timeScale = savedTimeScale; +// } function GameCompleteUI() { bgSprite.hidden = false; bgSprite.alphaFromTo( 2f, 0.0f, 0.8f, Easing.Sinusoidal.easeIn); // fallingPlayerComponent.FadeAudio (1.5, FadeDir.Out); - + // add anything else that requires main uitoolkit instance } @@ -653,7 +718,7 @@ function LoadNewLevelViaMenu() { loadLevelFour.hidden = true; BackToPauseMenuButton.hidden = true; loadingLabel.hidden = false; - + FallingLaunch.levelEndSlowdown = 0; Application.LoadLevel(levelToLoad); @@ -666,24 +731,23 @@ function LevelSelect() { loadLevelTwo.hidden = false; loadLevelThree.hidden = false; loadLevelFour.hidden = false; - + BackToHomeMenuButton.hidden = false; - + angledTiltLabel.hidden = true; flatTiltLabel.hidden = true; verticalTiltLabel.hidden = true; - loadNewLevelButton.hidden = true; + loadNewLevelButton.hidden = true; ShowBackButton(); } function HidePauseMenuElements() { rightArrow.hidden = true; - leftArrow.hidden = true; pauseButton.hidden = true; optionsButton.hidden = true; loadNewLevelButton.hidden = true; - + } function ShowBackButton() { @@ -691,16 +755,15 @@ function ShowBackButton() { } function BackToPauseMenu() { - //leftArrow.hidden = false; rightArrow.hidden = false; pauseButton.hidden = false; - + loadLevelOne.hidden = true; loadLevelTwo.hidden = true; loadLevelThree.hidden = true; loadLevelFour.hidden = true; HideOptions(); - + ShowOptionsButton(); //BackToHomeMenuButton.hidden = true; @@ -723,16 +786,16 @@ function HideOptions() { tiltText2.hidden = true; invertHorizAxisText.hidden = true; invertVertAxisText.hidden = true; - + invertVertAxisTextYes.hidden = true; invertVertAxisTextNo.hidden = true; invertHorizAxisTextYes.hidden = true; invertHorizAxisTextNo.hidden = true; - + angledTiltLabel.hidden = true; flatTiltLabel.hidden = true; verticalTiltLabel.hidden = true; - + } function ShowOptionsButton () { @@ -748,7 +811,7 @@ function fadeInOptions() { tiltText2.hidden = false; invertHorizAxisText.hidden = false; invertVertAxisText.hidden = false; - + if (FallingLaunch.invertVertAxisVal == -1) { invertVertAxisTextNo.hidden = true; invertVertAxisTextYes.hidden = false; @@ -766,7 +829,7 @@ function fadeInOptions() { invertHorizAxisTextNo.hidden = false; invertHorizAxisTextYes.hidden = true; } - + } function DisplayTiltChooser () { @@ -850,7 +913,7 @@ function LoadLevel1ViaMenu() { BackToPauseMenuButton.hidden = true; BackToHomeMenuButton.hidden = true; loadingLabel.hidden = false; - + FallingLaunch.hasSetAccel = false; Application.LoadLevel(level1); Time.timeScale = savedTimeScale; @@ -863,8 +926,8 @@ function LoadLevel2ViaMenu() { loadLevelFour.hidden = true; BackToPauseMenuButton.hidden = true; BackToHomeMenuButton.hidden = true; - loadingLabel.hidden = false; - + loadingLabel.hidden = false; + FallingLaunch.hasSetAccel = false; Application.LoadLevel(level2); Time.timeScale = savedTimeScale; @@ -878,7 +941,7 @@ function LoadLevel3ViaMenu() { BackToPauseMenuButton.hidden = true; BackToHomeMenuButton.hidden = true; loadingLabel.hidden = false; - + FallingLaunch.hasSetAccel = false; Application.LoadLevel(level3); Time.timeScale = savedTimeScale; @@ -892,7 +955,7 @@ function LoadLevel4ViaMenu() { BackToPauseMenuButton.hidden = true; BackToHomeMenuButton.hidden = true; loadingLabel.hidden = false; - + FallingLaunch.hasSetAccel = false; Application.LoadLevel(level4); Time.timeScale = savedTimeScale; @@ -906,7 +969,7 @@ function LoadHomeViaMenu() { BackToPauseMenuButton.hidden = true; BackToHomeMenuButton.hidden = true; loadingLabel.hidden = false; - + HidePauseMenuElements(); HideOptions(); @@ -916,22 +979,25 @@ function LoadHomeViaMenu() { flatTiltLabel.hidden = true; verticalTiltLabel.hidden = true; - FallingLaunch.hasSetAccel = false; - Application.LoadLevel(homeLevel); + LoadHomeNow(); Time.timeScale = savedTimeScale; } +function LoadHomeNow() { + FallingLaunch.hasSetAccel = false; + Application.LoadLevel(homeLevel); +} function OpenSite() { Application.OpenURL ("http://tysonkubota.net/"); } function HideGUI() { - pauseButton.hidden = true; - circleReticle.hidden = true; - lifeBar.hidden = true; - lifeBarOutline.hidden = true; - lifeBarThreat.hidden = true; + pauseButton.hidden = true; + circleReticle.hidden = true; + lifeBar.hidden = true; + lifeBarOutline.hidden = true; + lifeBarThreat.hidden = true; } function FadeOutGUI() { @@ -941,7 +1007,7 @@ function FadeOutGUI() { circleReticle.alphaTo( 0.5f, 0.0f, Easing.Quartic.easeIn); lifeBarThreat.hidden = true; yield WaitForSeconds (1.0); - + pauseButton.hidden = true; circleReticle.hidden = true; lifeBar.hidden = true; @@ -950,78 +1016,70 @@ function FadeOutGUI() { function UnhideGUI() { + if (!FallingLaunch.isVRMode) { pauseButton.hidden = false; circleReticle.hidden = false; lifeBar.hidden = false; lifeBarOutline.hidden = false; lifeBarThreat.hidden = true; - -// lifeBarThreat.alphaFrom( 1.0f, 0.0f, Easing.Quartic.easeIn); + + // lifeBarThreat.alphaFrom( 1.0f, 0.0f, Easing.Quartic.easeIn); pauseButton.alphaFromTo( 1.0f, 0.0f, 1.0f, Easing.Quartic.easeIn); lifeBar.alphaFromTo( 1.0f, 0.0f, 0.5f, Easing.Quartic.easeIn); lifeBarOutline.alphaFromTo( 1.0f, 0.0f, 1.0f, Easing.Quartic.easeIn); circleReticle.alphaFromTo( 1.0f, 0.0f, 1.0f, Easing.Quartic.easeIn); yield WaitForSeconds (1.0); - FallingPlayer.isPausable = true; -// lifeBarThreat.hidden = false; + } + FallingPlayer.isPausable = true; } function fadeIn( shouldUnhideGUI : boolean ) { - fadeSprite.hidden = false; - fadeSprite.alphaTo( 1.0f, 0.0f, Easing.Sinusoidal.easeOut); - yield WaitForSeconds(.5); - if (shouldUnhideGUI == true) {UnhideGUI();} - yield WaitForSeconds(.5); - fadeSprite.hidden = true; + fadeSprite.hidden = false; + fadeSprite.alphaTo( 1.0f, 0.0f, Easing.Sinusoidal.easeOut); + yield WaitForSeconds(.5); + if (shouldUnhideGUI == true) {UnhideGUI();} + yield WaitForSeconds(.5); + fadeSprite.hidden = true; } function fadeOut() { - fadeSprite.hidden = false; - fadeSprite.alphaTo( 1.0f, 1.0f, Easing.Sinusoidal.easeOut); - yield WaitForSeconds(1); - fadeSprite.hidden = true; + fadeSprite.hidden = false; + fadeSprite.alphaTo( 1.0f, 1.0f, Easing.Sinusoidal.easeOut); + yield WaitForSeconds(1); + fadeSprite.hidden = true; } function OnApplicationPause(pauseStatus: boolean) { - if (pauseStatus && Time.timeScale != 0 && FallingPlayer.isPausable == true) {setSavedTimeScale(); PauseGameNow();} + if (pauseStatus && FallingPlayer.isPausable && !FallingLaunch.isVRMode && + Time.timeScale != 0) { + setSavedTimeScale(); + PauseGameNow(); + } } function setSavedTimeScale() { savedTimeScale = Time.timeScale; } - -function PauseGameNow() { + +function PauseGameNow() { circleReticle.hidden = true; lifeBar.hidden = true; lifeBarOutline.hidden = true; lifeBarThreat.hidden = true; - + origPauseButtonArea = MoveController.pauseButtonArea; MoveController.pauseButtonArea = Rect(0, 0, Screen.width, Screen.height); - + // savedTimeScale = Time.timeScale; Time.timeScale = 0; AudioListener.volume = 0; AudioListener.pause = true; rightArrow.hidden = false; - //leftArrow.hidden = false; if (level2Unlocked) {loadNewLevelButton.hidden = false;} bgSprite.hidden = false; optionsButton.hidden = false; - //DisplayTiltOnPause(); -} - -function PauseGameBackgroundCheck() { - if (FallingPlayer.isPausable == true) { - if (Time.timeScale == 0) { - UnPauseGame(true); - } - else { - PauseGameNow(); - } - } } function setHoldingPauseButtonTrue() { @@ -1034,9 +1092,9 @@ function setHoldingPauseButtonFalse() { function ToggleTiltNeutral () { if (TogglingTiltNeutral == false) { - + TogglingTiltNeutral = true; - + if (PlayerPrefs.GetInt("TiltNeutral", 0) == 1) { fallingLaunchComponent.ChangeTilt(2); flatTiltLabel.hidden = true; @@ -1048,7 +1106,7 @@ function ToggleTiltNeutral () { flatTiltLabel.hidden = false; angledTiltLabel.hidden = true; verticalTiltLabel.hidden = true; - } + } else { fallingLaunchComponent.ChangeTilt(1); flatTiltLabel.hidden = true; @@ -1061,33 +1119,11 @@ function ToggleTiltNeutral () { } } -// function DisplayTilt () { -// if (PlayerPrefs.GetInt("TiltNeutral", 0) == 1) { -// flatTiltLabel.hidden = true; -// angledTiltLabel.hidden = false; -// verticalTiltLabel.hidden = true; -// } -// else if (PlayerPrefs.GetInt("TiltNeutral", 0) == 2) { -// flatTiltLabel.hidden = true; -// angledTiltLabel.hidden = true; -// verticalTiltLabel.hidden = false; -// } -// else { -// flatTiltLabel.hidden = false; -// angledTiltLabel.hidden = true; -// verticalTiltLabel.hidden = true; -// } -// } - -function DisplayTiltOnPause () { +function SaveCheckpointVR () { + FallingLaunch.Analytics.Event( + "ExitVRMode:" + SceneManagement.SceneManager.GetActiveScene().name, + FallingLaunch.secondsInLevel + ); - if (PlayerPrefs.GetInt("TiltNeutral", 0) == 1) { - angledTiltLabel.hidden = false; - } - else if (PlayerPrefs.GetInt("TiltNeutral", 0) == 2) { - verticalTiltLabel.hidden = false; - } - else { - flatTiltLabel.hidden = false; - } + initialRespawn.SaveCheckpoint(); } \ No newline at end of file diff --git a/lifeCountdown.js b/lifeCountdown.js index 5fbedd7..725e034 100644 --- a/lifeCountdown.js +++ b/lifeCountdown.js @@ -1,24 +1,43 @@ -var script : ScoreController; +private var script : ScoreController; var LifeFlashTexture : GameObject; static var LifeFlashTextureScript : GUITextureLaunch; LifeFlashTextureScript = LifeFlashTexture.GetComponent("GUITextureLaunch"); + +var lifeFlashUIVR : GameObject; +private var lifeFlashUIRenderer : Renderer; +private var lifeFlashUIMatl : Material; +private var peakLifeFlashValueVR : float = 0.7; +var lifeFlashAudioObj : GameObject; +private var lifeFlashAudio : AudioSource; + +var fallingIntroUIComponent : fallingIntroUI; + static var inOutro : boolean = false; -static var isAlive : int = 0; var UIscriptName : GameObject; +private var maxSlowdownThreshold : float; + function Awake () { - script = GetComponent("ScoreController"); + script = GetComponent("ScoreController"); } function Start () { - isAlive = 1; + if (FallingLaunch.isVRMode) { + lifeFlashUIRenderer = lifeFlashUIVR.GetComponent.(); + lifeFlashUIMatl = lifeFlashUIRenderer.material; + lifeFlashUIMatl.color.a = 0; + } + + lifeFlashAudio = lifeFlashAudioObj.GetComponent.(); + + maxSlowdownThreshold = MoveController.maxSlowdown - 1; Loop (); Loop2 (); ScoreLerpLoop (); } - + function Loop () { while (true && inOutro == false) { yield TickingAway(.25); @@ -29,7 +48,7 @@ function Loop () { function Loop2 () { while (true && inOutro == false) { - yield LifeFlashCheck(.2, 5); + yield LifeFlashCheck(.2, ScoreController.maxScore/4.0); } } @@ -39,55 +58,128 @@ function ScoreLerpLoop () { yield WaitForSeconds(.25); } } - - + +function FadeFlashVR (timer : float, fadeType : FadeDir) { + + var start = fadeType == FadeDir.In ? 0.0 : peakLifeFlashValueVR; + var end = fadeType == FadeDir.In ? peakLifeFlashValueVR : 0.0; + var i = 0.0; + var step = 1.0/timer; + + while (i <= 1.0) { + i += step * Time.deltaTime; + var t : float = i*i * (3f - 2f*i); // smoothstep lerp + lifeFlashUIMatl.color.a = Mathf.Lerp(start, end, t); + yield; + } +} + function TickingAway (delay : float) { - if (script.currentScore > 0) { - if (MoveController.Slowdown > 17999) { + // Early return if player's not alive, so we stop flashing red: + if (FallingPlayer.isAlive == 0) { + return; + } + + // The visibleScore check is to ensure that the onscreen health UI + // is actually empty before the player dies; if we used currentScore directly, + // the UI health bar's lerp would lag behind the actual value, so the player would + // appear to die too soon in some cases. + if (ScoreController.currentScore > 0 || ScoreController.visibleScore > 0) { + + if (MoveController.Slowdown > maxSlowdownThreshold) { script.DecrementScore(delay); - yield WaitForSeconds((delay/4)); - } - - else if (MoveController.Slowdown < 18000) { + yield WaitForSeconds((delay/4)); // 4x health penalty during player speedup + } else if (MoveController.Slowdown < MoveController.maxSlowdown) { script.DecrementScore(delay); yield WaitForSeconds(delay); } - } - - else { - isAlive = 0; + } else { + FallingPlayer.isAlive = 0; FallingPlayer.isPausable = false; - LifeFlashTextureScript.FadeFlash (1, FadeDir.Out); + + if (FallingLaunch.isVRMode) { + FadeFlashVR(1, FadeDir.Out); + } else { + LifeFlashTextureScript.FadeFlash(1, FadeDir.Out); + } + FallingLaunch.secondsAlive = (Time.time - FallingPlayer.lifeStartTime); - // GA.API.Design.NewEvent("Death:Drained:"+Application.loadedLevelName + ":" + FallingLaunch.thisLevelArea, FallingLaunch.secondsAlive, transform.position); + //Debug.Log("You died!"); - yield GetComponent(FallingPlayer).DeathRespawn (); - GetComponent(FallingPlayer).ShowDeathHelp(); - // GameAnalytics syntax: GA.API.Design.NewEvent(String eventName, float eventValue, Vector3 trackPosition); + FallingLaunch.Analytics.Event( + "Death:Drained:" + FallingLaunch.vrModeAnalyticsString + Application.loadedLevelName + ":" + FallingLaunch.thisLevelArea, + FallingLaunch.secondsAlive + ); + + // In VR mode, DeathRespawn is now decoupled from the actual respawning time: + // e.g. the player has a several-second time interval to decide whether + // to exit or respawn. If they take more time than showIconVR's timer, + // the tutorial UI hint will already be transparent by the time they respawn. + // That's probably not a huge deal since it's non-critical UI, just a help hint. + // TODO: Pass optional args to DeathRespawn in VR mode, so we can show specific UI + // after user-initiated respawn or via a callback. + yield GetComponent(FallingPlayer).DeathRespawn(); + + if (!FallingLaunch.isVRMode) { + GetComponent(FallingPlayer).ShowDeathHelp(); + } else if (fallingIntroUIComponent) { + // fallingIntroUIComponent only exists on intro level: + // 'tutorial-vr-intro-2' is the name of the 'gather orbs to survive' icon + fallingIntroUIComponent.ShowIconVR('tutorial-vr-intro-2', 8); + } + + // New GameAnalytics "Design" event syntax: + // GameAnalytics.NewDesignEvent (string eventName, float eventValue); + + // Original GameAnalytics syntax: GA.API.Design.NewEvent(String eventName, float eventValue, Vector3 trackPosition); } } function LifeFlashCheck (delay : float, score : int) { - - if (script.currentScore < score && inOutro == false) { - //Camera.main.SendMessage("lifeFlashOut"); - LifeFlashTextureScript.FadeFlash (delay, FadeDir.In); - yield WaitForSeconds(delay); -// Camera.main.SendMessage("lifeFlashUp"); - LifeFlashTextureScript.FadeFlash (delay, FadeDir.Out); - yield WaitForSeconds((delay*3)); + // Early return if player's not alive, so we stop flashing red: + if (!FallingPlayer.isAlive) { + return; } -} -// not being used currently, due to more versatile LifeFlashCheck in a separate coroutine. -function LifeFlash (delay : float, score : int) { + if (ScoreController.currentScore < score && inOutro == false) { - if (script.currentScore < score) { - Camera.main.SendMessage("lifeFlashOut"); - yield WaitForSeconds(delay); - Camera.main.SendMessage("lifeFlashUp"); - } + var lowLifeRatio = ScoreController.currentScore / score; + + if (lifeFlashAudio) { + // if speeding up, use a louder ping volume for audibility, plus a shorter + // yield wait since the health drain is 4x higher: + if (MoveController.Slowdown > maxSlowdownThreshold) { + lifeFlashAudio.volume = 0.9; + } else { + var deathPromixityScore = 1.0 - lowLifeRatio; + // Clamp to a min volume of 0.2, max volume of .9; + lifeFlashAudio.volume = Mathf.Clamp(deathPromixityScore, 0.2, 0.9); + } + } + + if (FallingLaunch.isVRMode) { + FadeFlashVR(delay, FadeDir.In); + if (lifeFlashAudio) {lifeFlashAudio.Play();} + yield WaitForSeconds(delay); + FadeFlashVR(delay, FadeDir.Out); + } else { + LifeFlashTextureScript.FadeFlash(delay, FadeDir.In); + if (lifeFlashAudio) {lifeFlashAudio.Play();} + yield WaitForSeconds(delay); + LifeFlashTextureScript.FadeFlash(delay, FadeDir.Out); + } + + // increase the flash frequency as death draws near (compare w/ `delay` above): + if (MoveController.Slowdown > maxSlowdownThreshold) { + // 4x delay when speeding up due to increased health drain: + yield WaitForSeconds( Mathf.Max(delay*lowLifeRatio*2.0, delay) ); + } else { + yield WaitForSeconds( Mathf.Max(delay*lowLifeRatio*8.0, delay*4.0) ); + } + } else { + return; + } } diff --git a/setVRMode.js b/setVRMode.js new file mode 100644 index 0000000..cabf170 --- /dev/null +++ b/setVRMode.js @@ -0,0 +1,173 @@ +#pragma strict + +private var fallingLaunch : GameObject; +private var fallingLaunchComponent : FallingLaunch; + +var GvrViewerMainObject : GameObject; + +// should be a prefab tilted 90 degrees in X axis, so the user faces forward in headset: +var cameraVRParentPrefab : GameObject; +private var cameraVRParent : GameObject; + +var cameraObj : GameObject; + +private var VRViewerComponent : Component; +// var VRViewer : GvrViewer; +private var hasCentered : boolean = false; + +var VRUICameraVRTransform : Transform; +var oceanCameraVRTransform : Transform; + +var VRUICameraObj : GameObject; +var VRUICamera : Camera; +private var VRUICameraVRHead : GvrHead; + +var fogColor : Color; +var fogColorVR : Color; + +function Awake () { + if (!cameraObj) { + cameraObj = Camera.main.gameObject; + // cameraObj = transform.Find("Player-cameras/Camera").gameObject; + } +} + +function Start () { + fallingLaunch = GameObject.Find("LaunchGameObject"); + fallingLaunchComponent = fallingLaunch.GetComponent.(); + + // oceanCameraVRTransform = cameraObj.transform.Find("Camera-for-ocean-VR"); + // VRUICameraVRTransform = cameraObj.transform.Find("Camera-for-VR-UI"); + + // VR UI Camera lives two levels down from the Player GameObject, + // inside the main parent Camera: + + oceanCameraVRTransform = cameraObj.transform.Find("Camera-for-ocean-VR"); + + VRUICameraVRTransform = cameraObj.transform.Find("Camera-for-VR-UI"); + VRUICameraObj = VRUICameraVRTransform ? VRUICameraVRTransform.gameObject : null; + VRUICamera = VRUICameraObj.GetComponent.(); + + // NOTE: Would be best to perform these lookups elsewhere, but + // due to JS/C# interactions and compilation order it's less feasible. + // http://answers.unity3d.com/questions/507580/bce0019-enabled-is-not-a-member-of-unityenginecomp-3.html + // Also better to use a type below, not a string, but it's necessary due to C# + JS: + // https://docs.unity3d.com/ScriptReference/Component.GetComponent.html + VRViewerComponent = GvrViewerMainObject.GetComponent("GvrViewer"); + + fogColor = RenderSettings.fogColor; + + if (FallingLaunch.isVRMode && VRViewerComponent) { + + // Clear is the Unity-default color: + if (fogColorVR.ToString() != Color.clear.ToString()) { + RenderSettings.fogColor = fogColorVR; + } + + (VRViewerComponent as MonoBehaviour).enabled = true; // type coercion required to access 'enabled' + (VRViewerComponent as GvrViewer).VRModeEnabled = true; + + // Center Cardboard view post-instantiation, but before calling setParent on + // the main camera to make it the child of the 90-degree-offset prefab, + // since we want to map 'forward' in Cardboard-land to 'down' in world space: + if (!hasCentered) { + var VRViewer = GvrViewerMainObject.GetComponent.(); + VRViewer.Instance.Recenter(); + hasCentered = true; + } + + // Re-parent camera for 90deg tilt offset (so player can look forward in VR): + cameraVRParent = + Instantiate(cameraVRParentPrefab); + + // Make the camera-VR-parent object (post-instantiation) a child of this (Player) gameObject transform, + // then make the Camera (cameraObj) a child of the camera-VR-parent object: + cameraVRParent.transform.SetParent(transform); + cameraObj.transform.SetParent(cameraVRParent.transform); + + // oceanCameraVR in particular seems to sometimes to adopt skewed rotation. + // (related to whether Player is tilted when the main VR camera object is re-parented?) + // Consider manually forcing it and the UI camera to (0,0,0) post-reparenting, to be safe: + if (oceanCameraVRTransform) { + // Debug.Log("found oceanCameraVRTransform with rotation " + oceanCameraVRTransform.rotation); + oceanCameraVRTransform.localRotation = Quaternion.identity; + } + + if (VRUICameraVRTransform) { + // Debug.Log("found VRUICameraVRTransform with rotation " + VRUICameraVRTransform.rotation); + VRUICameraVRTransform.localRotation = Quaternion.identity; + } + + } else if (VRViewerComponent) { + (VRViewerComponent as GvrViewer).VRModeEnabled = false; + } + + if (!FallingLaunch.isVRMode) { + GvrViewerMainObject.SetActive(false); // disable the GvrViewerMain gameObject to stop blank viewer from rendering + } +} + +function Update () { + // Early return if not in VR mode: + if (!FallingLaunch.isVRMode) { + return; + } else if (FallingLaunch.isVRMode) { + MaintainVRUI(); + if (VRViewerComponent) { + // See note in Start() about unfortunate-but-required type coercion: + if ( (VRViewerComponent as GvrViewer).BackButtonPressed ) { + // When Cardboard SDK close icon / back button tapped, return home: + FallingPlayer.isPausable = false; + fallingLaunchComponent.DisableVRMode(); + FallingPlayer.UIscriptComponent.SaveCheckpointVR(); + FallingPlayer.UIscriptComponent.LoadHomeNow(); + } + } + } + +} + + +function MaintainVRUI () { + // Existence check required for StereoControllerComponent in Update() + // since it takes 1+ seconds to set up everything via GVR plugin: + if (!VRUICameraVRHead && VRUICameraObj && VRUICamera) { + // Early return if we're not in VR mode and we've already disabled the VR UI camera: + if (!FallingLaunch.isVRMode && VRUICamera.enabled == false) { + return; + } + + if (FallingLaunch.isVRMode) { + if (VRUICameraObj.GetComponent.()) { + + // This GvrHead is already nested within the Player object, + // and the UI is meant to be static relative to the player, + // so therefore shouldn't independently track rotation. + + // We use getComponent. instead of the Google plugin's Head getter, + // because the latter is not guaranteed to be located on this component. + // It could be a parent object's GvrHead, since the GvrHeads are applied at runtime + // by GVRViewer, which adds a StereoController to `Camera.allCameras`'s results array. + // Then StereoController executes `AddStereoRig`, which only adds a new GvrHead if a + // component's parent is not presumed to have one. Otherwise, the parent GvrHead is used. + + // If we just set `trackRotation` on StereoController.Head directly, we might be disabling + // the parent (main) camera's ability to track with head movement, which is `no bueno.` + + // Keep VR UI aligned with parent gameObject, in case of drift via GvrHead + // (currently, this gameObj doesn't get its own GvrHead, but the order of assignment + // is nondeterministic, constructed by looping through an array of Camera.allCameras). + // Thus, the below is defensive code in case it does ever get its own GvrHead. + if (Debug.isDebugBuild) { + Debug.Log("Found matching GvrHead for VRUICameraVRHead"); + } + + VRUICameraVRHead = VRUICameraObj.GetComponent.(); + VRUICameraVRHead.trackRotation = false; + } + } else if (!FallingLaunch.isVRMode && VRUICamera.enabled) { + // Disable VR-specific UI camera if we're not in VR mode: + VRUICamera.enabled = false; + } + } +} \ No newline at end of file