Untitled

mail@pastecode.io avatarunknown
plain_text
2 months ago
12 kB
3
Indexable
Never
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;

public class Player : MonoBehaviour
{
   public static Player Instance { get; private set; }

   public event EventHandler OnStateChanged;
   
   public State currentState;
   

   [SerializeField] private float angularDrag;
   [SerializeField] private State startState;
   [SerializeField] private Transform grenadeSpawnPosition;
   [SerializeField] private float throwStrength;
   [SerializeField] private bool isActive = true;
  

   
   
  
   
   [Header("Movement")]
   [SerializeField] private float moveSpeed;
   [SerializeField] private float accelerationForce;
   [SerializeField] private float deccelerationForce;
   [SerializeField] private float velPower;
   
   [SerializeField] private float friction;
   
   [Header("Jump")]
   [SerializeField] private float jumpForce;
   [SerializeField] private float doubleJumpForce;
   [SerializeField] private float jumpCutMultiplier;
   [SerializeField] private float jumpCutMultiplierDoubleJump;
   [SerializeField] private float jumpCoyoteTime;
   [SerializeField] private float jumpBufferTime;
   [SerializeField] private float gravityScale;
   [SerializeField] private float fallGravityMultiplier;
   [SerializeField] private float additionalAirTimePeakStrength;
   
   [Header("Checks")]
   [SerializeField] private Transform groundCheckPoint;
   [SerializeField] private Vector2 groundCheckSize;
   [SerializeField] private LayerMask groundLayer;
   
   [Header("GrenadeForce")]
   [SerializeField] private float testForce;
   [SerializeField] private Vector2 testVector;
   [SerializeField] private AnimationCurve yCurve;
   [SerializeField] private AnimationCurve xCurve;
   [SerializeField] private AnimationCurve accelerationCurve;
   [SerializeField] private float duration;
   
   
   
   private Rigidbody2D playerRigidbody;
   private bool isJumping;
   private bool isFiringGrenade;
   private bool isGrounded;
   private bool isDoingSomethingElseThanIdle;
   private State lastState;
   private Vector2 moveDir;
   private float moveInput;
   private Vector3 mousePosition;
   public bool justShoot;
   private float scrollWheelInput;
   private CollectableSO lastFiredCollectableSO;
   private bool stillJumping;
   private float lastGroundedTime;
   private float lastJumpTime;
   private bool jumpInputReleased = false;
   private bool reducingJumpForce = false;

   public CollectableSO collectableSoLeftMouse;
   public CollectableSO collectableSoRightMouse;



   #region PrivateVariables

   private bool canDoubleJump = false;
   private bool isDoubleJumping = false;
   
   

   #endregion
   
   public enum State
   {
      Start,
      Idle,
      Jump,
      Fall,
      ThrowingBomb,
      GotHitMelee,
      GotHitPink
   }

   private void Awake()
   {
      Instance = this;
      currentState = startState;
      lastState = State.Start;
      isDoingSomethingElseThanIdle = false;
   }

   private void Start()
   {
      playerRigidbody = GetComponent<Rigidbody2D>();
      playerRigidbody.angularDrag = angularDrag;
      if (!isActive)
      {
         this.gameObject.SetActive(false);
      }
   }

   private void Update()
   {

      mousePosition = Input.mousePosition;
      moveInput = Input.GetAxisRaw("Horizontal");

      OrientateCharacterLook();

      if (Input.GetKeyDown(KeyCode.Q))
      {
         TestPhysics();
      }

      if (Input.GetKeyDown(KeyCode.W))
      {
         #region Jump

         jumpInputReleased = false;

         lastJumpTime = jumpBufferTime;
         #endregion

      }

      if (Input.GetKeyUp(KeyCode.W))
      {
         OnJumpUp();
      }

      if (Input.GetKeyDown(KeyCode.Mouse0))
      {
         isFiringGrenade = true;
         FiringGrenade(true);
      }

      if (Input.GetKeyDown(KeyCode.Mouse1) && !isFiringGrenade )
      {
         isFiringGrenade = true;
         FiringGrenade(false);
      }
      
      

      if (currentState != lastState)
      {
         lastState = currentState;
         OnStateChanged?.Invoke(this, EventArgs.Empty);
      }
      
      scrollWheelInput = Input.GetAxis("Mouse ScrollWheel");
      if (scrollWheelInput != 0)
      {
         ChangeLeftAndRightAttachedCollectableSO();
         PlayerInventory.Instance.UpdateInventory();
      }

      #region Timer

      lastGroundedTime -= Time.deltaTime;
      lastJumpTime -= Time.deltaTime;
      
      #endregion
      
      Debug.DrawRay(transform.position, -transform.up*5,Color.green);
      
   }

   private void FixedUpdate()
   {
      
      #region Run
      
         float targetSpeed = moveInput * moveSpeed;

         float speedDif = targetSpeed - playerRigidbody.velocity.x;

         float accelRate = (Mathf.Abs(targetSpeed) > 0.01f) ? accelerationForce : deccelerationForce;

         float movement = Mathf.Pow(Mathf.Abs(speedDif) * accelRate, velPower) * Mathf.Sign(speedDif);
      
         playerRigidbody.AddForce(movement * Vector2.right);
      
      #endregion


      #region Friction

         if (moveInput == 0)
         {
            float amount = Mathf.Min(Mathf.Abs(playerRigidbody.velocity.x), Mathf.Abs(friction));
            
            amount *= Mathf.Sign(playerRigidbody.velocity.x);
         
            playerRigidbody.AddForce(Vector2.right * -amount, ForceMode2D.Impulse);
         }
         
      #endregion

      #region GroundCheck

         if (Physics2D.OverlapBox(groundCheckPoint.position, groundCheckSize, 0, groundLayer))
         {
            isGrounded = true;
            isJumping = false;
            lastGroundedTime = jumpCoyoteTime;
            currentState = State.Idle;
            canDoubleJump = false;
            isDoubleJumping = false;
         }
         /*
         else
         {
            canDoubleJump = true;
         }
 */
      #endregion
      
      #region Jump
      
      if (lastGroundedTime > 0 && lastJumpTime > 0 && !isJumping && !canDoubleJump)
      {
         Debug.Log("JUMP");
         Jump();
         currentState = State.Jump;
         canDoubleJump = true;
      }
      else if (canDoubleJump  && !isDoubleJumping && lastJumpTime > 0)
      {
         Debug.Log("DoubleJump");
         isDoubleJumping = true;
         DoubleJump();
      }
         
      #endregion

      #region Jump Gravity

         if (isJumping && playerRigidbody.velocity.y < 0.1f && playerRigidbody.velocity.y > -0.1f)
         {
            playerRigidbody.AddForce(Vector2.up * additionalAirTimePeakStrength);
         }
         if (playerRigidbody.velocity.y < 0)
         {
            playerRigidbody.gravityScale = gravityScale * fallGravityMultiplier;
            if(!isGrounded) currentState = State.Fall;
         }
         else
         {
            playerRigidbody.gravityScale = gravityScale;
         }
         
      #endregion
      
     

   }

   private void Jump()
   {
      playerRigidbody.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
      lastGroundedTime = 0;
      lastJumpTime = 0;
      isJumping = true;
      jumpInputReleased = false;
   }
   
   private void DoubleJump()
   {
      playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, doubleJumpForce);
      //playerRigidbody.AddForce(Vector2.up * doubleJumpForce, ForceMode2D.Impulse);
      lastGroundedTime = 0;
      lastJumpTime = 0;
      jumpInputReleased = false;
   }

   private void OnJumpUp()
   {
      if (playerRigidbody.velocity.y > 0 && (isJumping && !isDoubleJumping))
      {
         playerRigidbody.AddForce(Vector2.down * playerRigidbody.velocity.y * (1 - jumpCutMultiplier));
      }
      else if (playerRigidbody.velocity.y > 0 && (isDoubleJumping))
      {
         playerRigidbody.AddForce(Vector2.down * playerRigidbody.velocity.y * (1 - jumpCutMultiplierDoubleJump));
      }

      jumpInputReleased = true;
      lastJumpTime = 0;
   }

   private void FiringGrenade(bool leftMouse)
   {
      Debug.Log("---------------------------------------------------");
      Vector2 grenadeDir = CalculateGrenadeDirNormalized();
      lastFiredCollectableSO = leftMouse ? collectableSoLeftMouse : collectableSoRightMouse;
      
      Transform grenadePrefab = lastFiredCollectableSO?.prefab;
      if (grenadePrefab == null)
      {
         Debug.Log("Mouse doesnt contain any item");
         isFiringGrenade = false;
         return;
      }
      Debug.Log(lastFiredCollectableSO.name + " has " + PlayerInventory.Instance.playerInventoryDictionary[lastFiredCollectableSO] + " item");

      PlayerInventory.Instance.playerInventoryDictionary[lastFiredCollectableSO] -= 1;
      Debug.Log(lastFiredCollectableSO.name + " now has " + PlayerInventory.Instance.playerInventoryDictionary[lastFiredCollectableSO] + " item");

      if (PlayerInventory.Instance.playerInventoryDictionary[lastFiredCollectableSO] == 0)
      {
         if (leftMouse)
         {
            collectableSoLeftMouse = null;
         }
         else
         {
            collectableSoRightMouse = null;
         }
      }
      
      Transform grenade = Instantiate(grenadePrefab, grenadeSpawnPosition.position, Quaternion.identity);
      Rigidbody2D rbGrenade = grenade.GetComponent<Rigidbody2D>();
      rbGrenade.AddForce(grenadeDir *  throwStrength * lastFiredCollectableSO.recoilForce,ForceMode2D.Impulse);
      
      PlayerInventory.Instance.UpdateInventory(lastFiredCollectableSO);
      Debug.Log("trigger");
      Debug.Log("---------------------------------------------------");
   }

   private void OrientateCharacterLook()
   {
      if (moveInput == 0) return;
      Vector3 currentScale = transform.localScale;
      currentScale.x = moveInput * 3.5f;
      transform.localScale = currentScale;
   }

   private Vector2 CalculateGrenadeDirNormalized()
   {
      Vector2 grenadeDir;
      Vector3 worldPosition = Camera.main.ScreenToWorldPoint(mousePosition);
      worldPosition.z = 0;
      if (mousePosition != Vector3.zero)
      {
         grenadeDir = worldPosition - transform.position;
      }
      else
      {
         grenadeDir = (transform.up + transform.right) * throwStrength;
      }

      grenadeDir = grenadeDir.normalized;
      if (grenadeDir.y > 0.5f) grenadeDir.y += 1f;
      if (grenadeDir.x > 0.5) grenadeDir.x += 0.2f;
      
      if (Mathf.Sign(transform.localScale.x) != Mathf.Sign(grenadeDir.x))
      {
         //return transform.right * Mathf.Sign(transform.localScale.x);
         
         //or rotate
         Vector3 currentScale = transform.localScale;
         currentScale.x = -currentScale.x;
         transform.localScale = currentScale;
      }
      
      return grenadeDir;
   }

   private void ChangeLeftAndRightAttachedCollectableSO()
   {
      CollectableSO temp = collectableSoLeftMouse;
      collectableSoLeftMouse = collectableSoRightMouse;
      collectableSoRightMouse = temp;
   }

   private void TestPhysics()
   {
      StartCoroutine(ApplyExplosionForce(playerRigidbody, testVector * testForce));
   }
   
   private IEnumerator ApplyExplosionForce(Rigidbody2D rb, Vector2 force)
   {
      float elapsedTime = 0f;
       // Adjust the duration to control the acceleration speed

      while (elapsedTime < duration)
      {
         float normalizedTime = elapsedTime / duration;

         force = new Vector2(xCurve.Evaluate(normalizedTime) * force.x, yCurve.Evaluate(normalizedTime) * force.y);
         
         
         float accelerationFactor = accelerationCurve.Evaluate(normalizedTime);

         rb.AddForce(force * accelerationFactor, ForceMode2D.Force);

         elapsedTime += Time.deltaTime;
         yield return null;
      }
   }
}