TowerDefenseGame/Assets/Scripts/Runtime/Characters/Player/PlayerMainController.cs

316 lines
9.6 KiB
C#

using System.Collections;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
[SelectionBase]
public class Player : MonoBehaviour {
[Header("Asset/Prefab")]
[SerializeField] public BuilderManager Builder;
[Header("Movement")]
[SerializeField] private Rigidbody2D Rigidbody;
[SerializeField] public Animator Animator;
[SerializeField] private SpriteRenderer Renderer;
[Header("Character Class")]
[SerializeField] private ParticleSystem Aura;
[SerializeField] private GameObject[] ClassIndicators;
private ClassBase ActiveClass;
[SerializeField] private MeleeFighterClass FighterClass;
public AttackAnimatorFactory AttackAnimator;
[Header("Movement Attributes")]
[SerializeField] public float MoveSpeed = 8;
[SerializeField] public float MoveSpeedDampener = 1;
[SerializeField] private float DashSpeedInitial = 200;
[SerializeField] private float DashSpeed = 0;
[SerializeField] private float DashDecayRate = 30;
[SerializeField] private float DashDelay1 = 0.05f;
[SerializeField] private float DashDelay2 = 0.05f;
[SerializeField] private float DashCooldown = 0.1f;
//[SerializeField] private float DriftSpeed = 60;
//[SerializeField] private float DriftFactorial = 0.85f;
[SerializeField] private float JumpDelay = 0.3f;
[Header("VFX")]
[SerializeField] private GameObject VfxDash;
private VfxHandlerBase VfxDashHandler;
[SerializeField] private GameObject VfxKineticSurge;
[HideInInspector] public VfxHandlerBase VfxKineticSurgeHandler;
[SerializeField] private GameObject VfxShockwave;
[HideInInspector] public GameObjectPool VfxShockwavePool;
private BoxCollider2D[] BoxColliders;
public Vector2 PrevDirection = Vector2.zero;
private Vector2 MoveDirection = Vector2.zero;
private Vector2 DashDirection = Vector2.zero;
private Directions FaceDir = Directions.Down;
public bool IsJumping { get; set; }
public float LastJumpTime { get; private set; }
public Coroutine CoroutineJumpReset { get; private set; }
public bool ActionAfterJumpReady {
get {
return (!IsJumping || (Time.time - LastJumpTime > 0.07f));
}
}
public bool IsDashing { get; private set; }
public float DashTime { get; private set; }
public bool CanDash { get; private set; } = true;
public Vector2 DriftDirection { get; private set; } = Vector2.zero;
private float Drift = 0;
public bool SkillInUse = false;
private enum Directions { Left, Right, Up, Down }
void Awake() {
Builder = GetComponent<BuilderManager>();
VfxDashHandler = new VfxHandlerBase(VfxDash, 5, 5);
VfxKineticSurgeHandler = new VfxHandlerBase(VfxKineticSurge, 5, 5);
FighterClass = new MeleeFighterClass(this);
VfxShockwavePool = new GameObjectPool(VfxShockwave, 5, 5);
BoxColliders = GetComponentsInChildren<BoxCollider2D>();
SetClass(1);
}
private void Update() {
KeyPressActions();
GatherInput();
ActiveClass.Tick();
}
private void GatherInput() {
MoveDirection.x = Input.GetAxisRaw("Horizontal");
MoveDirection.y = Input.GetAxisRaw("Vertical");
}
private void KeyPressActions() {
if (Input.GetKeyDown(KeyCode.LeftShift) || Input.GetKeyDown(KeyCode.RightShift)) {
DoDash();
} else if (!IsJumping && Input.GetKeyDown(KeyCode.Space)) {
Jump();
} else if (Input.GetKeyDown(KeyCode.F1)) {
SetClass(0);
} else if (Input.GetKeyDown(KeyCode.F2)) {
SetClass(1);
} else if (Input.GetKeyDown(KeyCode.F3)) {
SetClass(2);
} else if (Input.GetKeyDown(KeyCode.F4)) {
SetClass(3);
}
if (Input.GetKeyDown(KeyCode.X)) ActiveClass.HandlePrimaryAttack();
else if (Input.GetKeyDown(KeyCode.C)) ActiveClass.HandleSecondaryAttack();
}
private void DoDash() {
if (!CanDash) return;
if (!ActionAfterJumpReady) return;
CanDash = false;
IsDashing = true;
DashDirection = MoveDirection.normalized;
DashSpeed = DashSpeedInitial;
//StartCoroutine(DoDash(MoveDirection));
}
private void Dash(Vector2 direction) {
if (direction == Vector2.zero) return;
//if (Drift > 0.5f) return;
if (!ActionAfterJumpReady) return;
IsDashing = true;
DashTime = Time.time;
//Rigidbody.linearVelocity = direction.normalized * speed;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg + 180;
if (direction.normalized != Vector2.zero)
VfxDashHandler.PlayAll(this.transform.position, Quaternion.Euler(0f, 0f, angle));
DriftDirection = direction.normalized;
//Drift = speed;
//Rigidbody.AddForce(direction * speed, ForceMode2D.Impulse);
//Rigidbody.AddForce(direction.normalized * speed, ForceMode.Acceleration);
IsDashing = false;
}
IEnumerator DoDash(Vector2 direction) {
var startTime = Time.time;
var speed = MoveSpeed * DashSpeedInitial / MoveSpeedDampener;
//if (IsJumping) speed /= 2;
Rigidbody.linearVelocity = Vector2.zero;
//Rigidbody.AddForce(direction * speed, ForceMode2D.Impulse);
var mag = (direction.normalized * speed).magnitude;
Rigidbody.linearVelocity = direction.normalized * speed;
var isJumping = IsJumping;
if (isJumping) Jump();
while ((Time.time - startTime) < DashDelay1)
yield return null;
//yield return new WaitForSeconds(DashDelay1);
Rigidbody.linearVelocity = Vector2.zero;
var endTime = Time.time;
Debug.Log($"[{Mathf.Abs(mag):0.00}] Time elapsed {(endTime - startTime):0.000}");
yield return new WaitForSeconds(DashDelay2);
IsDashing = false;
yield return new WaitForSeconds(DashCooldown);
while (IsJumping)
yield return null;
CanDash = true;
}
private void Jump() {
if (SkillInUse) return;
IsJumping = true;
LastJumpTime = Time.time;
foreach (var col in BoxColliders)
col.enabled = false;
if (CoroutineJumpReset != null)
StopCoroutine(CoroutineJumpReset);
CoroutineJumpReset = StartCoroutine(ResetJumpAfterDelay());
//Rigidbody.AddForce(MoveDirection.normalized * MoveSpeed / 2, ForceMode2D.Force);
MoveSpeedDampener = 2;
}
private IEnumerator ResetJumpAfterDelay() {
yield return new WaitForSeconds(JumpDelay);
foreach (var col in BoxColliders)
col.enabled = true;
IsJumping = false;
MoveSpeedDampener = 1;
}
private void SetClass(int classIdx) {
Builder.SetBuildMode(classIdx == 3);
ActiveClass = FighterClass;
foreach (var (indicator, i) in ClassIndicators.Select((obj, i) => (obj, i)))
if (i != classIdx) {
indicator.transform.localScale = Vector3.one;
indicator.transform.rotation = Quaternion.identity;
} else {
indicator.transform.localScale = Vector3.one * 2;
indicator.transform.rotation = Quaternion.AngleAxis(90, Vector3.forward);
}
RawImage image = ClassIndicators[classIdx].GetComponent<RawImage>();
var main = Aura.main;
main.startColor = image.color;
}
private void FixedUpdate() {
MovementUpdate();
CalculateFacingDirection();
UpdateAnimation();
}
private void MovementUpdate() {
//if (IsJumping && !IsDashing) {
// Rigidbody.AddForce(MoveDirection.normalized * MoveSpeed / 5, ForceMode2D.Force);
// return;
//}
var movement = (MoveDirection.normalized * MoveSpeed) / MoveSpeedDampener;
//var movement = MoveDirection.normalized * MoveSpeed;
if (IsDashing) {
if (DashSpeed < 0.2f) {
DashSpeed = 0;
CanDash = true;
IsDashing = false;
} else if (DashSpeed > (movement.magnitude * 2)) {
if (IsJumping) Jump();
movement = DashDirection * DashSpeed;
DashSpeed *= Mathf.Exp(-DashDecayRate * Time.deltaTime);
} else {
movement = ((DashDirection * DashSpeed) + movement) / 2;
DashSpeed *= Mathf.Exp(-DashDecayRate * Time.deltaTime);
}
}
Rigidbody.linearVelocity = movement;
}
private void CalculateFacingDirection() {
if (MoveDirection.x != 0)
if (MoveDirection.x < 0)
FaceDir = Directions.Left;
else
FaceDir = Directions.Right;
}
private void UpdateAnimation() {
string state = GetAnimationState(MoveDirection);
if (state.Last() == '_')
state = state.Replace("_", "");
else
state += LastDirection.ToString();
Animator.CrossFade(state, 0);
}
public enum Direction { Up, Down, Left, Right }
public Direction LastDirection = Direction.Down;
private string GetAnimationState(Vector2 input) {
if (SkillInUse) return ActiveClass.AnimationToPlay;
if (!IsJumping && input.sqrMagnitude < 0.01f) return "Idle";
if (Mathf.Abs(input.x) > 0)
LastDirection = (input.x > 0) ? Direction.Right : Direction.Left;
else if (Mathf.Abs(input.y) > 0)
LastDirection = (input.y > 0) ? Direction.Up : Direction.Down;
if (IsJumping) return "Jump";
return "Run";
}
void OnDrawGizmos() {
DrawPlayerDirection();
}
private void DrawPlayerDirection() {
if (Rigidbody == null) Rigidbody = GetComponent<Rigidbody2D>();
if (Rigidbody == null) return;
Gizmos.color = Color.cyan;
Vector3 start = Rigidbody.transform.position;
Vector3 end = start + (Vector3)(Rigidbody.linearVelocity * 1);
Gizmos.DrawLine(start, end);
DrawArrowHead(end, (end - start).normalized);
}
void DrawArrowHead(Vector3 position, Vector3 direction) {
float arrowHeadAngle = 20f;
float arrowHeadLength = 0.25f;
Vector3 right = Quaternion.Euler(0, 0, arrowHeadAngle) * -direction;
Vector3 left = Quaternion.Euler(0, 0, -arrowHeadAngle) * -direction;
Gizmos.DrawLine(position, position + right * arrowHeadLength);
Gizmos.DrawLine(position, position + left * arrowHeadLength);
}
}