diff --git a/Assets/Prefabs/Fighters/AntiPlayer.prefab b/Assets/Prefabs/Fighters/AntiPlayer.prefab index c0b004d428ed310afd7bae0be86d861b06f6dc79..11218cee1d42bf67b7198f6dbc766b748b87d8a5 100644 --- a/Assets/Prefabs/Fighters/AntiPlayer.prefab +++ b/Assets/Prefabs/Fighters/AntiPlayer.prefab @@ -69,7 +69,6 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 8413529789942519730} - - component: {fileID: 9043920546160527475} - component: {fileID: 7070326077254508316} - component: {fileID: 2655505060201611074} - component: {fileID: 2954181336601895002} @@ -101,23 +100,6 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &9043920546160527475 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6323719953710832613} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0f5034bc83802944c9bca57c55e08978, type: 3} - m_Name: - m_EditorClassIdentifier: - m_speed: 4 - m_jumpForce: 7.5 - m_rollForce: 6 - m_noBlood: 0 - m_slideDust: {fileID: 1038168246061390451, guid: 8b8c8cc6774fb074cb9139cc631b108e, type: 3} --- !u!114 &7070326077254508316 MonoBehaviour: m_ObjectHideFlags: 0 @@ -135,6 +117,7 @@ MonoBehaviour: baseAttackDamage: 10 baseArmor: 1 currentHealth: 100 + maxDistanceToEnemy: 1 --- !u!95 &2655505060201611074 Animator: serializedVersion: 3 diff --git a/Assets/Prefabs/Fighters/Bandit.prefab b/Assets/Prefabs/Fighters/Bandit.prefab index cfa6ee483b0522814550aab131669f96cf4c8af6..c37169e53dc6e376cc318ce4a12e117ec04d29ab 100644 --- a/Assets/Prefabs/Fighters/Bandit.prefab +++ b/Assets/Prefabs/Fighters/Bandit.prefab @@ -9,7 +9,6 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 4805181885227780} - - component: {fileID: 114850797635947820} - component: {fileID: 6293755257358992638} - component: {fileID: 95346456782871180} - component: {fileID: 212259381048184306} @@ -37,20 +36,6 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &114850797635947820 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1689866831511430} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: ba8b435a8dc3f604e9a13c4acd7081c2, type: 3} - m_Name: - m_EditorClassIdentifier: - m_speed: 4 - m_jumpForce: 7.5 --- !u!114 &6293755257358992638 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/Fighters/Tank.prefab b/Assets/Prefabs/Fighters/Tank.prefab index 3aa9efa14551d12efabc3ac297875787f0bd6e54..a4646e0b5edab3ca32d70fbec702f0bae9c96bff 100644 --- a/Assets/Prefabs/Fighters/Tank.prefab +++ b/Assets/Prefabs/Fighters/Tank.prefab @@ -79,7 +79,6 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 4588935210562790} - - component: {fileID: 114999745408315450} - component: {fileID: 1594948182104342364} - component: {fileID: 95734438044755836} - component: {fileID: 212652212501150786} @@ -107,20 +106,6 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &114999745408315450 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1463392086428580} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: ba8b435a8dc3f604e9a13c4acd7081c2, type: 3} - m_Name: - m_EditorClassIdentifier: - m_speed: 4 - m_jumpForce: 7.5 --- !u!114 &1594948182104342364 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Fighters/AntiPlayer.cs b/Assets/Scripts/Fighters/AntiPlayer.cs index 4fed837e2aaa734a4838e58a09b781d38b4bd1dd..3074b432e0aaeeb8167e6cd05da83ffac8cbfc82 100644 --- a/Assets/Scripts/Fighters/AntiPlayer.cs +++ b/Assets/Scripts/Fighters/AntiPlayer.cs @@ -2,14 +2,68 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public class AntiPlayer : Fighter +public class AntiPlayer : Fighter, IFighterCallback { - string[] attacks = new string[] { "Attack1", "Attack2", "Attack3" }; + [SerializeField, Tooltip("How close the AntiPlayer has to be to start attacking, or how far away it has to be to start running towards the target")] + float maxDistanceToEnemy = 1f; + [SerializeField] float movementSpeed = 4f; + + List<Fighter> enemies = new List<Fighter>(); + Fighter currentTargetEnemy; + string[] attackAnimationTriggers = new string[] { "Attack1", "Attack2", "Attack3" }; + + protected override void Awake() + { + base.Awake(); + // TODO Eventually, the player will be able to place enemies _after_ the AntiPlayer has been created. + // Idea: Create a global GameManager-like class where scripts can register an IGameState callback, + // which has a `OnRoundStart()` callback. + foreach (var enemy in GameObject.FindGameObjectsWithTag("Enemy")) + { + enemies.Add(enemy.GetComponent<Fighter>()); + } + CalculateClosestEnemy(); + animator.SetBool("Grounded", true); + } + + protected override void Update() + { + base.Update(); + + var vectorToNextEnemy = currentTargetEnemy.transform.position - transform.position; + spriteRenderer.flipX = vectorToNextEnemy.x < 0; + if (Mathf.Abs(vectorToNextEnemy.x) > maxDistanceToEnemy) + { + animator.SetInteger("AnimState", 1); // Run + rigidbody.velocity = new Vector2(Mathf.Sign(vectorToNextEnemy.x) * movementSpeed, rigidbody.velocity.y); + } else + { + animator.SetInteger("AnimState", 0); + rigidbody.velocity = new Vector2(0, rigidbody.velocity.y); + } + } + protected override bool CanAttack() + { + // Can only attack when near an Enemy + var vectorToNextEnemy = currentTargetEnemy.transform.position - transform.position; + return Mathf.Abs(vectorToNextEnemy.x) <= maxDistanceToEnemy; + } protected override void Attack() { - animator.SetTrigger(attacks[Random.Range(0, attacks.Length)]); + animator.SetTrigger(attackAnimationTriggers[Random.Range(0, attackAnimationTriggers.Length)]); } + void CalculateClosestEnemy() + { + enemies.Sort((a, b) => (int)Mathf.Sign(Vector3.Distance(transform.position, a.transform.position) - Vector3.Distance(transform.position, b.transform.position))); + currentTargetEnemy = enemies[0]; + } + + public void OnFighterDeath(Fighter fighter) + { + enemies.Remove(fighter); + CalculateClosestEnemy(); + } } diff --git a/Assets/Scripts/Fighters/Bandit.cs b/Assets/Scripts/Fighters/Bandit.cs index 81865ecf77d23f7cfbadcedc02f3fe53ef1739ad..4f3d17aeb8f75ecd0165811862dd10518c78acaf 100644 --- a/Assets/Scripts/Fighters/Bandit.cs +++ b/Assets/Scripts/Fighters/Bandit.cs @@ -11,13 +11,12 @@ public class Bandit : Fighter float playerDistanceToAttack = 1.25f; GameObject antiPlayer; - SpriteRenderer spriteRenderer; protected override void Awake() { base.Awake(); - spriteRenderer = GetComponent<SpriteRenderer>(); antiPlayer = GameObject.FindGameObjectWithTag("AntiPlayer"); + animator.SetBool("Grounded", true); } protected override void Update() @@ -37,12 +36,14 @@ public class Bandit : Fighter spriteRenderer.flipX = transform.position.x < antiPlayer.transform.position.x; } + protected override bool CanAttack() + { + return GetDistanceToAntiPlayer() < playerDistanceToAttack; + } + protected override void Attack() { - if (GetDistanceToAntiPlayer() < playerDistanceToAttack) - { - animator.SetTrigger("Attack"); - } + animator.SetTrigger("Attack"); } float GetDistanceToAntiPlayer() diff --git a/Assets/Scripts/Fighters/Fighter.cs b/Assets/Scripts/Fighters/Fighter.cs index 2fced3b898f502f82135b6e61ce00a257cfbea76..fdfd8d9805df22c742bbbc7c4591258a4027ca02 100644 --- a/Assets/Scripts/Fighters/Fighter.cs +++ b/Assets/Scripts/Fighters/Fighter.cs @@ -4,7 +4,7 @@ using UnityEngine; public interface IFighterCallback { - void OnDeath(); + void OnFighterDeath(Fighter fighter); } // Generic subclass for any Fighter on the field, whether it's an Enemy or the AntiPlayer. @@ -21,15 +21,20 @@ public abstract class Fighter : MonoBehaviour [SerializeField] protected int currentHealth = 100; protected Animator animator; + protected new Rigidbody2D rigidbody; + protected SpriteRenderer spriteRenderer; protected bool alive { get => currentHealth > 0; } protected FighterTypes fighterType; + protected abstract bool CanAttack(); protected abstract void Attack(); - float timeSinceLastAttack = 0f; + float timeSinceLastAttack = float.PositiveInfinity; protected virtual void Awake() { animator = GetComponent<Animator>(); + rigidbody = GetComponent<Rigidbody2D>(); + spriteRenderer = GetComponent<SpriteRenderer>(); fighterType = FighterTypes.ENEMY; } @@ -42,12 +47,19 @@ public abstract class Fighter : MonoBehaviour { if (alive) { - timeSinceLastAttack += Time.deltaTime; - var timeUntilNextAttack = baseAttackSpeed - timeSinceLastAttack; - if (timeUntilNextAttack <= 0) // TODO only attack when near opposing faction + if (CanAttack()) { - Attack(); - timeSinceLastAttack = -timeUntilNextAttack; // To account for overshoot + timeSinceLastAttack += Time.deltaTime; + var timeUntilNextAttack = baseAttackSpeed - timeSinceLastAttack; + if (timeUntilNextAttack <= 0) + { + Attack(); + timeSinceLastAttack = float.IsInfinity(timeUntilNextAttack) ? 0 : -timeUntilNextAttack; // To account for overshoot + } + } + else + { + timeSinceLastAttack = float.PositiveInfinity; } } } @@ -63,7 +75,7 @@ public abstract class Fighter : MonoBehaviour if (currentHealth == 0) { animator.SetTrigger("Death"); - callbacks.ForEach(c => c.OnDeath()); + callbacks.ForEach(c => c.OnFighterDeath(this)); // TODO (Depending on the death animation) only destroy on round end so that corpses stay on the ground // Destroy(gameObject); } @@ -78,6 +90,7 @@ public abstract class Fighter : MonoBehaviour return StatsManager.instance.fighterStats[fighterType]; } + // TODO Move to new common Enemy subclass which also has reference to AnitPlayer void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag("AntiPlayer")) diff --git a/Assets/Scripts/Fighters/Tank.cs b/Assets/Scripts/Fighters/Tank.cs index 43866350ccde5c67af8029b84d7112168e0b8cf8..1f51d26c427da8e88492c4e00f2de690e8473046 100644 --- a/Assets/Scripts/Fighters/Tank.cs +++ b/Assets/Scripts/Fighters/Tank.cs @@ -11,13 +11,12 @@ public class Tank : Fighter float playerDistanceToAttack = 1.25f; GameObject antiPlayer; - SpriteRenderer spriteRenderer; protected override void Awake() { base.Awake(); - spriteRenderer = GetComponent<SpriteRenderer>(); antiPlayer = GameObject.FindGameObjectWithTag("AntiPlayer"); + animator.SetBool("Grounded", true); } protected override void Update() @@ -37,12 +36,14 @@ public class Tank : Fighter spriteRenderer.flipX = transform.position.x < antiPlayer.transform.position.x; } + protected override bool CanAttack() + { + return GetDistanceToAntiPlayer() < playerDistanceToAttack; + } + protected override void Attack() { - if (GetDistanceToAntiPlayer() < playerDistanceToAttack) - { - animator.SetTrigger("Attack"); - } + animator.SetTrigger("Attack"); } float GetDistanceToAntiPlayer()