diff --git a/Assets/Scripts/Bunker.cs b/Assets/Scripts/Bunker.cs index 4f5fa55..f81c7b5 100644 --- a/Assets/Scripts/Bunker.cs +++ b/Assets/Scripts/Bunker.cs @@ -17,23 +17,23 @@ public class Bunker : MonoBehaviour /// /// The sprite renderer component of the bunker. /// - private SpriteRenderer _spriteRenderer; + public SpriteRenderer spriteRenderer { get; private set; } /// /// The box collider component of the bunker. /// - private BoxCollider2D _collider; + public new BoxCollider2D collider { get; private set; } /// /// The original texture of the sprite so we can clone it. /// - private Texture2D _originalTexture; + public Texture2D originalTexture { get; private set; } private void Awake() { - _spriteRenderer = GetComponent(); - _collider = GetComponent(); - _originalTexture = _spriteRenderer.sprite.texture; + this.spriteRenderer = GetComponent(); + this.collider = GetComponent(); + this.originalTexture = this.spriteRenderer.sprite.texture; ResetBunker(); } @@ -42,7 +42,7 @@ public void ResetBunker() { // Each bunker needs a unique instance of the sprite texture since we // will be modifying it at the source - CopyTexture(_originalTexture); + CopyTexture(this.originalTexture); this.gameObject.SetActive(true); } @@ -58,8 +58,8 @@ private void CopyTexture(Texture2D source) copy.Apply(); // Create a new sprite using the copied texture - Sprite sprite = Sprite.Create(copy, _spriteRenderer.sprite.rect, new Vector2(0.5f, 0.5f), _spriteRenderer.sprite.pixelsPerUnit); - _spriteRenderer.sprite = sprite; + Sprite sprite = Sprite.Create(copy, this.spriteRenderer.sprite.rect, new Vector2(0.5f, 0.5f), this.spriteRenderer.sprite.pixelsPerUnit); + this.spriteRenderer.sprite = sprite; } public bool CheckPoint(Vector3 hitPoint, out int px, out int py) @@ -69,14 +69,14 @@ public bool CheckPoint(Vector3 hitPoint, out int px, out int py) // Offset the point to the corner of the object instead of the center so // we can transform to uv coordinates - localPoint.x += _collider.size.x / 2; - localPoint.y += _collider.size.y / 2; + localPoint.x += this.collider.size.x / 2; + localPoint.y += this.collider.size.y / 2; - Texture2D texture = _spriteRenderer.sprite.texture; + Texture2D texture = this.spriteRenderer.sprite.texture; // Transform the point from local space to uv coordinates - px = (int)((localPoint.x / _collider.size.x) * texture.width); - py = (int)((localPoint.y / _collider.size.y) * texture.height); + px = (int)((localPoint.x / this.collider.size.x) * texture.width); + py = (int)((localPoint.y / this.collider.size.y) * texture.height); // Return true if the pixel is not empty (not transparent) return texture.GetPixel(px, py).a != 0.0f; @@ -92,7 +92,7 @@ public bool Splat(Vector3 hitPoint) return false; } - Texture2D texture = _spriteRenderer.sprite.texture; + Texture2D texture = this.spriteRenderer.sprite.texture; // Offset the point by half the size of the splat texture so the splat // is centered around the hit point @@ -121,7 +121,6 @@ public bool Splat(Vector3 hitPoint) py++; } - // Apply any changes made to the texture texture.Apply(); return true; diff --git a/Assets/Scripts/GameManager.cs b/Assets/Scripts/GameManager.cs index 83e7b98..5e9dd1a 100644 --- a/Assets/Scripts/GameManager.cs +++ b/Assets/Scripts/GameManager.cs @@ -65,18 +65,15 @@ private void Awake() private void Start() { - // Register callbacks for game state this.player.killed += OnPlayerKilled; this.mysteryShip.killed += OnMysteryShipKilled; this.invaders.killed += OnInvaderKilled; - // Start a new game NewGame(); } private void Update() { - // Start a new game once the player presses 'Return' if (this.lives <= 0 && Input.GetKeyDown(KeyCode.Return)) { NewGame(); } @@ -84,74 +81,57 @@ private void Update() private void NewGame() { - // Hide the game over UI this.gameOverUI.SetActive(false); - // Reset score and lives SetScore(0); SetLives(3); - - // Start the first round NewRound(); } private void NewRound() { - // Reset all of the invaders this.invaders.ResetInvaders(); this.invaders.gameObject.SetActive(true); - // Reset all of the bunkers for (int i = 0; i < this.bunkers.Length; i++) { this.bunkers[i].ResetBunker(); } - // Spawn the player Respawn(); } private void Respawn() { - // Reset the position of the player Vector3 position = this.player.transform.position; position.x = 0.0f; this.player.transform.position = position; - - // Re-enable the player game object this.player.gameObject.SetActive(true); } private void GameOver() { - // Show the game over UI and hide the invaders this.gameOverUI.SetActive(true); this.invaders.gameObject.SetActive(false); } private void SetScore(int score) { - // Set score and update UI text this.score = score; this.scoreText.text = this.score.ToString().PadLeft(4, '0'); } private void SetLives(int lives) { - // Set lives and update UI text this.lives = Mathf.Max(lives, 0); this.livesText.text = this.lives.ToString(); } private void OnPlayerKilled() { - // Decrement lives by 1 SetLives(this.lives - 1); - // Temporarily disable the player game object this.player.gameObject.SetActive(false); - // Start the round over again after 1 second or trigger the game over - // state if out of lives if (this.lives > 0) { Invoke(nameof(NewRound), 1.0f); } else { @@ -161,10 +141,8 @@ private void OnPlayerKilled() private void OnInvaderKilled(Invader invader) { - // Increment score by how much the invader is worth SetScore(this.score + invader.score); - // Start a new round after all invaders have been killed if (this.invaders.AmountKilled == this.invaders.TotalAmount) { NewRound(); } @@ -172,7 +150,6 @@ private void OnInvaderKilled(Invader invader) private void OnMysteryShipKilled(MysteryShip mysteryShip) { - // Increment score by how much the mystery ship is worth SetScore(this.score + mysteryShip.score); } diff --git a/Assets/Scripts/Invader.cs b/Assets/Scripts/Invader.cs index 32646d1..f3c9540 100644 --- a/Assets/Scripts/Invader.cs +++ b/Assets/Scripts/Invader.cs @@ -9,7 +9,7 @@ public class Invader : MonoBehaviour /// /// The sprite renderer component of the invader. /// - private SpriteRenderer _spriteRenderer; + public SpriteRenderer spriteRenderer { get; private set; } /// /// The sprites that are animated on the invader. @@ -26,7 +26,7 @@ public class Invader : MonoBehaviour /// /// The index of the current sprite being rendered. /// - private int _animationFrame; + public int animationFrame { get; private set; } /// /// The amount of points the invader is worth when killed. @@ -41,34 +41,29 @@ public class Invader : MonoBehaviour private void Awake() { - // Get a reference to the sprite renderer so we can animate the sprite - _spriteRenderer = GetComponent(); - _spriteRenderer.sprite = this.animationSprites[0]; + this.spriteRenderer = GetComponent(); + this.spriteRenderer.sprite = this.animationSprites[0]; } private void Start() { - // Start an animation loop to cycle between sprites InvokeRepeating(nameof(AnimateSprite), this.animationTime, this.animationTime); } private void AnimateSprite() { - // Move to the next animation frame - _animationFrame++; + this.animationFrame++; // Loop back to the start if the animation frame exceeds the length - if (_animationFrame >= this.animationSprites.Length) { - _animationFrame = 0; + if (this.animationFrame >= this.animationSprites.Length) { + this.animationFrame = 0; } - // Set the sprite based on the current animation frame - _spriteRenderer.sprite = this.animationSprites[_animationFrame]; + this.spriteRenderer.sprite = this.animationSprites[this.animationFrame]; } private void OnTriggerEnter2D(Collider2D other) { - // The invader dies when hit by the laser if (other.gameObject.layer == LayerMask.NameToLayer("Laser")) { this.killed?.Invoke(this); } diff --git a/Assets/Scripts/Invaders.cs b/Assets/Scripts/Invaders.cs index 5dae95f..276007c 100644 --- a/Assets/Scripts/Invaders.cs +++ b/Assets/Scripts/Invaders.cs @@ -28,7 +28,7 @@ public class Invaders : MonoBehaviour /// /// The initial position of the invaders so they can be reset. /// - private Vector3 _initialPosition; + public Vector3 initialPosition { get; private set; } /// /// The callback invoked when an invader is killed. @@ -83,8 +83,7 @@ public class Invaders : MonoBehaviour private void Awake() { - // Store the initial position so we can reset after each round - _initialPosition = this.transform.position; + this.initialPosition = this.transform.position; // Form the grid of invaders for (int i = 0; i < this.rows; i++) @@ -111,7 +110,6 @@ private void Awake() private void Start() { - // Invoke a missile attack every given amount of seconds InvokeRepeating(nameof(MissileAttack), this.missileSpawnRate, this.missileSpawnRate); } @@ -145,8 +143,6 @@ private void Update() { // Evaluate the speed of the invaders based on how many have been killed float speed = this.speed.Evaluate(this.PercentKilled); - - // Move all of the invaders in the current direction this.transform.position += this.direction * speed * Time.deltaTime; // Transform the viewport to world coordinates so we can check when the @@ -190,27 +186,18 @@ private void AdvanceRow() private void OnInvaderKilled(Invader invader) { - // Disable the invader that was killed invader.gameObject.SetActive(false); - // Increment the amount of invaders killed so the game manager can check - // if they are all dead this.AmountKilled++; - - // Invoke the kill callback this.killed(invader); } public void ResetInvaders() { - // Reset state this.AmountKilled = 0; this.direction = Vector3.right; + this.transform.position = this.initialPosition; - // Reset the position of the invaders back to the top - this.transform.position = _initialPosition; - - // Re-enable all of the invaders that were killed foreach (Transform invader in this.transform) { invader.gameObject.SetActive(true); } diff --git a/Assets/Scripts/MysteryShip.cs b/Assets/Scripts/MysteryShip.cs index 8e5c433..d475d89 100644 --- a/Assets/Scripts/MysteryShip.cs +++ b/Assets/Scripts/MysteryShip.cs @@ -32,23 +32,23 @@ public class MysteryShip : MonoBehaviour /// The destination point of the mystery ship on the left edge of the /// screen. /// - private Vector3 _leftDestination; + public Vector3 leftDestination { get; private set; } /// /// The destination point of the mystery ship on the right edge of the /// screen. /// - private Vector3 _rightDestination; + public Vector3 rightDestination { get; private set; } /// /// The direction the mystery ship is traveling, 1=right, -1=left. /// - private int _direction = -1; + public int direction { get; private set; } = -1; /// /// Whether the mystery ship is currently spawned. /// - private bool _spawned; + public bool spawned { get; private set; } private void Start() { @@ -57,14 +57,17 @@ private void Start() Vector3 leftEdge = Camera.main.ViewportToWorldPoint(Vector3.zero); Vector3 rightEdge = Camera.main.ViewportToWorldPoint(Vector3.right); - _leftDestination = this.transform.position; - _leftDestination.x = leftEdge.x - 1.0f; + // Offset the destination by a unit so the ship is fully out of sight + Vector3 left = this.transform.position; + left.x = leftEdge.x - 1.0f; + this.leftDestination = left; - _rightDestination = this.transform.position; - _rightDestination.x = rightEdge.x + 1.0f; + Vector3 right = this.transform.position; + right.x = rightEdge.x + 1.0f; + this.rightDestination = right; - // Position the mystery ship initially on the left side of the screen - this.transform.position = _leftDestination; + // Start on the left side of the screen + this.transform.position = this.leftDestination; // Make sure the mystery ship is initially despawned. This will also // start the spawn cycle timer. @@ -74,30 +77,30 @@ private void Start() private void Spawn() { // Flip the direction so it moves the opposite way each time it spawns - _direction *= -1; + this.direction *= -1; // Set the spawn point opposite side of the destination - if (_direction == 1) { - this.transform.position = _leftDestination; + if (this.direction == 1) { + this.transform.position = this.leftDestination; } else { - this.transform.position = _rightDestination; + this.transform.position = this.rightDestination; } // Mark as spawned so it starts moving - _spawned = true; + this.spawned = true; } private void Despawn() { // Mark as despawned so it stops moving - _spawned = false; + this.spawned = false; // Move the mystery ship to the destination point so it is hidden off // the screen - if (_direction == 1) { - this.transform.position = _rightDestination; + if (this.direction == 1) { + this.transform.position = this.rightDestination; } else { - this.transform.position = _leftDestination; + this.transform.position = this.leftDestination; } // Start the timer again to respawn the mystery ship @@ -107,17 +110,17 @@ private void Despawn() private void Update() { // Do not do anything if the mystery ship is not moving - if (!_spawned) { + if (!this.spawned) { return; } - if (_direction == 1) + if (this.direction == 1) { // Move the mystery ship to the right based on its speed this.transform.position += Vector3.right * this.speed * Time.deltaTime; // Despawn the mystery ship once it exceeds the right screen edge - if (this.transform.position.x >= _rightDestination.x) { + if (this.transform.position.x >= this.rightDestination.x) { Despawn(); } } @@ -127,7 +130,7 @@ private void Update() this.transform.position += Vector3.left * this.speed * Time.deltaTime; // Despawn the mystery ship once it exceeds the left screen edge - if (this.transform.position.x <= _leftDestination.x) { + if (this.transform.position.x <= this.leftDestination.x) { Despawn(); } } @@ -135,8 +138,6 @@ private void Update() private void OnTriggerEnter2D(Collider2D other) { - // The mystery ship despawns when hit by a laser and the callback is - // invoked so score can be increased if (other.gameObject.layer == LayerMask.NameToLayer("Laser")) { Despawn(); diff --git a/Assets/Scripts/Player.cs b/Assets/Scripts/Player.cs index 6f7ca02..add510e 100644 --- a/Assets/Scripts/Player.cs +++ b/Assets/Scripts/Player.cs @@ -26,7 +26,7 @@ public class Player : MonoBehaviour /// Whether a laser shot is currently active so we can ensure only one laser /// is active at a given time. /// - private bool _laserActive; + public bool laserActive { get; private set; } private void Update() { @@ -35,7 +35,8 @@ private void Update() // Check for input to move the player either left or right if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow)) { position.x -= this.speed * Time.deltaTime; - } else if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)) { + } + else if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow)) { position.x += this.speed * Time.deltaTime; } @@ -43,11 +44,8 @@ private void Update() Vector3 leftEdge = Camera.main.ViewportToWorldPoint(Vector3.zero); Vector3 rightEdge = Camera.main.ViewportToWorldPoint(Vector3.right); position.x = Mathf.Clamp(position.x, leftEdge.x, rightEdge.x); - - // Set the updated position of the player this.transform.position = position; - // Check for input to shoot a laser if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) { Shoot(); } @@ -57,12 +55,10 @@ private void Shoot() { // Only one laser can be active at a given time so first check that // there is not already an active laser - if (!_laserActive) + if (!this.laserActive) { - _laserActive = true; + this.laserActive = true; - // Create a new laser projectile and register a callback so we know - // when it is destroyed Projectile laser = Instantiate(this.laserPrefab, this.transform.position, Quaternion.identity); laser.destroyed += OnLaserDestroyed; } @@ -70,13 +66,12 @@ private void Shoot() private void OnLaserDestroyed(Projectile laser) { - // Deactivate the laser so we can fire again - _laserActive = false; + // Once the laser is destroyed we can shoot again + this.laserActive = false; } private void OnTriggerEnter2D(Collider2D other) { - // The player is killed when hit by a missile or invader if (other.gameObject.layer == LayerMask.NameToLayer("Missile") || other.gameObject.layer == LayerMask.NameToLayer("Invader")) { this.killed?.Invoke(); diff --git a/Assets/Scripts/Projectile.cs b/Assets/Scripts/Projectile.cs index f2c415f..5837726 100644 --- a/Assets/Scripts/Projectile.cs +++ b/Assets/Scripts/Projectile.cs @@ -26,11 +26,11 @@ public class Projectile : MonoBehaviour /// /// The box collider component of the projectile. /// - private BoxCollider2D _collider; + public new BoxCollider2D collider { get; private set; } private void Awake() { - _collider = GetComponent(); + this.collider = GetComponent(); } private void OnDestroy() @@ -40,7 +40,6 @@ private void OnDestroy() private void Update() { - // Move the projectile in the given direction by its speed this.transform.position += this.direction * this.speed * Time.deltaTime; } @@ -52,7 +51,7 @@ private void CheckCollision(Collider2D other) // The projectile is destroyed when colliding with any object other than // a bunker or when it splats on a bunker - if (bunker == null || bunker.CheckCollision(_collider, this.transform.position)) { + if (bunker == null || bunker.CheckCollision(this.collider, this.transform.position)) { Destroy(this.gameObject); } }