using UnityEngine; using System.Collections; public class ShipControls : MonoBehaviour { public LevelManagerBase levelManager; public GUISkin steeringStyle; // Acorn prefab (Nutapult) (Dan) public GameObject acornPrefab; public int startingHealth = 4; public int maximumHealth = 4; public float boostLength = 5.0f; public int boostFactor = 5; public GameObject cannonFire; // Warp Speed effect public GameObject warpSpeed; // Boosted ship trail public GameObject boostTrail; string boostTrailCloneName; // Cannon firing indicator public bool firingBroadside; ArrayList boosts; // Steering controls protected MouseRotate wheel; protected int goodBarrelsHit = 0; protected int boostBarrelsHit = 0; protected int badBarrelsHit = 0; protected int shipsDestroyed = 0; protected Material shipMaterial; protected Texture healthBar; protected Texture healthBarFiller; protected Texture fullHeart; protected Texture emptyHeart; protected float sensitivity; int lastGoodBarrelID; int lastBoostBarrelID; int lastBadBarrelID; int goodBarrelStreak; int boostBarrelStreak; int badBarrelStreak; float cannonOffset; // bool modelMoved; int health; public bool isUsingTilt; public float smoothing = 40f; public float twitchBuffer = 0.025f; public Vector3 lastRotation; public int Health { get { return health; } set { health = Mathf.Clamp(value, 0, maximumHealth); } } public int Speed { get { return CalculateSpeed(); } } // Speed bonus provided by the boost barrels currently in effect public int BarrelBoost { get { return boosts.Count * boostFactor; } } public int PotionsHit { get { return goodBarrelsHit; } } public int BarrelsHit { get { return badBarrelsHit; } } public int BoostsHit { get { return boostBarrelsHit; } } public void Awake() { shipMaterial = GameObject.Find("ShipModel").renderer.material; healthBar = (Texture)Resources.Load("Textures/GUI/healthbar"); healthBarFiller = (Texture)Resources.Load("Textures/GUI/healthbar_fill"); boosts = new ArrayList(); boostTrailCloneName = "boost trail(Clone)"; // modelMoved = false; } public void Start() { ((AudioSource)Camera.main.GetComponent("AudioSource")).volume = PlayerPrefs.GetFloat("Music Volume"); Health = startingHealth; wheel = (MouseRotate)FindObjectOfType(typeof(MouseRotate)); goodBarrelsHit = 0; badBarrelsHit = 0; boostBarrelsHit = 0; shipsDestroyed = 0; isUsingTilt = true; sensitivity = PlayerPrefs.GetFloat("Sensitivity"); lastRotation = Input.acceleration; } public void Update () { // Check if we have boosts that have expired. Since boosts go in in order, and since we only hit // one barrel at a time (at the moment) we can stop checking as soon as we get a hit float t = Time.time; for (int i = 0; i < boosts.Count; i++) { if (t >= (float)boosts[i]) { boosts.RemoveAt(i); break; } } #if UNITY_IPHONE if (Input.touchCount > 0) isUsingTilt = false; else isUsingTilt = true; #endif #if UNITY_EDITOR isUsingTilt = false; #endif // Power down warp speed if (boosts.Count == 0) BoostEffectsOff(); // Pause and un-pause the sound if (TimeManager.paused) { Time.timeScale = 0; AudioListener.pause = true; } else { Time.timeScale = 1; AudioListener.pause = false; } MakeShipLookRatty(); if (isUsingTilt) { Vector3 tempRotation = Input.acceleration; if (Mathf.Abs(lastRotation.y - tempRotation.y) > twitchBuffer) lastRotation = tempRotation; Vector3 currentRotation = lastRotation; if (currentRotation.x <= 0) currentRotation.y *= -1f; transform.localEulerAngles = Vector3.Lerp(transform.localEulerAngles, new Vector3(0f,//transform.localEulerAngles.x, Mathf.Clamp(currentRotation.y * 45f, -45f, 45f), Mathf.Clamp((Mathf.Sin(Time.time) * 8f) + (currentRotation.y * sensitivity * 30f), -30f, 30f)), Time.deltaTime * smoothing); } else { transform.localEulerAngles = new Vector3(0f,//transform.localEulerAngles.x, Mathf.Clamp(wheel.wheelRotation * 0.025f, -45f, 45f), Mathf.Clamp((Mathf.Sin(Time.time) * 8f) + (wheel.wheelRotation * -0.025f * sensitivity), -30f, 30f)); } // Move the ship, allowing for pausing the game TimeManager.Translate(transform, new Vector3(transform.rotation.y, 0f, 0f), Space.World); if (transform.position.x > 30f) transform.position = new Vector3(30f, transform.position.y, transform.position.z); if (transform.position.x < -30f) transform.position = new Vector3(-30f, transform.position.y, transform.position.z); // End the game on zero health if (Health == 0 && levelManager.Playing) { // Tell the level manager the game ended so it will stop scoring levelManager.GameOver(); // Activate the explosions over the ship gameObject.SetActiveRecursively(true); } if (Health == 0) { Invoke("SinkShip", 1); Invoke("GameOver", 4); } // Check for Cannon Cue (Dan) CheckFrontCannon(); } public virtual void GoToMainMenu() { Application.LoadLevel("MainMenuBeach"); } public virtual void OnTriggerEnter(Collider other) { // Count and destroy barrels if we hit them Barrel barrel = other.GetComponent(); if (barrel != null) { int streak = 0; // Let the barrel effect the ship's health ApplyBarrelBonus(barrel.bonus); // Count the barrels, check for streaks, and apply special powers if (barrel.bType == BarrelType.Potion) { goodBarrelsHit++; goodBarrelStreak = (barrel.ID == lastGoodBarrelID + 1) ? goodBarrelStreak + 1 : 1; lastGoodBarrelID = barrel.ID; streak = goodBarrelStreak; } else if (barrel.bType == BarrelType.Boost) { boostBarrelsHit++; boostBarrelStreak = (barrel.ID == lastBoostBarrelID + 1) ? boostBarrelStreak + 1: 1; lastBoostBarrelID = barrel.ID; streak = boostBarrelStreak; // Boost barrels add a limited duration speed boost boosts.Add(Time.time + boostLength); BoostEffectsOn(); } else { badBarrelsHit++; badBarrelStreak = (barrel.ID == lastBadBarrelID + 1) ? badBarrelStreak + 1: 1; lastBadBarrelID = barrel.ID; streak = badBarrelStreak; } // Score the barrels levelManager.BarrelScoreUpdate(barrel.bType, streak); } // If we collide with the ship, show the cannons firing ChaseBarrelGenerator cbg = other.GetComponent(); if (cbg != null) FireBroadside(cbg.transform); } void BoostEffectsOn() { warpSpeed.active = true; // Invoke("ShutDownWarpSpeed", 1.5f); // Instantiate a boost trail and attach it to the ship so that it follows the ship around. // Use instantiate rather than just making an attached one active because an activated one "remembers" // where it last de-activated and for a moment creates a visual effect in the old location if (transform.Find(boostTrailCloneName) == null) { GameObject go = (GameObject)Instantiate(boostTrail, transform.position, transform.rotation); go.audio.volume = Options.sfxVolume; go.transform.parent = transform; } // if (!modelMoved) { // Transform model = transform.Find("ShipModel"); // model.localPosition -= 0.5f * model.right; // modelMoved = true; // } } // void ShutDownWarpSpeed() { // warpSpeed.active = false; // } void BoostEffectsOff() { warpSpeed.active = false; // Destroy the boost trail Transform t = transform.Find(boostTrailCloneName); if (t != null) Destroy(t.gameObject); // if (modelMoved) { // Transform model = transform.Find("ShipModel"); // model.localPosition += 0.5f * model.right; // modelMoved = false; // } } void FireBroadside(Transform t) { // Find the position of the chase-ee relative to the ship. Vector3 relativePosition = transform.InverseTransformPoint(t.position); // Check if the relative position falls to the left or the right if (relativePosition.x <= 0) { cannonOffset = -4.5f; // The other ship is to our left StartCoroutine(ShowFusillade("PortCamera", -4.5f)); } else { cannonOffset = 4.5f; // The other ship is to our right StartCoroutine(ShowFusillade("StarbordCamera", 4.5f)); } } IEnumerator ShowFusillade(string side, float offset) { // Set a flag so we can stop the barrels during the cannon firing firingBroadside = true; // Switch cameras so we can see the side of the ship Camera temp = Camera.main.camera; temp.enabled = false; transform.Find(side).camera.enabled = true; // Let them see the ship yield return new WaitForSeconds(0.5f); // Fire the cannons at slightly different times . . . // . . . first in front of the middle cannon FireCannons(offset, 2.3f, 2.9f); // . . . then in front of the other two, in random order if (Random.Range(0, 10) < 5) { Invoke("FireFrontCannons", 0.1f); Invoke("FireBackCannons", 0.2f); } else { Invoke("FireBackCannons", 0.1f); Invoke("FireFrontCannons", 0.2f); } // In front of the front two cannons // FireCannons(offset, 2.3f, 4.5f); // In front of the back two right-hand cannons // FireCannons(offset, 2.3f, 1.3f); // Let them enjoy the smoke yield return new WaitForSeconds(0.75f); // Switch cameras again transform.Find(side).camera.enabled = false; temp.enabled = true; // Done with the special effect. Start the barrels again. firingBroadside = false; } // Check for CannonDown input in LevelManager (Dan) void CheckFrontCannon() { if (levelManager.GetCannon()) { // Invoke the cannon fire particle effect. FireFrontCannons(); // (Create Acorn object with default linear velocity, random angular velocity and direction facing forward + up10) GameObject acorn = (GameObject)Instantiate(acornPrefab); acorn.transform.position = transform.position; acorn.transform.Translate(new Vector3(0, 0, 10.0f)); // Random angular velocity -- can be changed to constant values if performance issues arise. acorn.rigidbody.angularVelocity = new Vector3(Random.Range(3.0f, 10.0f), Random.Range(3.0f, 10.0f), Random.Range(3.0f, 10.0f)); // Calculate the theoritical radial direction of the ship float rads = (transform.rotation.y/2) * -Mathf.PI; rads += Mathf.PI/2; // Apply velocity of acorn based on radial direction Vector3 force = new Vector3(Mathf.Cos(rads)*2000.0f, 0.0f, Mathf.Sin(rads)*2000.0f); acorn.rigidbody.AddForce(force); } } void FireFrontCannons() { FireCannons(cannonOffset, 2.3f, 4.5f); } void FireMiddleCannon() { FireCannons(cannonOffset, 2.3f, 2.9f); } void FireBackCannons() { FireCannons(cannonOffset, 2.3f, 1.3f); } void FireCannons(float xOffset, float yOffset, float zOffset) { cannonFire.audio.volume = Options.sfxVolume; Instantiate(cannonFire, transform.position + transform.TransformDirection(xOffset, yOffset, zOffset), transform.rotation); } void SinkShip() { Vector3 v = new Vector3(0, -10.0f * Time.deltaTime, 0); transform.Translate(v); } // Use Frank's alpha trick to make the ship look worse void MakeShipLookRatty() { shipMaterial.SetFloat("_Cutoff", (1f - Mathf.Clamp01(Health / (float)startingHealth))); } int CalculateSpeed() { return levelManager.ShipSpeed + BarrelBoost; } void ApplyBarrelBonus(int bonus) { Health += bonus; } // This needs a new name. Or somethings. It only gets used in the base.OnGUI to help with // the ship health graphic. public float GetHealth() { return Mathf.Clamp01(Health / (float)maximumHealth); } protected void GameOver() { levelManager.ChangeScreen(ScreenType.Over); } }