diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 013855a..b84928d 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -6859,12 +6859,17 @@ PrefabInstance: - target: {fileID: 4623847142764859891, guid: b29a944aaba25f643afdc6b049845662, type: 3} propertyPath: maxApexTime - value: 0.1 + value: 0.3 objectReference: {fileID: 0} - target: {fileID: 4623847142764859891, guid: b29a944aaba25f643afdc6b049845662, type: 3} propertyPath: maxForwardJumpBoost value: 2 objectReference: {fileID: 0} + - target: {fileID: 4623847142764859891, guid: b29a944aaba25f643afdc6b049845662, + type: 3} + propertyPath: timeToMaxAirmoveSpeed + value: 0.25 + objectReference: {fileID: 0} m_RemovedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: b29a944aaba25f643afdc6b049845662, type: 3} diff --git a/Assets/Scripts/PlayerController.cs b/Assets/Scripts/PlayerController.cs index 9792e9b..13c218b 100644 --- a/Assets/Scripts/PlayerController.cs +++ b/Assets/Scripts/PlayerController.cs @@ -19,8 +19,12 @@ public class PlayerController : MonoBehaviour { // this has to be public to be readable by the display, which is a code // smell. public JumpState jumpState; + public JumpDirection jumpDirection; private float jumpStateStart; - private float apexTime; + private float jumpStartTime; + private float jumpHeldDuration; + private bool wasHoldingJump; + public float apexTime; private float jumpVelocity = 8f; private float gravity = -20f; @@ -36,7 +40,9 @@ public class PlayerController : MonoBehaviour { } void Update() { - Instantiate(tracerPrefab, transform.position, Quaternion.identity); + GameObject tracerObj = Instantiate(tracerPrefab, transform.position, Quaternion.identity); + TracerDot tracer = tracerObj.GetComponent(); + Debug.Log(tracer); Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); float targetX = input.x * moveSpeed; @@ -55,7 +61,9 @@ public class PlayerController : MonoBehaviour { switch (jumpState) { case JumpState.Grounded: - if (Input.GetButtonDown("Jump")) { + tracer.color = Color.white; + + if (Input.GetButton("Jump")) { velocity.y = jumpVelocity; if (input.x >= 0.25f) { velocity.x = moveSpeed*maxForwardJumpBoost; @@ -72,56 +80,63 @@ public class PlayerController : MonoBehaviour { break; case JumpState.Ascending: + tracer.color = Color.green; + + // n starts at 0 and goes to 1 as we ascend float n = Mathf.InverseLerp(0, timeToJumpApex, Time.time - jumpStateStart); + + // the drag coefficient gets bigger as we ascend, terminating at 1 float dragCoefficient = n * n; if (Input.GetButton("Jump")) { float jumpDrag = jumpVelocity * dragCoefficient; - if (n <= 0.4) { + if (n <= 0.7) { jumpDrag = 0; } velocity.y = jumpVelocity - jumpDrag; } else { // if we're not pressing jump any more we add all the gravity - velocity.y += gravity * Time.deltaTime; + velocity.y += 4 * gravity * Time.deltaTime; + + // the amount of time spent floating is equal to the amount of + // time the player held down the jump button. + if (wasHoldingJump) { + apexTime = Time.time - jumpStartTime; + } } float forwardBoost = maxForwardJumpBoost - (maxForwardJumpBoost * dragCoefficient); forwardBoost = Mathf.Clamp(forwardBoost, 1, maxForwardJumpBoost); - if (velocity.x >= 0) { - if (targetX >= 0) { - // continuing to move in your current direction is a boost - velocity.x = Mathf.SmoothDamp(velocity.x, targetX * forwardBoost, ref velocityXSmoothing, timeToMaxAirmoveSpeed); - } else { - // moving in the opposite direction can slow you down but - // not turn you around - velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed); - velocity.x = Mathf.Clamp(velocity.x, 0, initialVelocity.x); - } - } else { - if (targetX <= 0) { - // continuing to move in your current direction is a boost - velocity.x = Mathf.SmoothDamp(velocity.x, targetX * forwardBoost, ref velocityXSmoothing, timeToMaxAirmoveSpeed); - } else { - // moving in the opposite direction can slow you down but - // not turn you around - velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed); - velocity.x = Mathf.Clamp(velocity.x, initialVelocity.x, 0); - } + switch (jumpDirection) { + case JumpDirection.Neutral: + // you can wiggle out of a neutral jump in either direction + velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + + case JumpDirection.Left: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX < 0 ? targetX * forwardBoost : 0, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + + case JumpDirection.Right: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX > 0 ? targetX * forwardBoost : 0, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; } // 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; + if (wasHoldingJump && Input.GetButton("Jump")) { + apexTime = maxApexTime; + } setJumpState(JumpState.Apex); - apexTime = Mathf.Clamp(Time.time - jumpStateStart, 0, maxApexTime); } - break; case JumpState.Apex: + tracer.color = Color.magenta; + if (Input.GetButtonDown("Jump")) { velocity.y = jumpVelocity; if (input.x >= 0.25f) { @@ -133,10 +148,20 @@ public class PlayerController : MonoBehaviour { } setJumpState(JumpState.Ascending); } else { - // your horizontal motion at apex is constant throughout - // velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + switch (jumpDirection) { + case JumpDirection.Neutral: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + case JumpDirection.Left: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX < 0 ? targetX : 0, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + case JumpDirection.Right: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX > 0 ? targetX : 0, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + } + float timeAtApex = Time.time - jumpStateStart; - float apexTimeRemaining = maxApexTime - timeAtApex; + float apexTimeRemaining = apexTime - timeAtApex; if (apexTimeRemaining < 0) { velocity.y += gravity * -apexTimeRemaining; setJumpState(JumpState.Descending); @@ -147,25 +172,28 @@ public class PlayerController : MonoBehaviour { break; case JumpState.Descending: + tracer.color = Color.yellow; + float n2 = (Time.time - jumpStateStart) / timeToJumpApex; n2 = Mathf.Clamp(n2, 0, 1); - - // horizontal travel is decreasing when descending, so that you - // always land vertically. Drag increases as you descend, so that it - // is 1 at the end of your descent. - // float drag = n2*n2*Mathf.Abs(velocity.x); - // drag = 0; - // if (velocity.x >= 0) { - // velocity.x = Mathf.SmoothDamp(velocity.x, Mathf.Clamp(targetX, 0, velocity.x-drag), ref velocityXSmoothing, timeToMaxAirmoveSpeed); - // } else { - // velocity.x = Mathf.SmoothDamp(velocity.x, Mathf.Clamp(targetX, velocity.x+drag, 0), ref velocityXSmoothing, timeToMaxAirmoveSpeed); - // } + switch (jumpDirection) { + case JumpDirection.Neutral: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + case JumpDirection.Left: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX < 0 ? targetX : 0, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + case JumpDirection.Right: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX > 0 ? targetX : 0, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + } // fall speed is increasing when descending - velocity.y += gravity * Time.deltaTime * n2 * n2; + velocity.y += gravity * Time.deltaTime * (Mathf.Clamp(4 * n2 * n2, 1, 4)); break; case JumpState.CoyoteTime: + tracer.color = Color.blue; velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxRunSpeed); if (Input.GetButtonDown("Jump")) { setJumpState(JumpState.Ascending); @@ -181,7 +209,19 @@ public class PlayerController : MonoBehaviour { break; case JumpState.Falling: - velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + tracer.color = Color.red; + + switch (jumpDirection) { + case JumpDirection.Neutral: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + case JumpDirection.Left: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX < 0 ? targetX : 0, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + case JumpDirection.Right: + velocity.x = Mathf.SmoothDamp(velocity.x, targetX > 0 ? targetX : 0, ref velocityXSmoothing, timeToMaxAirmoveSpeed); + break; + } velocity.y += gravity * Time.deltaTime; break; @@ -200,6 +240,7 @@ public class PlayerController : MonoBehaviour { if (jumpState != JumpState.Grounded && moveController.isGrounded) { setJumpState(JumpState.Grounded); } + wasHoldingJump = Input.GetButton("Jump"); } void OnDestroy() { @@ -212,8 +253,18 @@ public class PlayerController : MonoBehaviour { } void setJumpState(JumpState state) { + if (jumpState != JumpState.Ascending && state == JumpState.Ascending) { + jumpStartTime = Time.time; + } jumpState = state; jumpStateStart = Time.time; + if (velocity.x == 0) { + jumpDirection = JumpDirection.Neutral; + } else if (velocity.x > 0) { + jumpDirection = JumpDirection.Right; + } else { + jumpDirection = JumpDirection.Left; + } } /* @@ -251,4 +302,10 @@ public class PlayerController : MonoBehaviour { // did not initially jump. Falling, } + + public enum JumpDirection { + Neutral, + Left, + Right, + } } diff --git a/Assets/Scripts/TracerDot.cs b/Assets/Scripts/TracerDot.cs index 1a603d2..15def6d 100644 --- a/Assets/Scripts/TracerDot.cs +++ b/Assets/Scripts/TracerDot.cs @@ -4,13 +4,15 @@ using UnityEngine; public class TracerDot : MonoBehaviour { private float spawned; + public Color color; void Start() { spawned = Time.time; + // color = Color.white; } void OnDrawGizmos() { - Gizmos.color = Color.red; + Gizmos.color = color; Gizmos.DrawWireSphere(transform.position, 0.125f); }