using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class PlayerController : MonoBehaviour { [Header("Editable player setting")] [SerializeField] private float speed = 2.5f; [SerializeField] private float force = 4.0f; [SerializeField] private float shootForce = 5; [SerializeField] private float reloadTime = 5; [SerializeField] private int minimalHeight = -10; [SerializeField] private Vector3 direction; [SerializeField] private Arrow arrow; [SerializeField] private Transform arrowSpawnPoint; [SerializeField] private int arrowsCount = 3; [SerializeField] private Rigidbody2D m_Rigidbody2D; [SerializeField] private SpriteRenderer m_SpriteRenderer; [SerializeField] private GroundDetection m_GroundDetection; [SerializeField] private Animator m_Animator; [SerializeField] private BuffReceiver buffReceiver; [SerializeField] private Health _health; public bool IsEnd { get; private set; } public float ReloadTimer { get; private set; } public float Force { get => force; set => force = value; } private List arrowPool; private bool isJumping; private bool isReloaded; private Arrow arrowPrefab; private float bonusForce; private float bonusDamage; private float bonusHealth; private UICharacterController controller; private static readonly int Speed = Animator.StringToHash("Speed"); private static readonly int IsGrounded = Animator.StringToHash("isGrounded"); private static readonly int StartJump = Animator.StringToHash("StartJump"); private static readonly int StartFall = Animator.StringToHash("StartFall"); private static readonly int Shoot = Animator.StringToHash("Shoot"); #region Singletone public static PlayerController Instance { get; set; } #endregion public void InitUIController(UICharacterController uiController) { controller = uiController; controller.Jump.onClick.AddListener(CheckJump); controller.Fire.onClick.AddListener(CheckShoot); } private void Awake() { Instance = this; IsEnd = false; ReloadTimer = 0; } private void Start() { isReloaded = false; arrowPool = new List(); for (var i = 0; i < arrowsCount; i++) { var arrowTemp = Instantiate(arrow, arrowSpawnPoint); arrowPool.Add(arrowTemp); arrowTemp.gameObject.SetActive(false); } buffReceiver.OnBuffChanged += ApplyBafs; } private void ApplyBafs() { var forceBuff = buffReceiver.Buffs.Find(t => t.type == BuffType.Force); var damageBuff = buffReceiver.Buffs.Find(t => t.type == BuffType.Damage); var armorBuff = buffReceiver.Buffs.Find(t => t.type == BuffType.Armor); bonusForce = forceBuff?.additiveBonus ?? 0; bonusHealth = armorBuff?.additiveBonus ?? 0; _health.SetHealth((int) bonusHealth); bonusDamage = damageBuff?.additiveBonus ?? 0; } private void Update() { if (isReloaded) { ReloadTimer += Time.deltaTime; return; } #if UNITY_EDITOR if (Input.GetKeyDown(KeyCode.Space)) { CheckJump(); } #endif } // Update is called once per frame private void FixedUpdate() { if (!IsEnd) { Move(); if (transform.position.y < minimalHeight) { SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); } } else { if (Input.GetKey(KeyCode.R)) { SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex); } } } // private void OnTriggerEnter2D(Collider2D other) { // if (other.gameObject.CompareTag("Finish")) { // if (!isEnd) { // isEnd = true; // } // } // } private void CheckShoot() { m_Animator.SetTrigger(Shoot); } private void Move() { m_Animator.SetBool(IsGrounded, m_GroundDetection.isGrounded); if (!isJumping && !m_GroundDetection.isGrounded) { m_Animator.SetTrigger(StartFall); } isJumping = isJumping && !m_GroundDetection.isGrounded; direction = Vector3.zero; #if UNITY_EDITOR if (Input.GetKey(KeyCode.A)) { direction = Vector3.left; m_SpriteRenderer.flipX = true; } if (Input.GetKey(KeyCode.D)) { direction = Vector3.right; m_SpriteRenderer.flipX = false; } #endif if (controller.Left.IsPressed) { direction = Vector3.left; m_SpriteRenderer.flipX = true; } if (controller.Right.IsPressed) { direction = Vector3.right; m_SpriteRenderer.flipX = false; } direction *= speed; direction.y = m_Rigidbody2D.velocity.y; m_Animator.SetFloat(Speed, Mathf.Abs(direction.x)); m_Rigidbody2D.velocity = direction; } private Arrow GetArrowFromPool() { if (arrowPool.Count > 0) { var arrowTemp = arrowPool[0]; arrowPool.Remove(arrowTemp); arrowTemp.gameObject.SetActive(true); arrowTemp.transform.parent = null; arrowTemp.transform.position = arrowSpawnPoint.transform.position; return arrowTemp; } return Instantiate(arrow, arrowSpawnPoint.position, Quaternion.identity); } public void ReturnArrowToPool(Arrow arrowTemp) { if (!arrowPool.Contains(arrowTemp)) { arrowPool.Add(arrowTemp); } arrowTemp.transform.parent = arrowSpawnPoint; arrowTemp.transform.position = arrowSpawnPoint.transform.position; arrowTemp.GetComponent().constraints = RigidbodyConstraints2D.FreezePositionY; arrowTemp.gameObject.SetActive(false); } public void ShowArrowBeforeShoot() { var tmpPos = arrowSpawnPoint.position; var position = tmpPos; position = new Vector3(m_SpriteRenderer.flipX ? position.x - 0.75f: position.x, position.y, position.z); arrowSpawnPoint.position = position; arrowPrefab = GetArrowFromPool(); arrowPrefab.SetImpulse(Vector2.right, 0, 0, this); arrowPrefab.transform.rotation = Quaternion.Euler(0, m_SpriteRenderer.flipX ? 180 : 0, 0); arrowSpawnPoint.position = tmpPos; } public void ShootArrow() { arrowPrefab.GetComponent().constraints = RigidbodyConstraints2D.None; arrowPrefab.SetImpulse(Vector2.right, m_SpriteRenderer.flipX ? -force * shootForce : force * shootForce, (int) bonusDamage, this); isReloaded = true; StartCoroutine(nameof(Reload)); } private IEnumerator Reload() { isReloaded = true; yield return new WaitForSeconds(reloadTime); isReloaded = false; ReloadTimer = 0; } public void CheckJump() { if (m_GroundDetection.isGrounded) { Jump(); } } public void Jump() { m_Rigidbody2D.velocity = Vector2.zero; m_Rigidbody2D.AddForce(Vector2.up * (force + bonusForce), ForceMode2D.Impulse); m_Animator.SetTrigger(StartJump); isJumping = true; } }