From 18e95b16b61968c0aa9b9027722b8cd53ba864ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Nu=C8=9Biu?= Date: Wed, 21 Aug 2019 19:23:28 +0300 Subject: [PATCH] Implement enemy death animation --- .../Animations/Enemies/SnowEnemy.controller | 4 +- Assets/Scripts/src/Ammo/BombController.cs | 6 +- Assets/Scripts/src/Base/EnemyBase.cs | 225 ++++++++++-------- Assets/Scripts/src/Base/PlayerBase.cs | 4 +- .../src/Enemy/CollisionMovementEnemy.cs | 10 +- .../src/Enemy/Dummy/OneDirectionEnemy.cs | 14 +- .../Scripts/src/Enemy/RandomMovementEnemy.cs | 5 +- Assets/Scripts/src/Helpers/ListExtensions.cs | 10 +- Assets/Scripts/src/Interfaces/IExplosable.cs | 2 +- Assets/Scripts/src/Wall/DestructibleWall.cs | 2 +- 10 files changed, 152 insertions(+), 130 deletions(-) diff --git a/Assets/Animations/Enemies/SnowEnemy.controller b/Assets/Animations/Enemies/SnowEnemy.controller index f9b1b23..8a86dff 100644 --- a/Assets/Animations/Enemies/SnowEnemy.controller +++ b/Assets/Animations/Enemies/SnowEnemy.controller @@ -29,7 +29,7 @@ AnimatorState: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Dumber + m_Name: Normal m_Speed: 1 m_CycleOffset: 0 m_Transitions: [] @@ -59,7 +59,7 @@ AnimatorStateMachine: m_ChildStates: - serializedVersion: 1 m_State: {fileID: 1102746068587636566} - m_Position: {x: 200, y: 0, z: 0} + m_Position: {x: 336, y: 24, z: 0} m_ChildStateMachines: [] m_AnyStateTransitions: [] m_EntryTransitions: [] diff --git a/Assets/Scripts/src/Ammo/BombController.cs b/Assets/Scripts/src/Ammo/BombController.cs index 24ecf73..566044f 100644 --- a/Assets/Scripts/src/Ammo/BombController.cs +++ b/Assets/Scripts/src/Ammo/BombController.cs @@ -56,7 +56,7 @@ namespace src.Ammo { Debug.Log("Hit something"); var key = hit.collider.GetComponent(); - key?.onExplosion(); + key?.OnExplosion(); break; } } @@ -68,11 +68,11 @@ namespace src.Ammo { if (!_exploded && other.CompareTag("Explosion")) { - onExplosion(); + OnExplosion(); } } - public void onExplosion() + public void OnExplosion() { CancelInvoke(nameof(Explode)); Explode(); diff --git a/Assets/Scripts/src/Base/EnemyBase.cs b/Assets/Scripts/src/Base/EnemyBase.cs index 3912bd9..ecd3469 100644 --- a/Assets/Scripts/src/Base/EnemyBase.cs +++ b/Assets/Scripts/src/Base/EnemyBase.cs @@ -1,115 +1,136 @@ -using src.Helpers; -using src.Managers; -using System.Collections; +using System.Collections; using System.Collections.Generic; +using src.Helpers; +using src.Managers; using UnityEngine; -public abstract class EnemyBase : MonoBehaviour, IExplosable +namespace src.Base { - - protected Vector2[] _directions = { Vector3.up, Vector3.down, Vector3.left, Vector3.right }; - protected readonly GameStateManager gameStateManager = GameStateManager.Instance; - - protected Rigidbody2D Rigidbody2d { get; set; } - protected float Speed { get; set; } - protected Vector2 Direction { get; set; } - - private List _allowedDirections = new List(); - private bool _isStucked = false; - private System.Random _random = new System.Random(); - - // Start is called before the first frame update - protected void Start() + public abstract class EnemyBase : MonoBehaviour, IExplosable { - Direction = _directions.ChoseRandom(); - Rigidbody2d = GetComponent(); - } + private readonly Vector2[] _directions = {Vector3.up, Vector3.down, Vector3.left, Vector3.right}; + private readonly GameStateManager _gameStateManager = GameStateManager.Instance; - // Update is called once per frame - protected void FixedUpdate() - { - if (gameStateManager.IsGamePaused || gameStateManager.IsPlayerMovementForbidden) {return;} - if(_isStucked) + protected Rigidbody2D Rigidbody2d { get; set; } + private Collider2D Collider2D { get; set; } + private Animator Animator { get; set; } + protected float Speed { get; set; } + protected Vector2 Direction { get; set; } + + private readonly List _allowedDirections = new List(); + private bool _isStuck; + private bool _isDead; + + private static readonly int AnimExplode = Animator.StringToHash("animExplode"); + + // Start is called before the first frame update + protected void Start() { + Direction = _directions.ChoseRandom(); + Rigidbody2d = GetComponent(); + Collider2D = GetComponent(); + Animator = GetComponentInChildren(); + } + + // Update is called once per frame + protected void FixedUpdate() + { + if (_gameStateManager.IsGamePaused || _gameStateManager.IsPlayerMovementForbidden || _isDead) + { + return; + } + + if (_isStuck) + { + Unstuck(); + } + HandleMovement(); + } + + /// + /// This function is implemented by subclasses and should provided personalized movement logic. + /// + protected abstract void HandleMovement(); + + public void OnTriggerEnter2D(Collider2D other) + { + if (other.CompareTag("Explosion")) + { + OnExplosion(); + } + } + + public void OnExplosion() + { + Collider2D.enabled = false; + _isDead = true; + Animator.SetTrigger(AnimExplode); + Destroy(gameObject, 1); + } + + public void OnCollisionEnter2D(Collision2D col) + { + MoveToCenterOfTheCell(); Unstuck(); } - Rigidbody2d.MovePosition(Rigidbody2d.position + Speed * Time.deltaTime * Direction); - } - public void OnTriggerEnter2D(Collider2D other) - { - if (other.CompareTag("Explosion")) + public void OnCollisionStay2D(Collision2D col) { - onExplosion(); + MoveToCenterOfTheCell(); + Unstuck(); + } + + protected void MoveToCenterOfTheCell() + { + var position = transform.position; + var absX = Mathf.RoundToInt(position.x); + var absY = Mathf.RoundToInt(position.y); + var newPosition = new Vector2(absX, absY); + transform.SetPositionAndRotation(newPosition, Quaternion.identity); + } + + protected Vector2 ChooseRandomDirection() + { + return _directions.ChoseRandom(); + } + + protected Vector2 ChooseRandomExceptCertainDirection(Vector2 direction) + { + return _directions.ChoseRandomExcept(direction); + } + + private void Unstuck() + { + _allowedDirections.Clear(); + StartCoroutine(CheckForObstacle(Vector3.down)); + StartCoroutine(CheckForObstacle(Vector3.left)); + StartCoroutine(CheckForObstacle(Vector3.up)); + StartCoroutine(CheckForObstacle(Vector3.right)); + if (_allowedDirections.Count == 0) + { + _isStuck = true; + } + else + { + Direction = _allowedDirections.PeekRandom(); + _isStuck = false; + } + } + + private IEnumerator CheckForObstacle(Vector3 direction) + { + const int layerMask = 1 << 8; // Block layer + var currentPosition = transform.position; + + var hit = Physics2D.Raycast(new Vector2(currentPosition.x + 0.5f, currentPosition.y + 0.5f), + direction, 1, layerMask); + + if (!hit.collider) + { + _allowedDirections.Add(direction); + } + + yield return new WaitForSeconds(0.05f); } } - - public void onExplosion() - { - Destroy(gameObject); - } - - public void OnCollisionEnter2D(Collision2D col) - { - MoveToCenterOfTheCell(); - Unstuck(); - } - - public void OnCollisionStay2D(Collision2D col) - { - MoveToCenterOfTheCell(); - Unstuck(); - } - - protected void MoveToCenterOfTheCell() - { - var absX = Mathf.RoundToInt(transform.position.x); - var absY = Mathf.RoundToInt(transform.position.y); - Vector2 position = new Vector2(absX, absY); - transform.SetPositionAndRotation(position, Quaternion.identity); - } - - protected Vector2 ChooseRandomDirection() - { - return _directions.ChoseRandom(); - } - - protected Vector2 ChooseRandomExceptCertainDirection(Vector2 direction) - { - return _directions.ChoseRandomExcept(direction); - } - - private void Unstuck() - { - _allowedDirections.Clear(); - StartCoroutine(CheckForObstacle(Vector3.down)); - StartCoroutine(CheckForObstacle(Vector3.left)); - StartCoroutine(CheckForObstacle(Vector3.up)); - StartCoroutine(CheckForObstacle(Vector3.right)); - if(_allowedDirections.Count == 0) - { - _isStucked = true; - } - else - { - var index = _random.Next(_allowedDirections.Count); - Direction = _allowedDirections[index]; - _isStucked = false; - } - } - - private IEnumerator CheckForObstacle(Vector3 direction) - { - var layerMask = (1 << 8) | (1 << 9); - var currentPosition = transform.position; - - var hit = Physics2D.Raycast(new Vector2(currentPosition.x + 0.5f, currentPosition.y + 0.5f), direction, 1, layerMask); - - if (!hit.collider) - { - _allowedDirections.Add(direction); - } - - yield return new WaitForSeconds(0.05f); - } -} +} \ No newline at end of file diff --git a/Assets/Scripts/src/Base/PlayerBase.cs b/Assets/Scripts/src/Base/PlayerBase.cs index 2009d37..cb72621 100644 --- a/Assets/Scripts/src/Base/PlayerBase.cs +++ b/Assets/Scripts/src/Base/PlayerBase.cs @@ -20,7 +20,7 @@ namespace src.Base { if (other.CompareTag("Explosion")) { - onExplosion(); + OnExplosion(); } if (other.CompareTag("Enemy")) { @@ -28,7 +28,7 @@ namespace src.Base } } - public void onExplosion() + public void OnExplosion() { DebugHelper.LogInfo("Player hit by explosion"); } diff --git a/Assets/Scripts/src/Enemy/CollisionMovementEnemy.cs b/Assets/Scripts/src/Enemy/CollisionMovementEnemy.cs index 8ab5849..a1865ce 100644 --- a/Assets/Scripts/src/Enemy/CollisionMovementEnemy.cs +++ b/Assets/Scripts/src/Enemy/CollisionMovementEnemy.cs @@ -1,4 +1,7 @@ -namespace src.Enemy +using src.Base; +using UnityEngine; + +namespace src.Enemy { public class CollisionMovementEnemy : EnemyBase /* Enemy that will change direction only on collision. */ @@ -9,10 +12,9 @@ base.Start(); } - protected new void FixedUpdate() + protected override void HandleMovement() { - base.FixedUpdate(); + Rigidbody2d.MovePosition(Rigidbody2d.position + Speed * Time.deltaTime * Direction); } - } } diff --git a/Assets/Scripts/src/Enemy/Dummy/OneDirectionEnemy.cs b/Assets/Scripts/src/Enemy/Dummy/OneDirectionEnemy.cs index f0b7d8b..cc27dad 100644 --- a/Assets/Scripts/src/Enemy/Dummy/OneDirectionEnemy.cs +++ b/Assets/Scripts/src/Enemy/Dummy/OneDirectionEnemy.cs @@ -1,27 +1,21 @@ -using UnityEngine; +using src.Base; +using UnityEngine; -namespace Assets.Scripts.src.Enemy.Dummy +namespace src.Enemy.Dummy { //This kind of enemy is used just for testing purposes //This enemy will go just in one direction or stays in place //To make it stay in place, don't assign any direction in OneDirection slot or assign Vector2.zero public class OneDirectionEnemy : EnemyBase { - public Vector2 OneDirection = Vector2.zero; - protected new void Start() { Speed = 4.0f; Rigidbody2d = GetComponent(); } - protected new void FixedUpdate() + protected override void HandleMovement() { - if (OneDirection != Vector2.zero) - { - if (gameStateManager.IsGamePaused || gameStateManager.IsPlayerMovementForbidden) { return; } - Rigidbody2d.MovePosition(Rigidbody2d.position + OneDirection * Speed * Time.deltaTime); - } } } } diff --git a/Assets/Scripts/src/Enemy/RandomMovementEnemy.cs b/Assets/Scripts/src/Enemy/RandomMovementEnemy.cs index 32b9da4..91b226b 100644 --- a/Assets/Scripts/src/Enemy/RandomMovementEnemy.cs +++ b/Assets/Scripts/src/Enemy/RandomMovementEnemy.cs @@ -1,5 +1,5 @@ using System; -using src.Helpers; +using src.Base; using UnityEngine; namespace src.Enemy @@ -13,12 +13,11 @@ namespace src.Enemy base.Start(); } - protected new void FixedUpdate() + protected override void HandleMovement() { var pos = transform.position; var x = pos.x; var y = pos.y; - if (gameStateManager.IsGamePaused || gameStateManager.IsPlayerMovementForbidden) { return; } if (Math.Abs(x - Mathf.Floor(x)) < 0.1 && Math.Abs(y - Mathf.Floor(y)) < 0.1) { if (RandomChange()) diff --git a/Assets/Scripts/src/Helpers/ListExtensions.cs b/Assets/Scripts/src/Helpers/ListExtensions.cs index 16cbb50..2054670 100644 --- a/Assets/Scripts/src/Helpers/ListExtensions.cs +++ b/Assets/Scripts/src/Helpers/ListExtensions.cs @@ -12,7 +12,7 @@ namespace src.Helpers var max = list.Count - 1; for (var i = min; i < max; i++) { - var randomPos = Mathf.FloorToInt(Random.Range(min, max)); + var randomPos = Random.Range(min, max); /* Swap elements in list */ var aux = list[randomPos]; @@ -23,10 +23,16 @@ namespace src.Helpers public static T PopRandom(this IList list) { - var randomIndex = Mathf.FloorToInt(Random.Range(0, list.Count - 1)); + var randomIndex = Random.Range(0, list.Count - 1); var elem = list[randomIndex]; list.RemoveAt(randomIndex); return elem; } + + public static T PeekRandom(this IList list) + { + var randomIndex = Random.Range(0, list.Count - 1); + return list[randomIndex]; + } } } \ No newline at end of file diff --git a/Assets/Scripts/src/Interfaces/IExplosable.cs b/Assets/Scripts/src/Interfaces/IExplosable.cs index a05c711..ad86730 100644 --- a/Assets/Scripts/src/Interfaces/IExplosable.cs +++ b/Assets/Scripts/src/Interfaces/IExplosable.cs @@ -4,5 +4,5 @@ using UnityEngine; public interface IExplosable { - void onExplosion(); + void OnExplosion(); } diff --git a/Assets/Scripts/src/Wall/DestructibleWall.cs b/Assets/Scripts/src/Wall/DestructibleWall.cs index b839da3..d27663e 100644 --- a/Assets/Scripts/src/Wall/DestructibleWall.cs +++ b/Assets/Scripts/src/Wall/DestructibleWall.cs @@ -60,7 +60,7 @@ namespace src.Wall // _animator.speed = 10; } - public void onExplosion() + public void OnExplosion() { DebugHelper.LogInfo($"Destructible wall hit by explosion {transform.position}"); PlayDestroyAnimation();