320 lines
9.5 KiB
C#
320 lines
9.5 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
public class playerC0ntroller : MonoBehaviour
|
|
{
|
|
|
|
private Rigidbody2D body;
|
|
private BoxCollider2D hbox;
|
|
private String SelectedPlayer;
|
|
|
|
bool isJumping;
|
|
|
|
Vector2 awayFromWall;
|
|
bool gravityLockActive;
|
|
bool isFacingRight = true;
|
|
float playerHealth;
|
|
|
|
//Input Variables
|
|
private KeyCode hop, up, down, left, right, dash, forward;
|
|
private String currentDirection;
|
|
private Vector2 directionHeld;
|
|
private bool inputLock;
|
|
|
|
//Wall Friction
|
|
float wallStallTimer, wallFricTimer, wallFricStrength = 4;
|
|
|
|
//Timers
|
|
float coyoteTime, wallCoyoteTime, jumpBufferTimer, inputLockTimer, dashCooldown, dashActiveTimer, turnaroundWindow;
|
|
|
|
//Upgrade Stats
|
|
public float vitalityLevel, healthModifier, regenerationRate, armorModifier;
|
|
public float powerLevel, damageModifier, unloadSpeedModifier;
|
|
public float agilityLevel, movementSpeedModifier, jumpPowerModifier, jumpChargeCap;
|
|
|
|
//Method Variables
|
|
float jumpPower = 30f;
|
|
float dashCharges, jumpCharges;
|
|
|
|
private void Start()
|
|
{
|
|
body = GetComponent<Rigidbody2D>();
|
|
hbox = GetComponent<BoxCollider2D>();
|
|
|
|
#region Character Archetype Controls
|
|
switch (SelectedPlayer)
|
|
{
|
|
case "Cade":
|
|
case "Sloane":
|
|
default:
|
|
hop = KeyCode.W;
|
|
up = KeyCode.W;
|
|
down = KeyCode.S;
|
|
left = KeyCode.A;
|
|
right = forward = KeyCode.D;
|
|
dash = KeyCode.LeftShift;
|
|
break;
|
|
|
|
case "Leo":
|
|
case "Gamma":
|
|
hop = KeyCode.Space;
|
|
up = KeyCode.UpArrow;
|
|
down = KeyCode.DownArrow;
|
|
left = KeyCode.LeftArrow;
|
|
right = forward = KeyCode.RightArrow;
|
|
dash = KeyCode.LeftShift;
|
|
break;
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
|
|
ManageTimers();
|
|
|
|
playerHealth = GameObject.Find("GameData").GetComponent<GameData>().CurrentHealth;
|
|
|
|
if (playerHealth > 0)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
//Methods Used By Other Methods
|
|
private bool isGrounded()
|
|
{
|
|
Vector2 groundCastOrigin = new Vector2(hbox.bounds.center.x, hbox.bounds.min.y);
|
|
Vector2 groundCastSize = new Vector2(hbox.bounds.size.x, 0.01f);
|
|
int checkLayers = (1 << 6) | (1 << 9); //Makes A Bitmask That Will Check For Collisions On Both Solid and Semiolid Ground Layers, Respectively
|
|
|
|
RaycastHit2D groundHit = Physics2D.BoxCast(groundCastOrigin, groundCastSize, 0f, Vector2.down, .05f, checkLayers);
|
|
RaycastHit2D doubleCheck = Physics2D.BoxCast(groundCastOrigin, groundCastSize, 0f, Vector2.up, .05f, 1 << 9); //Check if Player is Inside a Semisolid Layer
|
|
|
|
if (doubleCheck.collider != null) return false;
|
|
return groundHit.collider != null;
|
|
}
|
|
public bool isWallSlide()
|
|
{
|
|
if (directionHeld.x == -1 * directionAwayFromWall().x && body.linearVelocityY <= 0 && !isGrounded())
|
|
{
|
|
|
|
if (wallFricTimer >= 0 && body.linearVelocityY < 0)
|
|
{
|
|
body.linearVelocityY *= Mathf.Exp(-wallFricStrength * Time.deltaTime); //Friction On Wall Before Coming To A Stop
|
|
if (Math.Abs(body.linearVelocityY) < .25f) body.linearVelocityY = 0;
|
|
|
|
wallStallTimer = .15f;
|
|
}
|
|
|
|
wallCoyoteTime = .1f;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
wallFricTimer = (body.linearVelocityY - 0.1f) / -20; //As Velocity Approaches -20 Timer Approaches 1 Sec, .1 Sec Buffer Stops It From Being 0
|
|
return false;
|
|
}
|
|
}
|
|
private Vector2 directionAwayFromWall()
|
|
{
|
|
Vector2 wallCastOrigin = new Vector2(hbox.bounds.center.x, hbox.bounds.center.y);
|
|
Vector2 wallCastSize = new Vector2(hbox.bounds.size.x + .01f, hbox.bounds.size.y);
|
|
|
|
Collider2D wallHit = Physics2D.OverlapBox(wallCastOrigin, wallCastSize, 0f, 1 << 6); //Check for collisions on layer 6 (solidGround)
|
|
|
|
return (wallHit != null) ? wallHit.Distance(hbox).normal : default;
|
|
}
|
|
public void Flip()
|
|
{
|
|
transform.localScale = new Vector2(transform.localScale.x * -1, transform.localScale.y);
|
|
forward = (forward == left) ? right : left;
|
|
// ^if this is true^ ^then^ ^else^
|
|
}
|
|
public void CountDown(ref float timer)
|
|
// ^ref^ makes this function modify the referenced timer instead of assigning the timer to a placeholder
|
|
{
|
|
if (timer > 0) timer -= Time.deltaTime;
|
|
}
|
|
|
|
|
|
//Methods Run Every Frame
|
|
public void ManageInputs()
|
|
{
|
|
inputLock = (inputLockTimer > 0 || dashActiveTimer > 0) ? false : true;
|
|
|
|
if (!inputLock)
|
|
{
|
|
directionHeld.x = (Input.GetKey(right) ? 1 : 0) - (Input.GetKey(left) ? 1 : 0);
|
|
directionHeld.y = (Input.GetKey(up) ? 1 : 0) - (Input.GetKey(down) ? 1 : 0);
|
|
}
|
|
|
|
if (directionHeld.y == 1) currentDirection = "up";
|
|
else if (directionHeld.y == -1) currentDirection = "down";
|
|
else if (directionHeld.x == -1 && left != forward || directionHeld.x == 1 && right != forward) currentDirection = "backward";
|
|
else if (directionHeld.x == -1 && left == forward || directionHeld.x == 1 && right == forward) currentDirection = "forward";
|
|
if (directionHeld == default) currentDirection = "neutral"; //"default" acts as a vector with values (0, 0)
|
|
|
|
if (Input.GetKeyDown(hop)) jumpBufferTimer = .2f;
|
|
}
|
|
|
|
|
|
public void ManagePlayerOrientation()
|
|
{
|
|
|
|
if (directionHeld.x != 0 && (directionHeld.x > 0) != isFacingRight && isGrounded()) Flip();
|
|
|
|
|
|
}
|
|
|
|
|
|
public void ManageTimers()
|
|
{
|
|
CountDown(ref coyoteTime);
|
|
CountDown(ref wallCoyoteTime);
|
|
CountDown(ref jumpBufferTimer);
|
|
CountDown(ref inputLockTimer);
|
|
|
|
if (isGrounded() || dashCooldown > .05f) CountDown(ref dashCooldown);
|
|
|
|
CountDown(ref dashActiveTimer);
|
|
CountDown(ref turnaroundWindow);
|
|
CountDown(ref wallStallTimer);
|
|
CountDown(ref wallFricTimer);
|
|
}
|
|
|
|
public void ManageSpeedCaps()
|
|
{
|
|
bool speedClampingActive = (dashActiveTimer > 0) ? false : true;
|
|
|
|
if (speedClampingActive)
|
|
{
|
|
body.linearVelocityX = Mathf.Clamp(body.linearVelocity.x, -10 - movementSpeedModifier, 10 + movementSpeedModifier); //Clamp X Velocity
|
|
|
|
float terminalVelocity;
|
|
if (directionHeld.y == -1) terminalVelocity = -30;
|
|
else if (isWallSlide()) terminalVelocity = -12;
|
|
else terminalVelocity = -20;
|
|
|
|
body.linearVelocityY = Mathf.Clamp(body.linearVelocity.y, terminalVelocity, 10 + jumpPowerModifier); // Clamp Y Velocity
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public void ManageGravity()
|
|
{
|
|
body.gravityScale = dashActiveTimer > 0 || wallStallTimer > 0 && isWallSlide() ? 0 : body.gravityScale;
|
|
gravityLockActive = dashActiveTimer > 0 || wallStallTimer > 0 && isWallSlide();
|
|
|
|
if (!gravityLockActive)
|
|
{
|
|
if (directionHeld.y == -1) body.gravityScale = 8;
|
|
else if (isWallSlide()) body.gravityScale = 2;
|
|
else body.gravityScale = 6;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ManageGroundResetting()
|
|
{
|
|
if (isGrounded())
|
|
{
|
|
jumpCharges = jumpChargeCap;
|
|
dashCharges = 1;
|
|
coyoteTime = .1f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void InterpretInputs()
|
|
{
|
|
#region Walking & Friction
|
|
float turnAround = isGrounded() ? 8 : 6;
|
|
if (turnaroundWindow > 0) turnAround *= 5;
|
|
float moveSpeed = 10;
|
|
|
|
body.linearVelocityX += moveSpeed * directionHeld.x * turnAround * Time.deltaTime;
|
|
|
|
|
|
if (directionHeld.x == 0)
|
|
{
|
|
float fric = (Math.Abs(body.linearVelocityX) > 3f) ? .97f : .94f;
|
|
body.linearVelocityX = body.linearVelocityX * fric;
|
|
|
|
if (Math.Abs(body.linearVelocity.x) < .4f) body.linearVelocityX = 0;
|
|
}
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Jumping
|
|
if (jumpBufferTimer > 0) {
|
|
|
|
isJumping = true;
|
|
|
|
//Normal Jump
|
|
if (coyoteTime > 0) body.linearVelocityY = jumpPower;
|
|
|
|
//Wall Jump
|
|
else if (wallCoyoteTime > 0)
|
|
{
|
|
body.linearVelocity = new Vector2(moveSpeed * awayFromWall.x, 20f);
|
|
|
|
directionHeld.x = (awayFromWall.x > 0) ? 1 : -1;
|
|
inputLockTimer = 0.15f;
|
|
}
|
|
|
|
//Air Jump
|
|
else if (jumpCharges > 0)
|
|
{
|
|
body.linearVelocityY = jumpPower * .8f;
|
|
turnaroundWindow = .1f;
|
|
jumpCharges--;
|
|
}
|
|
|
|
//Wrapping Up Logic
|
|
else isJumping = false;
|
|
if (isJumping) jumpBufferTimer = 0;
|
|
}
|
|
|
|
//Jump Capping
|
|
if (!Input.GetKey(hop) && body.linearVelocityY > 0 && isJumping) body.linearVelocityY = body.linearVelocityY * .9f;
|
|
|
|
//isJumping Update
|
|
if (isJumping && body.linearVelocityY <= 0) isJumping = false;
|
|
|
|
#endregion
|
|
|
|
#region Dashing
|
|
if (Input.GetKeyDown(dash) && dashCooldown <= 0 && dashCharges > 0)
|
|
{
|
|
dashCooldown = 1;
|
|
dashActiveTimer = .15f;
|
|
|
|
float dashPower = (directionHeld.x * directionHeld.y != 0) ? 60 : 0.707f * 60;
|
|
|
|
if (directionHeld == default) directionHeld.x = (forward == right) ? 1 : -1;
|
|
|
|
body.linearVelocity = new Vector2(directionHeld.x * dashPower, directionHeld.y * 2 * dashPower);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
|
|
|
|
}
|