Files
Barrack-Unity/Assets/Scripts/Game/Player.cs
T

457 lines
11 KiB
C#

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<AudioSource>();
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<SpriteRenderer>().enabled = false;
magnetRight.GetComponent<SpriteRenderer>().enabled = false;
magnetTop.GetComponent<SpriteRenderer>().enabled = false;
magnetBottom.GetComponent<SpriteRenderer>().enabled = false;
magnetLeft.transform.position = new Vector3(
boardBounds.min.x + magnetLeft.GetComponent<SpriteRenderer>().bounds.extents.x,
transform.position.y,
transform.position.z
);
magnetRight.transform.position = new Vector3(
boardBounds.max.x - magnetRight.GetComponent<SpriteRenderer>().bounds.extents.x,
transform.position.y,
transform.position.z
);
magnetTop.transform.position = new Vector3(
transform.position.x,
boardBounds.max.y - magnetTop.GetComponent<SpriteRenderer>().bounds.extents.y,
transform.position.z
);
magnetBottom.transform.position = new Vector3(
transform.position.x,
boardBounds.min.y + magnetBottom.GetComponent<SpriteRenderer>().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<SpriteRenderer>().enabled = false;
magnetRight.GetComponent<SpriteRenderer>().enabled = false;
magnetTop.GetComponent<SpriteRenderer>().enabled = false;
magnetBottom.GetComponent<SpriteRenderer>().enabled = false;
ballSpawner.MagnetInactive();
}
}
}
private static bool TryGetWorldBounds(GameObject target, out Bounds bounds)
{
Collider2D collider2D = target.GetComponent<Collider2D>();
if (collider2D != null)
{
bounds = collider2D.bounds;
return true;
}
Renderer renderer = target.GetComponent<Renderer>();
if (renderer != null)
{
bounds = renderer.bounds;
return true;
}
Collider collider3D = target.GetComponent<Collider>();
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<SpriteRenderer>().enabled = true;
magnetBottom.GetComponent<SpriteRenderer>().enabled = true;
}
else
{
magnetLeft.GetComponent<SpriteRenderer>().enabled = true;
magnetRight.GetComponent<SpriteRenderer>().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
}
}