2025-01-10 16:14:33 -05:00
using System.Collections ;
2025-01-17 20:11:04 -05:00
using TMPro ;
2025-03-08 13:33:19 -05:00
using Unity.IO.LowLevel.Unsafe ;
2025-04-16 19:57:54 -04:00
using UnityEngine ; using Game ; using Music ; using Player ;
2025-01-10 16:14:33 -05:00
using UnityEngine.InputSystem ;
2025-04-16 19:57:54 -04:00
namespace Player
{
2025-01-10 16:14:33 -05:00
2025-01-17 19:46:17 -05:00
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(BoxCollider2D))]
[RequireComponent(typeof(PlayerInput))]
[RequireComponent(typeof(AnimationPlayer))]
[RequireComponent(typeof(Punch))]
2025-01-10 16:14:33 -05:00
public class PlayerMovement : MonoBehaviour
{
[Header("Ground Layers")]
public LayerMask ground ;
2025-01-17 20:11:04 -05:00
public TextMeshProUGUI playerText ;
2025-01-10 16:14:33 -05:00
[Header("Movement")]
public float walkSpeed ;
2025-03-28 17:39:07 -04:00
public float walkSpeedFactor = 1f ; // Sets walk speed
public float maxSpeed = 5f ; // Sets max speed
2025-02-08 18:54:21 -05:00
public float maxSpeedOverride ;
2025-03-28 17:39:07 -04:00
public float slowdownMultiplier = 10f ; // Sets slow walk speed
2025-01-10 16:14:33 -05:00
public float virtualAxisX ;
public float virtualButtonJump ;
public float virtualButtonJumpLastFrame ;
2025-03-28 17:39:07 -04:00
public float turnaroundMultiplier = 2 ; // Sets speed when turning around
2025-01-10 16:14:33 -05:00
public float walkSmooth ;
public float secondsToFullSpeed ;
public float jumpSpeed ;
public float coyoteTime ;
public float jumpLenience ;
2025-03-28 17:39:07 -04:00
public float timeUnableToBeDeclaredNotJumping = 0.1f ; // Jump threshold
2025-01-10 16:14:33 -05:00
public float groundCheckDistance ;
private Rigidbody2D body ;
private BoxCollider2D collide ;
2025-01-14 11:40:09 -05:00
private PlayerInput input ;
2025-01-17 19:46:17 -05:00
private AnimationPlayer animationPlayer ;
private Punch punch ;
2025-03-07 10:46:30 -05:00
private Damageable damageable ;
2025-01-17 19:46:17 -05:00
2025-01-10 16:14:33 -05:00
private bool jumpInputStillValid = false ;
private bool canBeDeclaredNotJumping = true ;
private bool jumpPhysics ;
private bool jumping ;
2025-03-28 17:39:07 -04:00
private float lastTimeJumpPressed ;
2025-01-10 16:14:33 -05:00
private float lastTimeOnGround ;
private Vector3 positionLastFrame ;
2025-03-28 17:39:07 -04:00
void Start ( ) // Sets up player components
2025-01-10 16:14:33 -05:00
{
2025-02-08 18:54:21 -05:00
maxSpeedOverride = maxSpeed ;
2025-01-15 14:07:17 -05:00
GetComponent < RespawnOnTriggerEnter > ( ) . spawnPoint = transform . position ;
2025-01-10 16:14:33 -05:00
body = GetComponent < Rigidbody2D > ( ) ;
collide = GetComponent < BoxCollider2D > ( ) ;
2025-01-14 11:40:09 -05:00
input = GetComponent < PlayerInput > ( ) ;
2025-01-17 19:46:17 -05:00
animationPlayer = GetComponent < AnimationPlayer > ( ) ;
punch = GetComponent < Punch > ( ) ;
2025-03-07 10:46:30 -05:00
damageable = GetComponent < Damageable > ( ) ;
2025-01-17 20:11:04 -05:00
playerText . text = input . playerIndex . ToString ( ) ;
2025-01-10 16:14:33 -05:00
}
2025-03-28 17:39:07 -04:00
private void Update ( ) // Updates player movement
2025-01-10 16:14:33 -05:00
{
2025-03-25 11:56:06 -04:00
if ( GameManager . Instance ! = null & & GameManager . Instance . gameOver ) maxSpeed = 1f ;
2025-03-28 17:39:07 -04:00
if ( damageable . dying ) return ;
2025-03-07 10:46:30 -05:00
2025-01-10 16:14:33 -05:00
Jump ( ) ;
UpdateVirtualAxis ( ) ;
}
private void FixedUpdate ( )
{
JumpPhysics ( ) ;
HorizontalMovement ( ) ;
Land ( ) ;
}
2025-03-28 17:39:07 -04:00
private void LateUpdate ( )
2025-01-15 16:55:07 -05:00
{
2025-01-17 19:46:17 -05:00
Animate ( ) ;
2025-01-15 16:55:07 -05:00
}
2025-03-28 17:39:07 -04:00
private void Animate ( ) // Sets player animation
2025-01-15 16:55:07 -05:00
{
if ( ! IsPhysicallyGrounded ( ) )
animationPlayer . SetState ( AnimationPlayer . AnimationState . Jump ) ;
else
{
2025-04-16 19:20:36 -04:00
if ( Mathf . Abs ( virtualAxisX ) > = 0.05f )
2025-03-08 13:33:19 -05:00
animationPlayer . SetState ( GameManager . Instance . gameOver ? AnimationPlayer . AnimationState . Walk : AnimationPlayer . AnimationState . Run ) ;
2025-01-15 16:55:07 -05:00
else
animationPlayer . SetState ( AnimationPlayer . AnimationState . Idle ) ;
}
2025-04-16 19:20:36 -04:00
if ( true )
{
if ( virtualAxisX < - 0.01f )
animationPlayer . backwards = true ;
else if ( virtualAxisX > 0.01f )
animationPlayer . backwards = false ;
}
else
{
if ( body . linearVelocityX < - 0.1f )
animationPlayer . backwards = true ;
else if ( body . linearVelocityX > 0.1f )
animationPlayer . backwards = false ;
}
2025-01-15 16:55:07 -05:00
}
2025-03-28 17:39:07 -04:00
private void Land ( ) // Stops jumping when player lands
2025-01-10 16:14:33 -05:00
{
if ( body . linearVelocity . y > = 0f ) return ;
if ( IsPhysicallyGrounded ( ) )
{
if ( canBeDeclaredNotJumping )
{
jumping = false ;
}
}
}
2025-03-28 17:39:07 -04:00
private void Jump ( ) // Player jumps when 'jump' is pressed
2025-01-10 16:14:33 -05:00
{
if ( virtualButtonJumpLastFrame = = 1f )
{
jumpInputStillValid = true ;
lastTimeJumpPressed = Time . time ;
}
bool isBasicallyGrounded = IsBasicallyGrounded ( ) ;
if ( ( virtualButtonJumpLastFrame = = 1f & & isBasicallyGrounded & & jumping = = false ) // Coyote Jump: Must have jump pressed this frame and be grounded in last time frame and not be actually jumping.
| | ( jumpInputStillValid & & Time . time - lastTimeJumpPressed < = jumpLenience & & IsPhysicallyGrounded ( ) ) ) // Buffered Jump: Must have pressed jump in the last time frame and be jumping
{
2025-04-12 17:24:51 -04:00
AudioManager . Instance . PlaySound ( "Jump" ) ;
2025-01-10 16:14:33 -05:00
jumpPhysics = true ;
jumping = true ;
jumpInputStillValid = false ;
StartCoroutine ( NotJumpingDelay ( ) ) ;
}
}
2025-03-28 17:39:07 -04:00
private void JumpPhysics ( ) // Applies jump physics
2025-01-10 16:14:33 -05:00
{
if ( jumpPhysics )
{
2025-02-09 17:18:51 -05:00
if ( ! GetComponent < Block > ( ) . blocking )
2025-02-08 18:54:21 -05:00
{
2025-02-09 17:18:51 -05:00
if ( body . linearVelocity . y < 0 | | ! IsPhysicallyGrounded ( ) ) body . linearVelocity = new Vector2 ( body . linearVelocity . x , 0 ) ;
body . AddForce ( Vector2 . up * jumpSpeed , ForceMode2D . Impulse ) ;
if ( Mathf . Abs ( body . linearVelocityX ) > maxSpeed )
{
body . linearVelocity = new Vector2 ( Mathf . Sign ( body . linearVelocityX ) * maxSpeed , body . linearVelocity . y ) ;
}
2025-02-08 18:54:21 -05:00
}
2025-01-10 16:14:33 -05:00
jumpPhysics = false ;
}
if ( ! IsPhysicallyGrounded ( ) & & ! ( virtualButtonJump = = 1f ) )
body . AddForce ( Vector2 . down * jumpSpeed ) ;
}
2025-03-28 17:39:07 -04:00
private IEnumerator NotJumpingDelay ( ) // Sets jump threshold
2025-01-10 16:14:33 -05:00
{
canBeDeclaredNotJumping = false ;
yield return new WaitUntil ( ( ) = > ! IsBasicallyGrounded ( ) ) ;
canBeDeclaredNotJumping = true ;
}
2025-03-28 17:39:07 -04:00
private void HorizontalMovement ( ) // Sets player horizontal movement
2025-01-10 16:14:33 -05:00
{
2025-02-08 18:54:21 -05:00
float temporaryMax = IsPhysicallyGrounded ( ) ? maxSpeedOverride : Mathf . Infinity ;
float temporarySlowdown = IsPhysicallyGrounded ( ) ? slowdownMultiplier : 1 ;
2025-01-17 19:46:17 -05:00
2025-02-09 17:18:51 -05:00
if ( ! GetComponent < Block > ( ) . blocking & & ( Mathf . Abs ( body . linearVelocityX ) < = maxSpeed | | Mathf . Sign ( body . linearVelocityX ) ! = Mathf . Sign ( virtualAxisX ) ) )
2025-02-08 18:54:21 -05:00
{
body . AddForce ( new Vector2 ( virtualAxisX * walkSpeed * walkSpeedFactor , 0 ) , ForceMode2D . Force ) ;
}
2025-01-13 15:58:50 -05:00
2025-02-08 18:54:21 -05:00
if ( Mathf . Abs ( body . linearVelocityX ) > = temporaryMax )
2025-01-13 15:58:50 -05:00
{
2025-02-08 18:54:21 -05:00
body . AddForce ( new Vector2 ( - Mathf . Sign ( body . linearVelocityX ) * ( Mathf . Abs ( body . linearVelocityX ) - temporaryMax ) * temporarySlowdown , 0 ) ) ;
2025-01-13 15:58:50 -05:00
}
2025-01-14 11:40:09 -05:00
if ( transform . position = = positionLastFrame & & ( input . actions . FindAction ( "Move" ) . ReadValue < Vector2 > ( ) . x = = 0 ) )
2025-01-10 16:14:33 -05:00
{
virtualAxisX = 0 ;
}
2025-02-09 17:18:51 -05:00
if ( GetComponent < Block > ( ) . blocking )
{
body . AddForce ( new Vector2 ( - body . linearVelocityX * 0.8f , 0 ) , ForceMode2D . Force ) ;
}
2025-01-10 16:14:33 -05:00
positionLastFrame = transform . position ;
}
2025-03-28 17:39:07 -04:00
private void UpdateVirtualAxis ( ) // Updates virtual axis
2025-01-10 16:14:33 -05:00
{
2025-01-14 11:40:09 -05:00
virtualButtonJump = input . actions . FindAction ( "Action" ) . ReadValue < float > ( ) ;
virtualButtonJumpLastFrame = input . actions . FindAction ( "Action" ) . WasPressedThisFrame ( ) ? 1 : 0 ;
2025-01-13 15:58:50 -05:00
2025-01-14 11:40:09 -05:00
virtualAxisX = input . actions . FindAction ( "Move" ) . ReadValue < Vector2 > ( ) . x ;
2025-01-13 15:58:50 -05:00
return ;
2025-01-10 16:14:33 -05:00
}
2025-01-14 11:40:09 -05:00
2025-03-28 17:39:07 -04:00
public bool IsBasicallyGrounded ( ) // Checks if player is on land within a threshold
2025-01-10 16:14:33 -05:00
{
if ( IsPhysicallyGrounded ( ) )
{
lastTimeOnGround = Time . time ;
}
if ( Time . time - lastTimeOnGround < coyoteTime )
{
return true ;
}
return false ;
}
2025-03-28 17:39:07 -04:00
public bool IsPhysicallyGrounded ( ) // Checks if player is on land
2025-01-10 16:14:33 -05:00
{
RaycastHit2D leftCheck = Physics2D . Raycast ( GetPointInBoxCollider ( collide , - 1 , - 1 ) , Vector2 . down , groundCheckDistance , ground ) ;
RaycastHit2D rightCheck = Physics2D . Raycast ( GetPointInBoxCollider ( collide , 1 , - 1 ) , Vector2 . down , groundCheckDistance , ground ) ;
RaycastHit2D midCheck = Physics2D . Raycast ( GetPointInBoxCollider ( collide , 0 , - 1 ) , Vector2 . down , groundCheckDistance , ground ) ;
if ( leftCheck | | rightCheck | | midCheck )
{
return true ;
}
return false ;
}
2025-03-28 17:39:07 -04:00
public Vector2 GetPointInBoxCollider ( BoxCollider2D boxCollider2D , float horizontal , float vertical )
2025-01-10 16:14:33 -05:00
{
return new Vector2
(
boxCollider2D . bounds . center . x + ( horizontal * boxCollider2D . bounds . extents . x ) ,
boxCollider2D . bounds . center . y + ( vertical * boxCollider2D . bounds . extents . y )
) ;
}
2025-01-17 19:46:17 -05:00
2025-03-28 17:39:07 -04:00
public void StopVelocity ( ) // Stops inertia when landed
2025-01-17 19:46:17 -05:00
{
if ( IsPhysicallyGrounded ( ) ) body . linearVelocity = Vector2 . zero ;
}
2025-01-10 16:14:33 -05:00
}
2025-04-16 19:57:54 -04:00
}