JudgeShotTrainHandle.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. using ShotSimulator.Target;
  2. using ShotSimulator.Tool;
  3. using ShotSimulator.Train.Info;
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using UnityEngine;
  8. using Random = UnityEngine.Random;
  9. namespace ShotSimulator.Train
  10. {
  11. public enum JudgeShotStep
  12. {
  13. Observe,
  14. Judge,
  15. }
  16. public class JudgeShotTrainHandle : BaseTrainHandle
  17. {
  18. private Color curTargetColor;
  19. private List<Color> colors = new List<Color>() { Color.red, Color.green };
  20. private JudgeShotStep curStep;
  21. private List<SphereShotTarget> curTargets = new List<SphereShotTarget>();
  22. private TimeTask m_ObserveTimer;
  23. private JudgeShotTrainDifficultyData m_DifficultyData;
  24. private JudgeShotTrainScoreData m_ScoreData;
  25. protected float totalReactionTime;
  26. private float invalidDecisionNums;
  27. private float validityDecisionNums;
  28. private double m_TotalHitNum;
  29. private double TotalHitNum
  30. {
  31. get { return m_TotalHitNum; }
  32. set
  33. {
  34. m_TotalHitNum = value;
  35. UpdatePrecision();
  36. }
  37. }
  38. private double m_MissHitNum;
  39. private double MissHitNum
  40. {
  41. get { return m_MissHitNum; }
  42. set
  43. {
  44. m_MissHitNum = value;
  45. UpdatePrecision();
  46. }
  47. }
  48. public JudgeShotTrainHandle(BaseTrainCallBack callBack, BaseTrainInfo info, DifficultyType difficultyType) : base(callBack, info, difficultyType)
  49. {
  50. SetShotTargetInteractiveEvent(ShotTargetInteractiveType.OnClick, OnShottedTargetEvent);
  51. m_DifficultyData = info.GetDifficultyData<JudgeShotTrainDifficultyData>(m_DifficultyType);
  52. m_ScoreData = info.GetScoreData<JudgeShotTrainScoreData>(m_DifficultyType);
  53. }
  54. #region Train
  55. protected override void ResetTrain()
  56. {
  57. ResetTarget();
  58. curTargetColor = Color.white;
  59. curStep = JudgeShotStep.Observe;
  60. TimerSystem.GetInstance().RemoveTimeTask(m_ObserveTimer);
  61. m_ObserveTimer = null;
  62. totalReactionTime = 0;
  63. invalidDecisionNums = 0;
  64. validityDecisionNums = 0;
  65. m_TotalHitNum = 0;
  66. m_MissHitNum = 0;
  67. }
  68. public override void StartTrain()
  69. {
  70. base.StartTrain();
  71. SwitchTrainStep(JudgeShotStep.Observe);
  72. }
  73. public override void ContinueTrain()
  74. {
  75. base.ContinueTrain();
  76. if (m_ObserveTimer != null)
  77. {
  78. m_ObserveTimer.pause = false;
  79. }
  80. }
  81. public override void PauseTrain()
  82. {
  83. base.PauseTrain();
  84. if (m_ObserveTimer != null)
  85. {
  86. m_ObserveTimer.pause = true;
  87. }
  88. }
  89. public override void CalculateTrainResult()
  90. {
  91. double reactionTime = 999;
  92. if (invalidDecisionNums + validityDecisionNums != 0)
  93. {
  94. reactionTime = Math.Round(totalReactionTime / (invalidDecisionNums + validityDecisionNums), 2);
  95. }
  96. double deactionAccurancy = 0;
  97. if (validityDecisionNums + invalidDecisionNums != 0)
  98. {
  99. deactionAccurancy = Math.Round(validityDecisionNums / (invalidDecisionNums + validityDecisionNums), 2);
  100. }
  101. SetResultMetricsDataValue(MetricsType.ReactionTime, reactionTime);
  102. SetResultMetricsDataValue(MetricsType.DeactionAccurancy, deactionAccurancy);
  103. }
  104. #endregion
  105. #region ShotTarget
  106. private void UpdatePrecision()
  107. {
  108. double totalShot = TotalHitNum + MissHitNum;
  109. double precision = 0;
  110. if (totalShot != 0)
  111. {
  112. precision = Math.Round(TotalHitNum / totalShot, 2);
  113. }
  114. SetResultMetricsDataValue(MetricsType.Precision, precision);
  115. }
  116. private void OnShottedTargetEvent(BaseShotTarget target)
  117. {
  118. if (target != null)
  119. {
  120. TotalHitNum++;
  121. CalculateShootingResult((target as SphereShotTarget).defaultColor);
  122. TimerSystem.GetInstance().RemoveTimeTask(m_ObserveTimer);
  123. JudgeShotStep nextStep = curStep == JudgeShotStep.Judge ? JudgeShotStep.Observe : JudgeShotStep.Judge;
  124. SwitchTrainStep(nextStep);
  125. }
  126. else
  127. {
  128. comboNums = 0;
  129. int missPunitiveS = 0;
  130. switch (curStep)
  131. {
  132. case JudgeShotStep.Observe:
  133. missPunitiveS = Mathf.CeilToInt(m_ScoreData.singleWheelBaseScore * m_ScoreData.singleWheelMissPunitiveMul) + Random.Range(-2, 2);
  134. break;
  135. case JudgeShotStep.Judge:
  136. missPunitiveS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.doubleWheelMissPunitiveMul) + Random.Range(-2, 2);
  137. break;
  138. }
  139. IncreaseScore(missPunitiveS * -1);
  140. MissHitNum++;
  141. }
  142. }
  143. #endregion
  144. private void SwitchTrainStep(JudgeShotStep step)
  145. {
  146. ResetTarget();
  147. curStep = step;
  148. StartBestHitTimer();
  149. switch (curStep)
  150. {
  151. case JudgeShotStep.Observe:
  152. ExecuteObserveStepTarget();
  153. break;
  154. case JudgeShotStep.Judge:
  155. ExecuteJudgeStepTarget();
  156. break;
  157. }
  158. }
  159. private void ExecuteObserveStepTarget()
  160. {
  161. GameObject obj = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/SphereTarget"));
  162. SphereShotTarget target = obj.GetComponent<SphereShotTarget>();
  163. target.onClickCanChangeColor = false;
  164. target.onHoveringCanChangeColor = false;
  165. target.defaultColor = RandomTargetColorType();
  166. Vector3 centerPos = new Vector3(0, 0, m_DifficultyData.targetDistance);
  167. target.Init(1, ReduceHealthTriggerType.OnClick, false, ReduceHealthType.Per, MotionType.None, centerPos);
  168. curTargets.Add(target);
  169. target.IsRunning = true;
  170. }
  171. private void ExecuteJudgeStepTarget()
  172. {
  173. for (int i = 0; i < 2; i++)
  174. {
  175. GameObject obj = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/SphereTarget"));
  176. SphereShotTarget target = obj.GetComponent<SphereShotTarget>();
  177. curTargets.Add(target);
  178. target.IsRunning = true;
  179. target.onClickCanChangeColor = false;
  180. target.onHoveringCanChangeColor = false;
  181. target.defaultColor = i == 0 ? curTargetColor : RandomTargetColorType();
  182. target.Init(1, ReduceHealthTriggerType.OnClick, false, ReduceHealthType.Per, MotionType.None, RandomPosition());
  183. }
  184. m_ObserveTimer = TimerSystem.GetInstance().AddTimeTask(ObserveTimeOut, m_DifficultyData.observeTime);
  185. }
  186. private void ObserveTimeOut()
  187. {
  188. invalidDecisionNums++;
  189. totalReactionTime += m_DifficultyData.observeTime;
  190. comboNums = 0;
  191. int outTimePunitiveS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.doubleWheelOutTimePunitiveMul) + Random.Range(-2, 2);
  192. IncreaseScore(outTimePunitiveS * -1);
  193. SwitchTrainStep(JudgeShotStep.Observe);
  194. }
  195. private void CalculateShootingResult(Color color)
  196. {
  197. switch (curStep)
  198. {
  199. case JudgeShotStep.Observe:
  200. CalculateObserveStepResult(color);
  201. break;
  202. case JudgeShotStep.Judge:
  203. CalculateJudgeStepResult(color);
  204. break;
  205. }
  206. }
  207. private void CalculateObserveStepResult(Color color)
  208. {
  209. curTargetColor = color;
  210. int comboS = Mathf.CeilToInt(m_ScoreData.singleWheelBaseScore * comboNums * m_ScoreData.comboMul);
  211. int bestS = m_IsBestHit ? Mathf.CeilToInt(m_ScoreData.singleWheelBaseScore * m_ScoreData.bestHitMul) + Random.Range(-1, 3) : 0;
  212. IncreaseScore(m_ScoreData.singleWheelBaseScore + comboS + bestS);
  213. comboNums++;
  214. }
  215. private void CalculateJudgeStepResult(Color color)
  216. {
  217. bool validity = curTargetColor == color;
  218. if (validity)
  219. {
  220. validityDecisionNums++;
  221. int comboS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * comboNums * m_ScoreData.comboMul);
  222. int bestS = m_IsBestHit ? Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.bestHitMul) + Random.Range(-1, 3) : 0;
  223. IncreaseScore(m_ScoreData.doubleWheelBaseScore + comboS + bestS);
  224. comboNums++;
  225. }
  226. else
  227. {
  228. invalidDecisionNums++;
  229. comboNums = 0;
  230. int falsePunitiveS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.doubleWheelFalsePunitiveMul) + Random.Range(-3, 3);
  231. IncreaseScore(falsePunitiveS * -1);
  232. }
  233. totalReactionTime += m_ObserveTimer.delay - m_ObserveTimer.remainingTime;
  234. }
  235. private Color RandomTargetColorType()
  236. {
  237. Color color = colors[Random.Range(0, colors.Count)];
  238. while (color == curTargetColor)
  239. {
  240. color = colors[Random.Range(0, colors.Count)];
  241. }
  242. return color;
  243. }
  244. private Vector3 RandomPosition()
  245. {
  246. List<Vector3> positions = curTargets.GetGameObjectWorldPosition<SphereShotTarget>();
  247. Vector2 widthLimt = Vector2.zero;
  248. Vector2 heightLimt = Vector2.zero;
  249. switch (m_DifficultyType)
  250. {
  251. case DifficultyType.Standard:
  252. widthLimt = new Vector2(-4, 4);
  253. heightLimt = new Vector2(-1.5f, 1.5f);
  254. break;
  255. case DifficultyType.Advance:
  256. widthLimt = new Vector2(-8, 8);
  257. heightLimt = new Vector2(-1.5f, 3.5f);
  258. break;
  259. case DifficultyType.Professional:
  260. widthLimt = new Vector2(-8, 8);
  261. heightLimt = new Vector2(-1.5f, 5f);
  262. break;
  263. }
  264. Vector3 min = ExtraTool.GetScreenOffsetPosition(ExtraTool.Sphere_Diameter1_ScreenLeftBottomOffset, m_DifficultyData.targetDistance, widthLimt, heightLimt);
  265. Vector3 max = ExtraTool.GetScreenOffsetPosition(ExtraTool.Sphere_Diameter1_ScreenRightTopOffset, m_DifficultyData.targetDistance, widthLimt, heightLimt);
  266. if (ExtraTool.TryGetNonOverlapRamdonPos(positions, min, max, 1, out Vector3 ramdonPos, false))
  267. {
  268. return ramdonPos;
  269. }
  270. else
  271. {
  272. return new Vector3(0, 0, m_DifficultyData.targetDistance);
  273. }
  274. }
  275. private void ResetTarget()
  276. {
  277. for (int i = 0; i < curTargets.Count; i++)
  278. {
  279. curTargets[i].IsRunning = false;
  280. GameObject.Destroy(curTargets[i].gameObject);
  281. }
  282. curTargets.Clear();
  283. }
  284. }
  285. }