added comments and organized project files
This commit is contained in:
35
Assets/Scripts/Player/AnimationPlayer.cs
Normal file
35
Assets/Scripts/Player/AnimationPlayer.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(Animator))]
|
||||
public class AnimationPlayer : MonoBehaviour
|
||||
{
|
||||
public enum AnimationState { Idle, Run, Jump, Walk };
|
||||
public AnimationState state;
|
||||
public bool backwards;
|
||||
public bool block = false;
|
||||
public AnimationClip clip;
|
||||
private Animator animator;
|
||||
|
||||
private void Start() // Plays the specified animation clip
|
||||
{
|
||||
animator = GetComponent<Animator>();
|
||||
animator.Play(clip.name);
|
||||
}
|
||||
|
||||
private void LateUpdate() // Updates the animation state
|
||||
{
|
||||
animator.SetInteger("state", (int)state);
|
||||
transform.localScale = new Vector3(Mathf.Sign(backwards ? -1 : 1) * Mathf.Abs(transform.localScale.x), transform.localScale.y, transform.localScale.z);
|
||||
animator.SetBool("block", block);
|
||||
}
|
||||
|
||||
public void SetState(AnimationState state) // Sets the animation state
|
||||
{
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void Punch() // Triggers punch animation
|
||||
{
|
||||
animator.SetTrigger("punch");
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/AnimationPlayer.cs.meta
Normal file
2
Assets/Scripts/Player/AnimationPlayer.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e9d01bde449c4d0fa146e06804d6a03
|
||||
57
Assets/Scripts/Player/Block.cs
Normal file
57
Assets/Scripts/Player/Block.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
[RequireComponent(typeof(PlayerInput))]
|
||||
public class Block : MonoBehaviour
|
||||
{
|
||||
public bool blocking = false;
|
||||
private InputActionAsset actions;
|
||||
private float blockPressTime = 0f;
|
||||
[SerializeField] private float parryThreshold = 0.2f; // Time for successful parry
|
||||
private bool isParrying = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
actions = GetComponent<PlayerInput>().actions;
|
||||
}
|
||||
|
||||
private void Update() // Player blocks when "block" is pressed
|
||||
{
|
||||
InputAction blockAction = actions.FindAction("Block");
|
||||
if (blockAction.ReadValue<float>() == 1f)
|
||||
{
|
||||
if (!blocking)
|
||||
{
|
||||
blockPressTime = Time.time; // Start parry timer
|
||||
}
|
||||
blocking = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (blocking) // Successful parry if blocked in time
|
||||
{
|
||||
float pressDuration = Time.time - blockPressTime;
|
||||
if (pressDuration <= parryThreshold)
|
||||
{
|
||||
Parry();
|
||||
}
|
||||
else
|
||||
{
|
||||
isParrying = false;
|
||||
}
|
||||
}
|
||||
blocking = false;
|
||||
}
|
||||
GetComponent<AnimationPlayer>().block = blocking;
|
||||
}
|
||||
|
||||
private void Parry()
|
||||
{
|
||||
isParrying = true;
|
||||
}
|
||||
|
||||
public bool IsParrying()
|
||||
{
|
||||
return isParrying;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/Block.cs.meta
Normal file
2
Assets/Scripts/Player/Block.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8c9288561905664eade3f6b2634fc6d
|
||||
130
Assets/Scripts/Player/Damageable.cs
Normal file
130
Assets/Scripts/Player/Damageable.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
[RequireComponent(typeof(RespawnOnTriggerEnter))]
|
||||
public class Damageable : MonoBehaviour
|
||||
{
|
||||
public float force = 50f; // Force applied when hit
|
||||
public float damage = 0f;
|
||||
public float maxDamage = 1000f; // Set max health
|
||||
public int lives = 0;
|
||||
private Animator animator;
|
||||
public bool damageSelfDebug = false;
|
||||
public bool dying = false;
|
||||
public event System.Action<GameObject> OnPlayerPunched;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
animator = GetComponent<Animator>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (damageSelfDebug)
|
||||
{
|
||||
damageSelfDebug = false;
|
||||
Damage(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D collision) // Calls Damage method when player is hit
|
||||
{
|
||||
if (collision.gameObject.CompareTag("Punch Hurtbox"))
|
||||
{
|
||||
Damage(collision.transform.parent.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void Damage(GameObject damageSource) // Damages player
|
||||
{
|
||||
if (dying) return;
|
||||
|
||||
float actualForce = damageSource.GetComponent<Damageable>().force;
|
||||
Block blockComponent = GetComponent<Block>();
|
||||
|
||||
GetComponentInChildren<UseItem>().DropItem(); // Drops hat if held
|
||||
|
||||
if (blockComponent != null && blockComponent.blocking)
|
||||
{
|
||||
if (blockComponent.IsParrying()) // Player receives damage if punching a parrying player
|
||||
{
|
||||
damageSource.GetComponent<Damageable>().SuccessfulParry(gameObject, actualForce);
|
||||
return;
|
||||
}
|
||||
else // Player does less damage if punching a blocking player
|
||||
{
|
||||
actualForce /= 4;
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * actualForce, ForceMode2D.Force);
|
||||
}
|
||||
}
|
||||
else // Player does full damage to a non-blocking player
|
||||
{
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * actualForce * (1 + (damage / maxDamage) * 3), ForceMode2D.Force);
|
||||
}
|
||||
damage += actualForce;
|
||||
damage = Mathf.Clamp(damage, 0f, maxDamage);
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
public void Damage(float damage) // Adds damage to player when hit
|
||||
{
|
||||
this.damage += damage;
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
private void SuccessfulParry(GameObject damageSource, float force)
|
||||
{
|
||||
GetComponent<Rigidbody2D>().AddForce(((transform.position - damageSource.transform.position).normalized + Vector3.up * 2) * force, ForceMode2D.Force);
|
||||
damage += force;
|
||||
damage = Mathf.Clamp(damage, 0f, maxDamage);
|
||||
if (damage >= maxDamage)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
private void Die() // Triggers death animation and sets player to dying state
|
||||
{
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GetComponent<UseItem>().DropItem();
|
||||
animator.SetBool("die", true);
|
||||
dying = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleDeath() // Removes player from dying state after respawn
|
||||
{
|
||||
GameManager.Instance.PlayerDied(this);
|
||||
animator.SetBool("die", false);
|
||||
dying = false;
|
||||
}
|
||||
|
||||
public void Respawn() // Respawns player to the spawnPosition and resets damage/health bar
|
||||
{
|
||||
transform.position = GameManager.Instance.spawnPosition;
|
||||
if (TryGetComponent<Rigidbody2D>(out var rb))
|
||||
{
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
rb.angularVelocity = 0f;
|
||||
}
|
||||
if (TryGetComponent<Damageable>(out var damageable))
|
||||
{
|
||||
damageable.ResetDamage();
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetDamage()
|
||||
{
|
||||
damage = 0f;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/Damageable.cs.meta
Normal file
2
Assets/Scripts/Player/Damageable.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bac5d744efb2eb40be2220da2d52b35
|
||||
83
Assets/Scripts/Player/PlayerCameraMovement.cs
Normal file
83
Assets/Scripts/Player/PlayerCameraMovement.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerCameraMovement : MonoBehaviour
|
||||
{
|
||||
private Vector3 start;
|
||||
private Vector3 target;
|
||||
public float weight;
|
||||
public float speed;
|
||||
private GameObject playerThatWon;
|
||||
public float lowerBound;
|
||||
public bool winScene = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
start = transform.position;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (winScene) // If the game is over, the camera will follow the player that won
|
||||
{
|
||||
if (playerThatWon == null || !playerThatWon.activeInHierarchy)
|
||||
{
|
||||
playerThatWon = FindWinner();
|
||||
}
|
||||
|
||||
if (playerThatWon != null)
|
||||
{
|
||||
target = playerThatWon.transform.position;
|
||||
transform.position = Vector3.Lerp(transform.position, new Vector3(target.x, target.y, target.z - 10), speed * 12 * Time.deltaTime);
|
||||
if (transform.position.y < lowerBound)
|
||||
{
|
||||
transform.position = new Vector3(transform.position.x, lowerBound, transform.position.z);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
// Moves the camera to follow the players
|
||||
List<GameObject> players = GameManager.players;
|
||||
if (players.Count == 0) return;
|
||||
Vector3 playerAverage = Vector3.zero;
|
||||
int activePlayers = 0;
|
||||
foreach (GameObject player in players)
|
||||
{
|
||||
if (player == null || !player.activeInHierarchy) continue;
|
||||
Damageable damageable = player.GetComponent<Damageable>();
|
||||
if (damageable != null && damageable.dying) continue;
|
||||
playerAverage += player.transform.position;
|
||||
activePlayers++;
|
||||
}
|
||||
|
||||
if (activePlayers == 0) return;
|
||||
|
||||
playerAverage /= activePlayers;
|
||||
|
||||
target = start * weight + playerAverage * (1 - weight);
|
||||
transform.position = Vector3.Lerp(transform.position, new Vector3(target.x, target.y, transform.position.z), speed * Time.deltaTime);
|
||||
if (transform.position.y < lowerBound)
|
||||
{
|
||||
transform.position = new Vector3(transform.position.x, lowerBound, transform.position.z);
|
||||
}
|
||||
}
|
||||
|
||||
public void WinScene(GameObject player)
|
||||
{
|
||||
winScene = true;
|
||||
playerThatWon = player;
|
||||
}
|
||||
|
||||
private GameObject FindWinner() // Finds the player that won
|
||||
{
|
||||
foreach (GameObject player in GameManager.players)
|
||||
{
|
||||
if (player != null && player.activeInHierarchy)
|
||||
{
|
||||
return player;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/PlayerCameraMovement.cs.meta
Normal file
2
Assets/Scripts/Player/PlayerCameraMovement.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9e12ca6f2eb8fa42bba84ae691faeb1
|
||||
97
Assets/Scripts/Player/PlayerManager.cs
Normal file
97
Assets/Scripts/Player/PlayerManager.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public class PlayerManager : MonoBehaviour
|
||||
{
|
||||
public static PlayerManager Instance;
|
||||
public List<PlayerJoinCard> cards;
|
||||
[SerializeField] private InputActionAsset playerActions;
|
||||
public List<Color> playerColors;
|
||||
public GameObject playerSelect;
|
||||
private bool gameStarted = false;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
GetComponent<PlayerInputManager>().onPlayerJoined += OnPlayerJoined;
|
||||
GetComponent<PlayerInputManager>().onPlayerLeft += OnPlayerLeft;
|
||||
}
|
||||
|
||||
private void OnPlayerJoined(PlayerInput playerInput) // Adds a player when they join
|
||||
{
|
||||
if (gameStarted)
|
||||
{
|
||||
Destroy(playerInput.gameObject);
|
||||
return;
|
||||
}
|
||||
Debug.Log("Player joined");
|
||||
DontDestroyOnLoad(playerInput.gameObject);
|
||||
PlayerJoinCard card = PlayerCardCreator.Instance.CreateCard();
|
||||
card.playerNumber = GameManager.players.Count + 1;
|
||||
cards.Add(card);
|
||||
GameManager.players.Add(playerInput.gameObject);
|
||||
Colorize(GameManager.players.Count - 1);
|
||||
}
|
||||
|
||||
|
||||
private void OnPlayerLeft(PlayerInput playerInput) // Removes the player if they leave
|
||||
{
|
||||
Destroy(playerInput.gameObject);
|
||||
GameManager.players.Remove(playerInput.gameObject);
|
||||
Debug.Log("Player left");
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void StartGame() // Allows game to start after a player has joined
|
||||
{
|
||||
if (GameManager.players.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gameStarted = true;
|
||||
HubManager.Instance.LoadScene(GameManager.map);
|
||||
}
|
||||
|
||||
private void Colorize(int index) // Pairs each player with a unique color
|
||||
{
|
||||
GameObject player = GameManager.players[index];
|
||||
Color color = playerColors[(GameManager.players.Count - 1) % playerColors.Count];
|
||||
float tint = Mathf.Floor((GameManager.players.Count - 1) / playerColors.Count);
|
||||
color = (color + color + Color.white * tint) / (tint + 2);
|
||||
GameManager.playerColors.Add(color);
|
||||
ApplyColor(player, color);
|
||||
ApplyColor(cards[GameManager.players.IndexOf(player)].playerPreview, color);
|
||||
}
|
||||
|
||||
private void ApplyColor(GameObject obj, Color color) // Applies a color to each player
|
||||
{
|
||||
if (obj.TryGetComponent<SpriteRenderer>(out _))
|
||||
{
|
||||
obj.GetComponent<SpriteRenderer>().color = color;
|
||||
}
|
||||
foreach (Transform child in obj.transform)
|
||||
{
|
||||
if (child.TryGetComponent<SpriteRenderer>(out _))
|
||||
{
|
||||
ApplyColor(child.gameObject, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/PlayerManager.cs.meta
Normal file
2
Assets/Scripts/Player/PlayerManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33e0fad1e452e0140bc99e780d4dda4f
|
||||
248
Assets/Scripts/Player/PlayerMovement.cs
Normal file
248
Assets/Scripts/Player/PlayerMovement.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
using System.Collections;
|
||||
using TMPro;
|
||||
using Unity.IO.LowLevel.Unsafe;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
[RequireComponent(typeof(BoxCollider2D))]
|
||||
[RequireComponent(typeof(PlayerInput))]
|
||||
[RequireComponent(typeof(AnimationPlayer))]
|
||||
[RequireComponent(typeof(Punch))]
|
||||
public class PlayerMovement : MonoBehaviour
|
||||
{
|
||||
[Header("Ground Layers")]
|
||||
public LayerMask ground;
|
||||
|
||||
public TextMeshProUGUI playerText;
|
||||
|
||||
[Header("Movement")]
|
||||
public float walkSpeed;
|
||||
public float walkSpeedFactor = 1f; // Sets walk speed
|
||||
public float maxSpeed = 5f; // Sets max speed
|
||||
public float maxSpeedOverride;
|
||||
public float slowdownMultiplier = 10f; // Sets slow walk speed
|
||||
public float virtualAxisX;
|
||||
public float virtualButtonJump;
|
||||
public float virtualButtonJumpLastFrame;
|
||||
public float turnaroundMultiplier = 2; // Sets speed when turning around
|
||||
public float walkSmooth;
|
||||
public float secondsToFullSpeed;
|
||||
public float jumpSpeed;
|
||||
public float coyoteTime;
|
||||
public float jumpLenience;
|
||||
public float timeUnableToBeDeclaredNotJumping = 0.1f; // Jump threshold
|
||||
public float groundCheckDistance;
|
||||
|
||||
private Rigidbody2D body;
|
||||
private BoxCollider2D collide;
|
||||
private PlayerInput input;
|
||||
private AnimationPlayer animationPlayer;
|
||||
private Punch punch;
|
||||
private Damageable damageable;
|
||||
|
||||
private bool jumpInputStillValid = false;
|
||||
private bool canBeDeclaredNotJumping = true;
|
||||
private bool jumpPhysics;
|
||||
private bool jumping;
|
||||
private float lastTimeJumpPressed;
|
||||
private float lastTimeOnGround;
|
||||
|
||||
private Vector3 positionLastFrame;
|
||||
|
||||
void Start() // Sets up player components
|
||||
{
|
||||
maxSpeedOverride = maxSpeed;
|
||||
GetComponent<RespawnOnTriggerEnter>().spawnPoint = transform.position;
|
||||
|
||||
body = GetComponent<Rigidbody2D>();
|
||||
collide = GetComponent<BoxCollider2D>();
|
||||
input = GetComponent<PlayerInput>();
|
||||
animationPlayer = GetComponent<AnimationPlayer>();
|
||||
punch = GetComponent<Punch>();
|
||||
damageable = GetComponent<Damageable>();
|
||||
|
||||
playerText.text = input.playerIndex.ToString();
|
||||
}
|
||||
|
||||
private void Update() // Updates player movement
|
||||
{
|
||||
if (GameManager.Instance != null && GameManager.Instance.gameOver) maxSpeed = 1f;
|
||||
if (damageable.dying) return;
|
||||
|
||||
Jump();
|
||||
|
||||
UpdateVirtualAxis();
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
JumpPhysics();
|
||||
|
||||
HorizontalMovement();
|
||||
|
||||
Land();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
Animate();
|
||||
}
|
||||
|
||||
private void Animate() // Sets player animation
|
||||
{
|
||||
if (!IsPhysicallyGrounded())
|
||||
animationPlayer.SetState(AnimationPlayer.AnimationState.Jump);
|
||||
else
|
||||
{
|
||||
if (Mathf.Abs(body.linearVelocityX) >= 0.05f)
|
||||
animationPlayer.SetState(GameManager.Instance.gameOver ? AnimationPlayer.AnimationState.Walk : AnimationPlayer.AnimationState.Run);
|
||||
else
|
||||
animationPlayer.SetState(AnimationPlayer.AnimationState.Idle);
|
||||
}
|
||||
|
||||
if (body.linearVelocityX < -0.1f)
|
||||
animationPlayer.backwards = true;
|
||||
else if (body.linearVelocityX > 0.1f)
|
||||
animationPlayer.backwards = false;
|
||||
}
|
||||
|
||||
private void Land() // Stops jumping when player lands
|
||||
{
|
||||
if (body.linearVelocity.y >= 0f) return;
|
||||
|
||||
if (IsPhysicallyGrounded())
|
||||
{
|
||||
if (canBeDeclaredNotJumping)
|
||||
{
|
||||
jumping = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Jump() // Player jumps when 'jump' is pressed
|
||||
{
|
||||
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
|
||||
{
|
||||
jumpPhysics = true;
|
||||
jumping = true;
|
||||
jumpInputStillValid = false;
|
||||
StartCoroutine(NotJumpingDelay());
|
||||
}
|
||||
}
|
||||
|
||||
private void JumpPhysics() // Applies jump physics
|
||||
{
|
||||
if (jumpPhysics)
|
||||
{
|
||||
if (!GetComponent<Block>().blocking)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
jumpPhysics = false;
|
||||
}
|
||||
|
||||
if (!IsPhysicallyGrounded() && !(virtualButtonJump == 1f))
|
||||
body.AddForce(Vector2.down * jumpSpeed);
|
||||
}
|
||||
|
||||
private IEnumerator NotJumpingDelay() // Sets jump threshold
|
||||
{
|
||||
canBeDeclaredNotJumping = false;
|
||||
yield return new WaitUntil(() => !IsBasicallyGrounded());
|
||||
canBeDeclaredNotJumping = true;
|
||||
}
|
||||
|
||||
private void HorizontalMovement() // Sets player horizontal movement
|
||||
{
|
||||
float temporaryMax = IsPhysicallyGrounded() ? maxSpeedOverride : Mathf.Infinity;
|
||||
float temporarySlowdown = IsPhysicallyGrounded() ? slowdownMultiplier : 1;
|
||||
|
||||
if (!GetComponent<Block>().blocking && (Mathf.Abs(body.linearVelocityX) <= maxSpeed || Mathf.Sign(body.linearVelocityX) != Mathf.Sign(virtualAxisX)))
|
||||
{
|
||||
body.AddForce(new Vector2(virtualAxisX * walkSpeed * walkSpeedFactor, 0), ForceMode2D.Force);
|
||||
}
|
||||
|
||||
if (Mathf.Abs(body.linearVelocityX) >= temporaryMax)
|
||||
{
|
||||
body.AddForce(new Vector2(-Mathf.Sign(body.linearVelocityX) * (Mathf.Abs(body.linearVelocityX) - temporaryMax) * temporarySlowdown, 0));
|
||||
}
|
||||
|
||||
if (transform.position == positionLastFrame && (input.actions.FindAction("Move").ReadValue<Vector2>().x == 0))
|
||||
{
|
||||
virtualAxisX = 0;
|
||||
}
|
||||
|
||||
if (GetComponent<Block>().blocking)
|
||||
{
|
||||
body.AddForce(new Vector2(-body.linearVelocityX * 0.8f, 0), ForceMode2D.Force);
|
||||
}
|
||||
|
||||
positionLastFrame = transform.position;
|
||||
}
|
||||
|
||||
private void UpdateVirtualAxis() // Updates virtual axis
|
||||
{
|
||||
virtualButtonJump = input.actions.FindAction("Action").ReadValue<float>();
|
||||
virtualButtonJumpLastFrame = input.actions.FindAction("Action").WasPressedThisFrame() ? 1 : 0;
|
||||
|
||||
virtualAxisX = input.actions.FindAction("Move").ReadValue<Vector2>().x;
|
||||
return;
|
||||
}
|
||||
|
||||
public bool IsBasicallyGrounded() // Checks if player is on land within a threshold
|
||||
{
|
||||
if (IsPhysicallyGrounded())
|
||||
{
|
||||
lastTimeOnGround = Time.time;
|
||||
}
|
||||
|
||||
if (Time.time - lastTimeOnGround < coyoteTime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsPhysicallyGrounded() // Checks if player is on land
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public Vector2 GetPointInBoxCollider(BoxCollider2D boxCollider2D, float horizontal, float vertical)
|
||||
{
|
||||
return new Vector2
|
||||
(
|
||||
boxCollider2D.bounds.center.x + (horizontal * boxCollider2D.bounds.extents.x),
|
||||
boxCollider2D.bounds.center.y + (vertical * boxCollider2D.bounds.extents.y)
|
||||
);
|
||||
}
|
||||
|
||||
public void StopVelocity() // Stops inertia when landed
|
||||
{
|
||||
if (IsPhysicallyGrounded()) body.linearVelocity = Vector2.zero;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/PlayerMovement.cs.meta
Normal file
2
Assets/Scripts/Player/PlayerMovement.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b920f65db6650d4aa4858ad8a795d19
|
||||
59
Assets/Scripts/Player/Punch.cs
Normal file
59
Assets/Scripts/Player/Punch.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
[RequireComponent(typeof(PlayerInput))]
|
||||
[RequireComponent(typeof(AnimationPlayer))]
|
||||
public class Punch : MonoBehaviour
|
||||
{
|
||||
public bool cancelable = true;
|
||||
|
||||
[SerializeField] private BoxCollider2D hurtbox;
|
||||
|
||||
InputActionAsset actions;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
actions = GetComponent<PlayerInput>().actions;
|
||||
}
|
||||
|
||||
private void Update() // Executes punch when 'punch' is pressed
|
||||
{
|
||||
if (actions.FindAction("Punch").WasPressedThisFrame())
|
||||
{
|
||||
if (!cancelable) return;
|
||||
ExecutePunch();
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecutePunch() // Triggers punch animation
|
||||
{
|
||||
GetComponent<AnimationPlayer>().Punch();
|
||||
DisableCancellation();
|
||||
GetComponent<PlayerMovement>().maxSpeedOverride = 1f; // Slows player down when punching
|
||||
}
|
||||
|
||||
public void EnableHurtbox()
|
||||
{
|
||||
if (hurtbox != null) hurtbox.enabled = true;
|
||||
}
|
||||
|
||||
public void DisableHurtbox()
|
||||
{
|
||||
if (hurtbox != null) hurtbox.enabled = false;
|
||||
}
|
||||
|
||||
public void DisableCancellation()
|
||||
{
|
||||
cancelable = false;
|
||||
}
|
||||
|
||||
public void EnableCancellation()
|
||||
{
|
||||
cancelable = true;
|
||||
}
|
||||
|
||||
public void ReturnToMaxSpeed() // Resets player speed after punch
|
||||
{
|
||||
GetComponent<PlayerMovement>().maxSpeedOverride = GetComponent<PlayerMovement>().maxSpeed;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/Punch.cs.meta
Normal file
2
Assets/Scripts/Player/Punch.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ae332d743f1a42ce8ee7a958853bcc1
|
||||
37
Assets/Scripts/Player/TeleportPlatform.cs
Normal file
37
Assets/Scripts/Player/TeleportPlatform.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class TeleportPlatform : MonoBehaviour
|
||||
{
|
||||
public Vector2 teleportPoint;
|
||||
public string teleportTag;
|
||||
public string playerTag = "Player";
|
||||
public bool isPlatform = true;
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D collision)
|
||||
{
|
||||
if (!isPlatform)
|
||||
{
|
||||
// Teleports the platform
|
||||
if (collision.CompareTag(teleportTag))
|
||||
{
|
||||
transform.position = teleportPoint;
|
||||
if (TryGetComponent<Rigidbody2D>(out var rb))
|
||||
{
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Teleports the player
|
||||
if (collision.CompareTag(playerTag))
|
||||
{
|
||||
collision.transform.position = teleportPoint;
|
||||
if (collision.TryGetComponent<Rigidbody2D>(out var rb))
|
||||
{
|
||||
rb.linearVelocity = Vector2.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/TeleportPlatform.cs.meta
Normal file
2
Assets/Scripts/Player/TeleportPlatform.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 182a9e619d36aeb4592fb532d3c9db55
|
||||
63
Assets/Scripts/Player/UseItem.cs
Normal file
63
Assets/Scripts/Player/UseItem.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class UseItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private string itemTag;
|
||||
private GameObject heldItem;
|
||||
private bool isHoldingItem = false;
|
||||
private float holdStartTime;
|
||||
public float holdTime;
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (isHoldingItem)
|
||||
{
|
||||
// Keeps hat on the player's head
|
||||
heldItem.transform.position = transform.position + Vector3.up;
|
||||
if (GameManager.gameMode == GameManager.GameMode.keepAway)
|
||||
{
|
||||
// Adds time to the player's leaderboard standing
|
||||
holdTime += Time.deltaTime;
|
||||
GameManager.Instance.UpdatePlayerHoldTime(gameObject, holdTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCollisionEnter2D(Collision2D collision) // Player automatically picks up hat when touching it
|
||||
{
|
||||
if (collision.gameObject.CompareTag("Hat") && !isHoldingItem)
|
||||
{
|
||||
PickUpItem(collision.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void PickUpItem(GameObject item) // Player picks up hat and starts hold counter
|
||||
{
|
||||
heldItem = item;
|
||||
isHoldingItem = true;
|
||||
holdStartTime = Time.time;
|
||||
item.GetComponent<Collider2D>().enabled = false;
|
||||
item.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Static;
|
||||
item.transform.rotation = Quaternion.identity;
|
||||
if (!GameManager.playerHoldTimes.ContainsKey(gameObject))
|
||||
{
|
||||
GameManager.playerHoldTimes[gameObject] = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public void DropItem() // Player drops hat when hit
|
||||
{
|
||||
if (isHoldingItem)
|
||||
{
|
||||
heldItem.GetComponent<Collider2D>().enabled = true;
|
||||
heldItem.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
|
||||
heldItem.transform.position += Vector3.up * 3f;
|
||||
heldItem = null;
|
||||
isHoldingItem = false;
|
||||
if (GameManager.playerHoldTimes.ContainsKey(gameObject))
|
||||
{
|
||||
GameManager.playerHoldTimes.Remove(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Player/UseItem.cs.meta
Normal file
2
Assets/Scripts/Player/UseItem.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 861b3bde023ca7f48a72c48ef9ee25d2
|
||||
Reference in New Issue
Block a user