BikeSpeedBooster.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace Controller.Bicycle
  5. {
  6. readonly struct Booster
  7. {
  8. public float StartTime { get; }
  9. public float EndTime { get; }
  10. public float StartValue { get; }
  11. public float EndValue { get; }
  12. public Booster(float startTime, float duration, float startValue, float endValue)
  13. {
  14. StartTime = startTime;
  15. EndTime = startTime + duration;
  16. StartValue = startValue;
  17. EndValue = endValue;
  18. }
  19. public override string ToString()
  20. {
  21. return $"Booster({StartValue}-{EndValue} between Time({StartTime}, {EndTime}))";
  22. }
  23. }
  24. public class BikeSpeedBooster
  25. {
  26. #region singleton
  27. private static readonly Lazy<BikeSpeedBooster>
  28. lazy =
  29. new Lazy<BikeSpeedBooster>
  30. (() => new BikeSpeedBooster());
  31. public static BikeSpeedBooster Instance => lazy.Value;
  32. private readonly List<Booster> activeBooster = new List<Booster>();
  33. #endregion
  34. public const float MaxBoost = 1.4f;
  35. public const float MinBoost = 0.6f;
  36. public const float ThresholdZero = 0.05f;
  37. private const float DURATION_BOOST_STRAIGHT_UPHILL = 2.5f;
  38. private const float DURATION_BOOST_UPHILL_STRAIGHT = 1.5f;
  39. private const float DURATION_BOOST_STRAIGHT_DOWNHILL = 3.5f;
  40. private const float DURATION_BOOST_DOWNHILL_STRAIGHT = 5f;
  41. private float maxSlopeDeg = 8.7f;
  42. private float fixedBoost = 1;
  43. public float Boost
  44. {
  45. get
  46. {
  47. var boost = fixedBoost;
  48. var toDelete = new Stack<Booster>();
  49. var t = Time.time;
  50. foreach (var b in activeBooster)
  51. {
  52. if (b.EndTime < t)
  53. {
  54. toDelete.Push(b);
  55. continue;
  56. }
  57. if (b.StartTime > t) continue;
  58. var add = Mathf.Lerp(b.StartValue, b.EndValue,
  59. (Time.time - b.StartTime) / (b.EndTime - b.StartTime));
  60. boost *= add;
  61. }
  62. foreach (var d in toDelete)
  63. {
  64. activeBooster.Remove(d);
  65. }
  66. return Mathf.Clamp(boost, MinBoost, MaxBoost);
  67. }
  68. }
  69. public void AddBoosterForFirstAndSlope(float slopeDegree)
  70. {
  71. //going from straight to downhill -> increase speed from straight to slope
  72. //-> inverse fixed boost first, then 1*fixedBoost
  73. //going from straight to uphill -> decrease speed from straight to slope
  74. //-> inverse fixed boost first, then 1*fixedBoost
  75. var booster = new Booster(Time.time,
  76. slopeDegree < 0 ? DURATION_BOOST_STRAIGHT_DOWNHILL : DURATION_BOOST_STRAIGHT_UPHILL,
  77. 1f / fixedBoost, 1f);
  78. //Debug.Log($"Adding Booster: {booster}");
  79. activeBooster.Add(booster);
  80. }
  81. public void AddBoosterForLastAndSlope(float slopeDegree)
  82. {
  83. //going from downhill to straight -> let the bike roll -> boost starts at fixedBoost and decreases to 1
  84. //going from uphill to straight -> don't go to 1 immediately
  85. //-> boost starts at fixedBoost and increases to 1
  86. var booster = new Booster(Time.time,
  87. slopeDegree < 0 ? DURATION_BOOST_DOWNHILL_STRAIGHT : DURATION_BOOST_UPHILL_STRAIGHT,
  88. fixedBoost, 1f);
  89. //Debug.Log($"Adding Booster: {booster}");
  90. activeBooster.Add(booster);
  91. }
  92. public void SetFixedBoostForSlope(float slopeDegree)
  93. {
  94. var max = slopeDegree < 0 ? -maxSlopeDeg : maxSlopeDeg;
  95. fixedBoost = Mathf.Lerp(1f, slopeDegree < 0 ? MaxBoost : MinBoost, slopeDegree / max);
  96. }
  97. public void ResetFixedBoost()
  98. {
  99. fixedBoost = 1;
  100. }
  101. }
  102. }