Player.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using Cinemachine;
  2. using DG.Tweening;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using UnityEngine;
  7. public class Player : EntityBase {
  8. public static Player instance;
  9. private void Awake() {
  10. instance = this;
  11. _hp = 3;
  12. }
  13. internal override bool isPressingCrouch() => InputM.GetKeyEvent(InputM.KeyType.Crouch);
  14. internal override bool isPressDownJump() => InputM.GetKeyEvent(InputM.KeyType.Jump);
  15. internal override bool isPressingLeft() => InputM.GetKeyEvent(InputM.KeyType.Left);
  16. internal override bool isPressingRight() => InputM.GetKeyEvent(InputM.KeyType.Right);
  17. // 生命
  18. public RectTransform[] hearts;
  19. private static int _hp;
  20. public static int hp {
  21. get { return _hp; }
  22. set {
  23. if (_hp == value) return;
  24. _hp = value;
  25. instance.RefreshHearts();
  26. }
  27. }
  28. public float knockbackForceH = 30f, knockbackForceV = 15f;
  29. internal override void OnHitBorder() {
  30. Hurt();
  31. resistanceTime = resistanceOnHurt;
  32. transform.position = new Vector3(-6, 10, 0);
  33. }
  34. internal override void OnHitEnemy(Collision2D collision) {
  35. if (Hurt()) {
  36. int face = collision.transform.position.x < transform.position.x ? 1 : -1;
  37. rb.velocity = new Vector2(face * knockbackForceH, knockbackForceV);
  38. }
  39. }
  40. public float resistanceOnHurt = 1f; private float resistanceTime = 0f;
  41. public bool Hurt() {
  42. if (resistanceTime <= 0.001f) {
  43. resistanceTime = resistanceOnHurt;
  44. hp--;
  45. AudioM.Play("hurt", 0.6f);
  46. rb.velocity = Vector2.zero;
  47. DOTween.Kill("ScreenShake");
  48. Camera.current.DOShakePosition(0.4f, 0.5f, 25).SetId("ScreenShake");
  49. return true;
  50. } else {
  51. return false;
  52. }
  53. }
  54. // 治疗
  55. public float healTime = 4f; private float currentHealTime = 0f;
  56. private void RefreshHearts() {
  57. float totalHp = Mathf.Clamp(hp + Mathf.Pow(currentHealTime / healTime, 7f) * 0.7f + currentHealTime / healTime * 0.3f, 0, 3);
  58. for (int i = 0; i < 3; i++) {
  59. hearts[i].localScale = Vector3.one * Mathf.Clamp(totalHp - i, 0, 1);
  60. }
  61. }
  62. // 射击
  63. public int maxBullet = 20, currentBullet = 20;
  64. public float shootDelay = 0.15f; private float currentShootDelay = 0f;
  65. public float reloadDelay = 1.5f; private float currentReloadDelay = 0f;
  66. public float bulletSpeed = 50f, bulletKnockback = 1f;
  67. public GameObject bullet; public TMPro.TextMeshProUGUI textBullet;
  68. internal override void OnUpdate() {
  69. // 反向
  70. if ((towardsRight && isPressingLeft() && !isPressingRight()) || (!towardsRight && isPressingRight() && !isPressingLeft())) {
  71. towardsRight = !towardsRight;
  72. transform.DOScaleX(towardsRight ? 1 : -1, 0.15f);
  73. }
  74. // 无敌
  75. if (resistanceTime > 0f) resistanceTime -= Time.deltaTime;
  76. // 治疗
  77. if (isPressingCrouch() && hp < 3 && isLand) {
  78. currentHealTime += Time.deltaTime;
  79. if (currentHealTime > healTime) {
  80. currentHealTime -= healTime;
  81. hp++;
  82. }
  83. RefreshHearts();
  84. } else if (currentHealTime != 0f) {
  85. currentHealTime = 0f;
  86. RefreshHearts();
  87. }
  88. // 装填
  89. if (InputM.GetKeyEvent(InputM.KeyType.Reload) && currentBullet < maxBullet && currentReloadDelay <= 0f) {
  90. AudioM.Play("reload", 1f);
  91. currentReloadDelay = reloadDelay;
  92. } else if (currentReloadDelay > 0 && currentReloadDelay < Time.deltaTime) {
  93. currentReloadDelay = 0f; currentBullet = maxBullet;
  94. } else if (currentReloadDelay > 0) {
  95. currentReloadDelay -= Time.deltaTime;
  96. }
  97. // 开火
  98. if (InputM.GetKeyEvent(InputM.KeyType.Fire) && currentBullet > 0 && currentShootDelay <= 0f && currentReloadDelay <= 0f) {
  99. AudioM.Play("fire", 0.65f);
  100. currentBullet--; currentShootDelay = shootDelay;
  101. Vector2 fromPos = transform.position + Vector3.up * ((canCrouch && isPressingCrouch()) ? 0.55f : 1.3f);
  102. Vector2 toPos = AspectUtility.cam.ScreenToWorldPoint(Input.mousePosition);
  103. Vector2 shootVector = (toPos - fromPos).normalized;
  104. // 随机散布
  105. shootVector.x *= 1f + (float) (Modules.randomDefault.NextDouble() * 0.4f - 0.2f);
  106. shootVector.y *= 1f + (float) (Modules.randomDefault.NextDouble() * 0.4f - 0.2f);
  107. shootVector.Normalize();
  108. // 生成
  109. GameObject newBullet = Instantiate(bullet, fromPos, Quaternion.identity);
  110. newBullet.GetComponent<Rigidbody2D>().velocity = bulletSpeed * shootVector;
  111. newBullet.transform.eulerAngles = (shootVector.x > 0 ? -1 : 1) * Vector2.Angle(shootVector, Vector2.up) * Vector3.forward;
  112. // 后座力
  113. rb.velocity += bulletKnockback * -shootVector;
  114. } else if (currentShootDelay > 0) {
  115. currentShootDelay -= Time.deltaTime;
  116. }
  117. string fireKey = InputM.GetKeyRaw(InputM.KeyType.Fire);
  118. bool isFireDown = fireKey == "l" ? Input.GetMouseButton(0) : (fireKey == "r" ? Input.GetMouseButton(1) : Input.GetKey(fireKey));
  119. if (isFireDown && currentBullet == 0 && currentReloadDelay <= 0f) {
  120. AudioM.Play("bullet_empty", 0.7f);
  121. }
  122. // 更新 UI
  123. textBullet.text = currentReloadDelay > 0f ?
  124. "".PadLeft(maxBullet - Mathf.RoundToInt(currentReloadDelay / reloadDelay * maxBullet), "|".ToCharArray().First()) :
  125. "".PadLeft(currentBullet, "|".ToCharArray().First());
  126. textBullet.color = currentReloadDelay > 0f ? new Color(0.6f, 0.6f, 0.6f) : new Color(0.9686275f, 0.5568628f, 0.1098039f);
  127. }
  128. }