using UnityEngine; using UnityEngine.InputSystem; using System.Collections; public class Player : MonoBehaviour { public GameObject gameBoard; public AudioClip flip; public AudioClip normalShoot; public AudioClip laserCharge; public AudioClip laserDischarge; public AudioClip laserShoot; public AudioClip magnetIdle; public AudioClip magnetShoot; public AudioClip death; public AudioClip killed; public AudioClip defeat; public AudioClip denied; public AudioClip victory; public MusicManager musicManager; public Fader fader; public GameObject horizontalBarrierPrefab; public GameObject verticalBarrierPrefab; public GameObject horizontalLaserPrefab; public GameObject verticalLaserPrefab; public int lives = 8; public int score = 0; public int bonus = 3100; public Animator gunAnimator; public Animator muzzleAnimator; public SpriteRenderer muzzleRenderer; public GameObject debrisPrefab; public int magnetCount = 0; public int laserCount = 0; public GameObject magnetLeft; public GameObject magnetRight; public GameObject magnetTop; public GameObject magnetBottom; public BallSpawner ballSpawner; private bool flipped = false; private bool gameOver = false; private AudioSource audioSource; private bool canFire = true; private float damageTimer = 0.0f; private float damageCooldown = 0.5f; private bool exploding = false; private Bounds playerBounds; private Bounds boardBounds; private bool laserActive = false; private bool magnetActive = false; private float magnetDuration = 5.0f; private float magnetTimer = 0.0f; // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { audioSource = GetComponent(); Cursor.visible = false; if (!TryGetWorldBounds(gameObject, out playerBounds)) { Debug.LogWarning("Could not get world bounds for player."); } if (!TryGetWorldBounds(gameBoard, out boardBounds)) { Debug.LogWarning("Could not get world bounds for gameBoard."); return; } // TODO: Generalize this to work with subset of the board bounds. // Initialize the magnets. magnetLeft.GetComponent().enabled = false; magnetRight.GetComponent().enabled = false; magnetTop.GetComponent().enabled = false; magnetBottom.GetComponent().enabled = false; magnetLeft.transform.position = new Vector3( boardBounds.min.x + magnetLeft.GetComponent().bounds.extents.x, transform.position.y, transform.position.z ); magnetRight.transform.position = new Vector3( boardBounds.max.x - magnetRight.GetComponent().bounds.extents.x, transform.position.y, transform.position.z ); magnetTop.transform.position = new Vector3( transform.position.x, boardBounds.max.y - magnetTop.GetComponent().bounds.extents.y, transform.position.z ); magnetBottom.transform.position = new Vector3( transform.position.x, boardBounds.min.y + magnetBottom.GetComponent().bounds.extents.y, transform.position.z ); } // Update is called once per frame void Update() { if (damageTimer > 0.0f) { damageTimer -= Time.fixedDeltaTime; } if (!exploding) { Vector2 mouseScreen = Mouse.current.position.ReadValue(); Camera cam = Camera.main; // Keep movement on the same depth plane as the current player position. float screenZ = cam.WorldToScreenPoint(transform.position).z; Vector3 mouseWorld = cam.ScreenToWorldPoint(new Vector3(mouseScreen.x, mouseScreen.y, screenZ)); Vector3 extents = playerBounds.extents; float clampedX = Mathf.Clamp(mouseWorld.x, boardBounds.min.x + extents.x / 2.0f, boardBounds.max.x - extents.x / 2.0f); float clampedY = Mathf.Clamp(mouseWorld.y, boardBounds.min.y + extents.y / 2.0f, boardBounds.max.y - extents.y / 2.0f); transform.position = new Vector3(clampedX, clampedY, transform.position.z); } if (Keyboard.current != null) { if (Keyboard.current.spaceKey.wasPressedThisFrame) { flipped = !flipped; transform.eulerAngles = new Vector3(0, 0, flipped ? 90 : 0); audioSource.PlayOneShot(flip); } if (Keyboard.current.escapeKey.wasPressedThisFrame) { gameOver = true; } if (Keyboard.current.wKey.wasPressedThisFrame) { if (laserActive) { DisableLaser(); } else { EnableLaser(); } } if (Keyboard.current.dKey.wasPressedThisFrame) { if (magnetActive) { DisableMagnet(); } else { EnableMagnet(); } } } if (Mouse.current.leftButton.wasPressedThisFrame && canFire && !exploding) { if (laserActive) { FireLaser(); } else if (magnetActive) { FireMagnet(); } else { FireNormal(); } } if (gameOver) { StartCoroutine(EndGame()); gameOver = false; // Reset gameOver to prevent multiple coroutine starts } if (magnetTimer > 0.0f) { magnetTimer -= Time.deltaTime; if (magnetTimer <= 0.0f) { magnetLeft.GetComponent().enabled = false; magnetRight.GetComponent().enabled = false; magnetTop.GetComponent().enabled = false; magnetBottom.GetComponent().enabled = false; ballSpawner.MagnetInactive(); } } } private static bool TryGetWorldBounds(GameObject target, out Bounds bounds) { Collider2D collider2D = target.GetComponent(); if (collider2D != null) { bounds = collider2D.bounds; return true; } Renderer renderer = target.GetComponent(); if (renderer != null) { bounds = renderer.bounds; return true; } Collider collider3D = target.GetComponent(); if (collider3D != null) { bounds = collider3D.bounds; return true; } bounds = default; return false; } private IEnumerator EndGame() { musicManager.pauseMusic(); audioSource.PlayOneShot(defeat); yield return new WaitForSeconds(1.3f); fader.ResetFader(); } public void BarrierFinished() { canFire = true; } public IEnumerator SetGameOver() { yield return new WaitForSeconds(3.0f); gameOver = true; } private void EnableLaser() { if (laserCount > 0) { laserActive = true; magnetActive = false; audioSource.PlayOneShot(laserCharge); gunAnimator.SetBool("laserActivated", true); gunAnimator.SetBool("magnetActivated", false); } else { if (!audioSource.isPlaying) { audioSource.PlayOneShot(denied); } } } private void EnableMagnet() { if (magnetCount > 0) { laserActive = false; magnetActive = true; audioSource.PlayOneShot(magnetIdle); gunAnimator.SetBool("laserActivated", false); gunAnimator.SetBool("magnetActivated", true); } else { if (!audioSource.isPlaying) { audioSource.PlayOneShot(denied); } } } private void DisableLaser() { if (laserActive) { laserActive = false; audioSource.PlayOneShot(laserDischarge); gunAnimator.SetBool("laserActivated", false); } } private void DisableMagnet() { if (magnetActive) { magnetActive = false; gunAnimator.SetBool("magnetActivated", false); } } private void FireNormal() { canFire = false; audioSource.PlayOneShot(normalShoot); muzzleAnimator.SetTrigger("firing"); if (flipped) { Instantiate(verticalBarrierPrefab, transform.position, Quaternion.identity); } else { Instantiate(horizontalBarrierPrefab, transform.position, Quaternion.identity); } } private void FireLaser() { canFire = false; audioSource.PlayOneShot(laserShoot); muzzleAnimator.SetTrigger("firing"); laserCount--; if (flipped) { Instantiate(verticalLaserPrefab, transform.position, Quaternion.identity); } else { Instantiate(horizontalLaserPrefab, transform.position, Quaternion.identity); } DisableLaser(); } private void FireMagnet() { audioSource.PlayOneShot(magnetShoot); muzzleAnimator.SetTrigger("firing"); magnetCount--; magnetTimer = magnetDuration; if (flipped) { magnetTop.GetComponent().enabled = true; magnetBottom.GetComponent().enabled = true; } else { magnetLeft.GetComponent().enabled = true; magnetRight.GetComponent().enabled = true; } ballSpawner.MagnetActive(flipped); DisableMagnet(); } private void Explode() { if (exploding) { return; } exploding = true; gunAnimator.SetTrigger("playerKilled"); muzzleRenderer.enabled = false; audioSource.PlayOneShot(death); for (int i = 0; i < 8; i++) { SpawnDebris(); } } private void SpawnDebris() { Vector2 randomOffset = Random.insideUnitCircle * playerBounds.extents.magnitude; Instantiate( debrisPrefab, transform.position + new Vector3(randomOffset.x, randomOffset.y, 0), Quaternion.identity ); } public void OnBarHit() { if (damageTimer > 0.0f) { return; } lives--; damageTimer = damageCooldown; if (lives <= 0) { Explode(); StartCoroutine(SetGameOver()); } canFire = true; // Allow firing again after bar hit } }