using Assets.Scripts.Enums; using Assets.Scripts.Helpers; using System; using UnityEngine; using UnityEngine.InputSystem; [RequireComponent(typeof(Rigidbody2D))] public class PlayerController : MonoBehaviour { public float moveSpeed = 5f; public float maxFallSpeed = -20f; public float maxFallSpeedDamge = -10f; private float maxFallSpeedCurrent = 0f; Vector2 moveInput; [NonSerialized] public Rigidbody2D rb; [NonSerialized] public Damageable health; BoxCollider2D boxCollider; Animator animator; Animator animator_rotor; public GameObject rotorGO; TouchingDirections touchingDirections; // Time it takes to drill private float drillingTime = 1f; private float timeSinceDrill = 0f; private bool drillToPosition; private Vector3 drillTilePosition; private Vector3 drillOriginalPosition; [SerializeField] private bool _isMoving; public bool IsMoving { get { return _isMoving; } private set { _isMoving = value; animator.SetBool(AnimationStrings.Player.isMoving, value); } } [SerializeField] private bool _isFlying; public bool IsFlying { get { return _isFlying; } private set { _isFlying = value; animator.SetBool(AnimationStrings.Player.isFlying, value); animator_rotor.SetBool(AnimationStrings.Player.isFlying, value); } } public bool IsDrilling { get { return IsDrillingDown || IsDrillingLeftRight; } set { if (value) { Debug.Assert(false, "Can't set IsDrilling this way, use IsDrillingLeftRight or IsDrillingDown!"); } if (IsDrillingDown) { IsDrillingDown = false; } if (IsDrillingLeftRight) { IsDrillingLeftRight = false; } } } [SerializeField] private bool _isDrillingLeftRight; public bool IsDrillingLeftRight { get { return _isDrillingLeftRight; } set { _isDrillingLeftRight = value; animator.SetBool(AnimationStrings.Player.isDrillingLeftRight, value); animator_rotor.SetBool(AnimationStrings.Player.isFlying, false); if (value) { animator.speed = 1 / drillingTime; } else { animator.speed = 1f; } } } [SerializeField] private bool _isDrillingDown; public bool IsDrillingDown { get { return _isDrillingDown; } set { _isDrillingDown = value; animator.SetBool(AnimationStrings.Player.isDrillingDown, value); animator_rotor.SetBool(AnimationStrings.Player.isFlying, false); if (value) { animator.speed = 1 / drillingTime; } else { animator.speed = 1f; } } } private bool _isFacingRight = true; public bool IsFacingRight { get { return _isFacingRight; } set { if (_isFacingRight != value) { transform.localScale *= new Vector2(-1, 1); } _isFacingRight = value; } } public bool CanMove { get { return animator.GetBool(AnimationStrings.canMove) && !PauseMenu.GameIsPaused && !IsDrilling; } } private void OnEnable() { CharacterEvents.characterDrillingToPosition += (DrillingToPosition); } private void OnDisable() { CharacterEvents.characterDrillingToPosition -= (DrillingToPosition); } private void Awake() { rb = GetComponent(); animator = GetComponent(); animator_rotor = rotorGO.GetComponent(); touchingDirections = GetComponent(); health = GetComponent(); boxCollider = GetComponent(); if (SaveSystem.isGameLoaded) { LoadPlayer(); } } private void LoadPlayer() { SaveDataPlayer save = SaveSystem.LoadPlayer(); health.MaxHealth = save.maxHealth; health.Health = save.health; transform.position = VectorHelper.ConvertToVector3(save.position); rb.velocity = VectorHelper.ConvertToVector2(save.velocity); } private void FixedUpdate() { if (CanMove) { if (moveInput.y == 0) { if (rb.velocity.y <= maxFallSpeed) { // max fall speed, dont accelerate more rb.velocity = new Vector2(moveInput.x * moveSpeed, maxFallSpeed); } else { // normal fall rb.velocity = new Vector2(moveInput.x * moveSpeed, rb.velocity.y); } } else { if (rb.velocity.y < 0 && moveInput.y > 0) { // falling but moving upwards rb.velocity = new Vector2(moveInput.x * moveSpeed, (moveInput.y * moveSpeed) + rb.velocity.y); } else { // moving upwards no falling rb.velocity = new Vector2(moveInput.x * moveSpeed, (moveInput.y * moveSpeed)); } } if (touchingDirections.IsGrounded) { if (maxFallSpeedCurrent < maxFallSpeedDamge) { TakeFallDamage(Math.Abs((int)maxFallSpeedCurrent)); maxFallSpeedCurrent = 0; } } else if (IsFlying) { maxFallSpeedCurrent = rb.velocity.y; } else { if (maxFallSpeedCurrent > rb.velocity.y) { maxFallSpeedCurrent = rb.velocity.y; } } if (touchingDirections.IsGrounded && moveInput.y < 0 && !IsDrilling) { //IsDrilling = true; Drill(DrillDirection.Down); } if (touchingDirections.IsGrounded && moveInput.x != 0 && !IsDrilling) { if (touchingDirections.IsAtWallLeft && moveInput.x < 0) { Drill(DrillDirection.Left); } else if (touchingDirections.IsAtWallRight && moveInput.x > 0) { Drill(DrillDirection.Right); } } } if (IsDrilling) { rb.velocity = Vector2.zero; if (drillToPosition) { if (timeSinceDrill < drillingTime) { gameObject.transform.position = Vector3.Lerp(drillOriginalPosition, drillTilePosition, timeSinceDrill / drillingTime); //Debug.Log("drillTilePosition: " + drillTilePosition); //Debug.Log("timeSinceDrill: " + timeSinceDrill); timeSinceDrill += Time.deltaTime; } else { boxCollider.enabled = true; IsDrilling = false; drillToPosition = false; timeSinceDrill = 0; } } } } public void OnMove(InputAction.CallbackContext context) { moveInput = context.ReadValue(); IsMoving = moveInput.x != 0; IsFlying = (moveInput.y != 0); SetFacingDirection(moveInput); if (IsDrilling) { IsMoving = false; IsFlying = false; //moveInput = Vector2.zero; } } private void Drill(DrillDirection drillDirection) { ContactPoint2D[] contactPoints = new ContactPoint2D[1]; //rb.GetContacts(contactPoints); switch (drillDirection) { case DrillDirection.Left: touchingDirections.wallHitsLeft[0].collider.GetContacts(contactPoints); break; case DrillDirection.Right: touchingDirections.wallHitsRight[0].collider.GetContacts(contactPoints); break; case DrillDirection.Down: touchingDirections.groundHits[0].collider.GetContacts(contactPoints); break; default: Debug.Assert(false, "Add DrillDirection here!"); break; } //Debug.Log(contactPoints[0].otherRigidbody?.gameObject.name); if (contactPoints[0].otherRigidbody?.name == "Tilemap") { boxCollider.enabled = false; switch (drillDirection) { case DrillDirection.Left: case DrillDirection.Right: IsDrillingLeftRight = true; break; case DrillDirection.Down: IsDrillingDown = true; break; default: Debug.Assert(false, "Add DrillDirection here!"); break; } CharacterEvents.characterDrill.Invoke(contactPoints[0], drillDirection); } } private void DrillingToPosition(Vector3 tilePosition) { //Debug.Log("DrillingToPosition() called"); //Debug.Log(gameObject.transform.position); drillToPosition = true; drillTilePosition = tilePosition; //Debug.Log("drillTilePosition: " + drillTilePosition); drillOriginalPosition = gameObject.transform.position; //Debug.Log("drillOriginalPosition: " + drillOriginalPosition); } //private void DrillLeftOrRight() //{ // ContactPoint2D[] contactPoints = new ContactPoint2D[1]; // touchingDirections.wallHits[0].collider.GetContacts(contactPoints); // CharacterEvents.characterDrillLeftOrRight.Invoke(contactPoints[0]); //} private void SetFacingDirection(Vector2 moveInput) { if (moveInput.x > 0 && !IsFacingRight) { IsFacingRight = true; } else if (moveInput.x < 0 && IsFacingRight) { IsFacingRight = false; } } public void TakeDamage(int damage) { health.Hit(damage); } public void TakeFallDamage(int fallDamage) { TakeDamage(fallDamage); } //public void OnRun(InputAction.CallbackContext context) //{ // if (context.started) // Button pressed // { // _isRunning = true; // } // else if (context.canceled) // Button released // { // _isRunning = false; // } //} }