TowerDefenseGame/Assets/Scripts/Runtime/Characters/Player/PlayerJumpHandler.cs
Nico ba13eb9e51 Create PlayerJumpHandler to deal with Player's jumping
Create Vfx for multiple jumps while on air
Finalize jumping ability with up to 3 multi-jump implementing a hacky bezier curve
2025-07-23 01:24:54 -07:00

121 lines
3.1 KiB
C#

using System;
using System.Collections;
using System.Data;
using System.Linq;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;
[Serializable]
public class PlayerJumpHandler {
private Player Player;
public Transform Transform;
private Vector2 Position => Transform.position;
[Header("FakeZ and Jump Attributes")]
public float GroundFakeZ = 0;
public float CurrentFakeZ = 0;
public float Height = 2.5f;
public float AirTime = 0.7f;
public float FreeFallSpeedPerSec = 13.5f;
public bool Active { get; set; }
public bool Paused { get; set; }
public bool IsFalling => TimeElapsedNormalized > 0.5;
public bool IsFreeFalling => TimeElapsedNormalized > 1;
public float LastJump { get; private set; }
public float PauseTimeStamp { get; private set; }
public float PauseTime { get; private set; } = 0;
public float TimeElapsedNormalized => (Time.time - LastJump) / AirTime;
public float TimeLeftNormalized => 1 - TimeElapsedNormalized;
public bool IsNonBlocking => !Active || (Time.time - LastJump > 0.03f);
private int JumpCount = 0;
private float Yref = 0;
[Header("Jump Curve Parameters")]
public float a = 1.2f;
public float b = 1.4f;
public float c = 1;
public PlayerJumpHandler(Player player) {
Player = player;
Transform = player.transform.Find("Visuals").Find("CharacterPos");
player.DoUpdate += SetHeight;
}
private void SetHeight() {
if (!Active || Paused) return;
if (!IsFreeFalling) {
var shift = (TimeElapsedNormalized < 0.5) ? 0 : AirTime;
var elapsed = Math.Abs(TimeElapsedNormalized * AirTime - shift) / (AirTime / 2);
var min = Math.Min(elapsed, 1);
var t = Math.Max(min, 0);
var u = 1 - t;
var h1 = 4 * u * u * u * t * a;
var h2 = 4 * u * u * t * t * b;
var h3 = 4 * u * t * t * t * c;
var h4 = t * t * t * t;
var h = (Height * (h1 + h2 + h3 + h4)) / JumpCount + GroundFakeZ + Yref;
CurrentFakeZ = h;
} else {
Yref -= (TimeElapsedNormalized - 1) * FreeFallSpeedPerSec;
if (Yref < 0) Yref = 0;
CurrentFakeZ = Yref;
}
if (TimeLeftNormalized <= 0 && Yref == 0)
Stop();
else
SetTransformYPos(CurrentFakeZ);
}
public void Pause() {
if (!Active) return;
PauseTimeStamp = Time.time;
Paused = true;
}
public void Unpause() {
if (!Active) return;
PauseTime = Time.time - PauseTimeStamp;
LastJump = Time.time - (AirTime * TimeLeftNormalized);
Paused = false;
}
public void Start() {
if (JumpCount++ > 2) return;
if (Player.SkillInUse) return;
if (JumpCount > 1) {
var pos = Player.transform.position;
pos.y += Transform.localPosition.y - 0.7f;
Player.VfxAirJumpPool.Get(pos);
}
Yref = Transform.localPosition.y;
Active = true;
LastJump = Time.time;
PauseTime = 0;
}
public void Stop() {
Active = false;
JumpCount = 0;
SetTransformYPos(0);
}
public void SetTransformYPos(float yPos) {
var pos = Transform.localPosition;
pos.y = Math.Max(yPos, 0);
Transform.localPosition = pos;
Yref = Math.Min(Yref, pos.y);
}
}