/Assets/Scripts/BlobMove.cs

https://bitbucket.org/Danvil/ld26_minimal · C# · 182 lines · 151 code · 21 blank · 10 comment · 14 complexity · 722a44442549c7462cd99a3848f44b15 MD5 · raw file

  1. using UnityEngine;
  2. using System.Linq;
  3. public class BlobMove : MonoBehaviour {
  4. const float cSpeedMaxBoost = 1.2f;
  5. const float cAvoidStrengthPlayer = 1.0f;
  6. const float cAvoidStrengthOther = 0.5f;
  7. const float cAvoidStrengthLevel = 1.0f;
  8. public float cAvoidStrengthBombs = 2.5f;
  9. const float cBombAvoidRadius = 1.0f;
  10. const float cRotationMixStrength = 0.5f;
  11. public float size = 0.3f;
  12. public float speed = 1.5f;
  13. public float playerFollowStrength = 0.0f;
  14. public bool isPlayerFollow = false;
  15. public float goalTolerance = 0.5f;
  16. public bool hasGoal { get; private set; }
  17. public Vector3 goal { get; private set; }
  18. public float PlayerMinDistance = 0.0f;
  19. public void SetGoal(Vector3 goal)
  20. {
  21. this.goal = goal;
  22. this.hasGoal = true;
  23. }
  24. public void DisableGoal()
  25. {
  26. this.hasGoal = false;
  27. }
  28. public bool isGoalReached() {
  29. return (transform.position - goal).magnitude < goalTolerance;
  30. }
  31. // Use this for initialization
  32. void Start () {
  33. hasGoal = false;
  34. }
  35. float slerpAngle(float x, float y, float p) {
  36. float d = y - x;
  37. if(d > Mathf.PI) {
  38. d = 2.0f * Mathf.PI - d;
  39. }
  40. return x + p * d;
  41. }
  42. Vector3 computePlayerFollow() {
  43. const float cMinRadius = 1.0f;
  44. Vector3 d = Globals.Player.transform.position - transform.position;
  45. float m = d.magnitude;
  46. if(m == 0) {
  47. return Vector3.zero; // TODO
  48. }
  49. if(playerFollowStrength >= 0) {
  50. if(m < cMinRadius) {
  51. return Vector3.zero;
  52. }
  53. else {
  54. return playerFollowStrength * d.normalized;
  55. }
  56. }
  57. else {
  58. m = 0.5f + 0.4f*Mathf.Max(0.0f, m - 3.0f);
  59. return playerFollowStrength / (m*m) * d.normalized;
  60. }
  61. }
  62. Vector3 computeGoalFollow() {
  63. if(hasGoal) {
  64. return (goal - transform.position).normalized;
  65. }
  66. else {
  67. return Vector3.zero;
  68. }
  69. }
  70. float avoidFalloff(float d, float d_min) {
  71. float z = Mathf.Max(d/d_min, 0.4f);
  72. return 1.0f / (z*z);
  73. }
  74. // avoid player
  75. Vector3 computeAvoidPlayer() {
  76. Vector3 player_pos = Globals.Player.transform.position;
  77. Vector3 delta = player_pos - transform.position;
  78. float dist = delta.magnitude;
  79. if(dist < PlayerMinDistance) {
  80. return - avoidFalloff(dist, PlayerMinDistance) * delta.normalized;
  81. }
  82. else {
  83. return Vector3.zero;
  84. }
  85. }
  86. // avoid other
  87. Vector3 computeAvoidOther() {
  88. Vector3 force = Vector3.zero;
  89. foreach(BlobMove x in Globals.BlobManager.GetMoveBehaviours()) { // TODO reduce range
  90. Vector3 delta = x.transform.position - transform.position;
  91. float d_min = this.size + x.size;
  92. force -= avoidFalloff(delta.magnitude, 0.5f*d_min) * delta.normalized;
  93. }
  94. return force;
  95. }
  96. // avoid bombs
  97. Vector3 computeAvoidBombs() {
  98. Vector3 force = Vector3.zero;
  99. foreach(Bomb x in Globals.BombManager.GetBombs()) { // TODO reduce range
  100. Vector3 delta = x.transform.position - transform.position;
  101. float d_min = this.size + cBombAvoidRadius;
  102. force -= avoidFalloff(delta.magnitude, d_min) * delta.normalized;
  103. }
  104. return force;
  105. }
  106. // avoid level
  107. Vector3 computeAvoidLevel() {
  108. Vector3 force = Vector3.zero;
  109. Vector3 pos = this.transform.position.WithChangedZ(0.0f);
  110. foreach(Vector3 bc in Globals.Level.BlockedCells) {
  111. Vector3 delta = pos - bc;
  112. force += avoidFalloff(delta.magnitude, this.size) * delta.normalized;
  113. }
  114. return force;
  115. }
  116. Vector3 moveFollow;
  117. Vector3 movePlayer;
  118. Vector3 moveAvoid;
  119. Vector3 moveLevel;
  120. Vector3 moveBombs;
  121. // Update is called once per frame
  122. void Update () {
  123. if(isGoalReached()) {
  124. hasGoal = false;
  125. }
  126. moveFollow = speed * computeGoalFollow().normalized;
  127. movePlayer = cAvoidStrengthPlayer * computeAvoidPlayer();
  128. moveAvoid = cAvoidStrengthOther * computeAvoidOther();
  129. moveLevel = cAvoidStrengthLevel * computeAvoidLevel();
  130. moveBombs = cAvoidStrengthBombs * computeAvoidBombs();
  131. Vector3 move = moveFollow + movePlayer + moveAvoid + moveLevel + moveBombs;
  132. // some randomness
  133. move += MyTime.deltaTime * 0.05f * MoreMath.RandomInsideUnitCircle3;
  134. move.WithChangedZ(0.0f);
  135. // limit max velocity
  136. float mag = move.magnitude;
  137. float speedMax = cSpeedMaxBoost * speed;
  138. if(mag > speedMax) {
  139. move *= speedMax / mag;
  140. }
  141. // compute new position
  142. transform.position += MyTime.deltaTime * move;
  143. // compute new rotation
  144. float angle_old = MoreMath.VectorAngle(transform.localRotation * Vector3.right);
  145. float angle_new = MoreMath.VectorAngle(move.normalized);
  146. float angle_final = slerpAngle(angle_old, angle_new, cRotationMixStrength * MyTime.deltaTime);
  147. transform.localRotation = MoreMath.RotAngle(angle_final);
  148. }
  149. void OnDrawGizmos()
  150. {
  151. if(hasGoal) {
  152. Gizmos.color = Color.blue;
  153. Gizmos.DrawLine(transform.position, goal);
  154. Debug.DrawRay(this.transform.position, movePlayer, new Color(1.0f, 0.5f, 0.0f));
  155. Debug.DrawRay(this.transform.position, moveFollow, Color.blue);
  156. Debug.DrawRay(this.transform.position, moveAvoid, Color.green);
  157. Debug.DrawRay(this.transform.position, moveLevel, Color.cyan);
  158. Debug.DrawRay(this.transform.position, moveBombs, Color.red);
  159. }
  160. }
  161. }