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(); hbox = GetComponent(); #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().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 } }