You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
6.3 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MoveController))]
[RequireComponent(typeof(BoxCollider2D))]
public class PlayerController : MonoBehaviour {
public float jumpHeight = 4f;
public float timeToJumpApex = 0.4f;
public float moveSpeed = 6f;
public float maxFallSpeed = -20f;
public float timeToMaxRunSpeed = 0.15f;
public float timeToMaxAirmoveSpeed = 0.25f;
public float floatTime = 0.025f; // amount of time spent at max jump height before falling again
public float coyoteTime = 0.025f;
// this has to be public to be readable by the display, which is a code
// smell.
public JumpState jumpState;
private float jumpStateStart;
private float jumpVelocity = 8f;
private float gravity = -20f;
private Vector3 velocity;
private MoveController moveController;
private float velocityXSmoothing;
void Start() {
setJumpState(JumpState.Falling);
moveController = GetComponent<MoveController>();
gravity = -(2* jumpHeight) / Mathf.Pow(timeToJumpApex, 2);
jumpVelocity = Mathf.Abs(gravity) * timeToJumpApex;
}
void Update() {
Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
float targetX = input.x * moveSpeed;
Vector3 initialVelocity = velocity;
if (moveController.collisions.above) {
velocity.y = 0;
}
if (moveController.collisions.left || moveController.collisions.right) {
velocity.x = 0;
}
switch (jumpState) {
case JumpState.Grounded:
if (Input.GetButtonDown("Jump")) {
setJumpState(JumpState.Ascending);
velocity.y = jumpVelocity;
} else {
velocity.y = gravity * Time.deltaTime;
}
velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxRunSpeed);
break;
// case JumpState.Ascending:
// velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed);
// velocity.y += gravity * Time.deltaTime;
// if (velocity.y < maxFallSpeed) {
// velocity.y = maxFallSpeed;
// }
// // if we were rising in the last frame but will be falling in this
// // frame, we should zero out the velocity to float instead.
// if (initialVelocity.y >= 0 && velocity.y <= 0) {
// velocity.y = 0;
// setJumpState(JumpState.Apex);
// }
// break;
case JumpState.Apex:
velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed);
float timeFloating = Time.time - jumpStateStart;
float floatTimeRemaining = floatTime - timeFloating;
if (floatTimeRemaining < 0) {
velocity.y += gravity * -floatTimeRemaining;
setJumpState(JumpState.Descending);
} else {
velocity.y = 0;
}
break;
case JumpState.CoyoteTime:
velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxRunSpeed);
if (Input.GetButtonDown("Jump")) {
setJumpState(JumpState.Ascending);
velocity.y = jumpVelocity;
} else {
float elapsedCoyoteTime = Time.time - jumpStateStart;
float coyoteTimeRemaining = coyoteTime - elapsedCoyoteTime;
if (coyoteTimeRemaining < 0) {
velocity.y += gravity * -coyoteTimeRemaining;
setJumpState(JumpState.Falling);
} else {
velocity.y = 0;
}
}
break;
default:
velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed);
velocity.y += gravity * Time.deltaTime;
if (velocity.y < maxFallSpeed) {
velocity.y = maxFallSpeed;
}
// if we were rising in the last frame but will be falling in this
// frame, we should zero out the velocity to float instead.
if (initialVelocity.y >= 0 && velocity.y <= 0) {
velocity.y = 0;
setJumpState(JumpState.Apex);
}
break;
}
moveController.Move(velocity * Time.deltaTime);
if (jumpState == JumpState.Grounded && !moveController.isGrounded) {
setJumpState(JumpState.CoyoteTime);
}
if (jumpState != JumpState.Grounded && moveController.isGrounded) {
setJumpState(JumpState.Grounded);
}
}
void OnDestroy() {
}
void OnCollisionEnter(Collision other) {
}
void OnTriggerEnter(Collider other) {
}
void setJumpState(JumpState state) {
jumpState = state;
jumpStateStart = Time.time;
}
/*
Possible JumpState transitions:
Grounded -> Ascending : a normal jump
Grounded -> CoyoteTime : player has walked off ledge
CoyoteTime -> Ascending : player has jumped after leaving a ledge
CoyoteTime -> Falling : player has walked off of a ledge and is now falling
Ascending -> Apex : player has reached the top of their jump normally
Apex -> Descending : player has reached the top of their jump and is now falling
*/
public enum JumpState {
// The player is on the ground
Grounded,
// The player has not jumped; they have walked off of a platform without
// jumping
CoyoteTime,
// The player is rising in a jump
Ascending,
// The player has reached the apex of their jump, where they will
// briefly remain to give a feeling of lightness
Apex,
// The player, having jumped, is in a controlled descent following the
// jump
Descending,
// The player is descending but without control; they are falling but
// did not initially jump.
Falling,
}
}