using ShotSimulator.Target; using ShotSimulator.Tool; using ShotSimulator.Train.Info; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using Random = UnityEngine.Random; namespace ShotSimulator.Train { public enum JudgeShotStep { Observe, Judge, } public class JudgeShotTrainHandle : BaseTrainHandle { private Color curTargetColor; private List colors = new List() { Color.red, Color.green }; private JudgeShotStep curStep; private List curTargets = new List(); private TimeTask m_ObserveTimer; private JudgeShotTrainDifficultyData m_DifficultyData; private JudgeShotTrainScoreData m_ScoreData; protected float totalReactionTime; private float invalidDecisionNums; private float validityDecisionNums; private double m_TotalHitNum; private double TotalHitNum { get { return m_TotalHitNum; } set { m_TotalHitNum = value; UpdatePrecision(); } } private double m_MissHitNum; private double MissHitNum { get { return m_MissHitNum; } set { m_MissHitNum = value; UpdatePrecision(); } } public JudgeShotTrainHandle(BaseTrainCallBack callBack, BaseTrainInfo info, DifficultyType difficultyType) : base(callBack, info, difficultyType) { SetShotTargetInteractiveEvent(ShotTargetInteractiveType.OnClick, OnShottedTargetEvent); m_DifficultyData = info.GetDifficultyData(m_DifficultyType); m_ScoreData = info.GetScoreData(m_DifficultyType); } #region Train protected override void ResetTrain() { ResetTarget(); curTargetColor = Color.white; curStep = JudgeShotStep.Observe; TimerSystem.GetInstance().RemoveTimeTask(m_ObserveTimer); m_ObserveTimer = null; totalReactionTime = 0; invalidDecisionNums = 0; validityDecisionNums = 0; m_TotalHitNum = 0; m_MissHitNum = 0; } public override void StartTrain() { base.StartTrain(); SwitchTrainStep(JudgeShotStep.Observe); } public override void ContinueTrain() { base.ContinueTrain(); if (m_ObserveTimer != null) { m_ObserveTimer.pause = false; } } public override void PauseTrain() { base.PauseTrain(); if (m_ObserveTimer != null) { m_ObserveTimer.pause = true; } } public override void CalculateTrainResult() { SetResultMetricsDataValue(MetricsType.ReactionTime, Math.Round(totalReactionTime / (invalidDecisionNums + validityDecisionNums), 2)); SetResultMetricsDataValue(MetricsType.DeactionAccurancy, Math.Round(validityDecisionNums / (invalidDecisionNums + validityDecisionNums), 2)); } #endregion #region ShotTarget private void UpdatePrecision() { double totalShot = TotalHitNum + MissHitNum; double precision = 0; if (totalShot != 0) { precision = Math.Round(TotalHitNum / totalShot, 2); } SetResultMetricsDataValue(MetricsType.Precision, precision); } private void OnShottedTargetEvent(BaseShotTarget target) { if (target != null) { TotalHitNum++; CalculateShootingResult((target as SphereShotTarget).defaultColor); TimerSystem.GetInstance().RemoveTimeTask(m_ObserveTimer); JudgeShotStep nextStep = curStep == JudgeShotStep.Judge ? JudgeShotStep.Observe : JudgeShotStep.Judge; SwitchTrainStep(nextStep); } else { comboNums = 0; int missPunitiveS = 0; switch (curStep) { case JudgeShotStep.Observe: missPunitiveS = Mathf.CeilToInt(m_ScoreData.singleWheelBaseScore * m_ScoreData.singleWheelMissPunitiveMul) + Random.Range(-2, 2); break; case JudgeShotStep.Judge: missPunitiveS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.doubleWheelMissPunitiveMul) + Random.Range(-2, 2); break; } IncreaseScore(missPunitiveS * -1); MissHitNum++; } } #endregion private void SwitchTrainStep(JudgeShotStep step) { ResetTarget(); curStep = step; StartBestHitTimer(); switch (curStep) { case JudgeShotStep.Observe: ExecuteObserveStepTarget(); break; case JudgeShotStep.Judge: ExecuteJudgeStepTarget(); break; } } private void ExecuteObserveStepTarget() { GameObject obj = GameObject.Instantiate(Resources.Load("Prefabs/SphereTarget")); SphereShotTarget target = obj.GetComponent(); target.onClickCanChangeColor = false; target.onHoveringCanChangeColor = false; target.defaultColor = RandomTargetColorType(); Vector3 centerPos = new Vector3(0, 0, m_DifficultyData.targetDistance); target.Init(1, ReduceHealthTriggerType.OnClick, false, ReduceHealthType.Per, MotionType.None, centerPos); curTargets.Add(target); target.IsRunning = true; } private void ExecuteJudgeStepTarget() { for (int i = 0; i < 2; i++) { GameObject obj = GameObject.Instantiate(Resources.Load("Prefabs/SphereTarget")); SphereShotTarget target = obj.GetComponent(); curTargets.Add(target); target.IsRunning = true; target.onClickCanChangeColor = false; target.onHoveringCanChangeColor = false; target.defaultColor = i == 0 ? curTargetColor : RandomTargetColorType(); target.Init(1, ReduceHealthTriggerType.OnClick, false, ReduceHealthType.Per, MotionType.None, RandomPosition()); } m_ObserveTimer = TimerSystem.GetInstance().AddTimeTask(ObserveTimeOut, m_DifficultyData.observeTime); } private void ObserveTimeOut() { invalidDecisionNums++; totalReactionTime += m_DifficultyData.observeTime; comboNums = 0; int outTimePunitiveS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.doubleWheelOutTimePunitiveMul) + Random.Range(-2, 2); IncreaseScore(outTimePunitiveS * -1); SwitchTrainStep(JudgeShotStep.Observe); } private void CalculateShootingResult(Color color) { switch (curStep) { case JudgeShotStep.Observe: CalculateObserveStepResult(color); break; case JudgeShotStep.Judge: CalculateJudgeStepResult(color); break; } } private void CalculateObserveStepResult(Color color) { curTargetColor = color; int comboS = Mathf.CeilToInt(m_ScoreData.singleWheelBaseScore * comboNums * m_ScoreData.comboMul); int bestS = m_IsBestHit ? Mathf.CeilToInt(m_ScoreData.singleWheelBaseScore * m_ScoreData.bestHitMul) + Random.Range(-1, 3) : 0; IncreaseScore(m_ScoreData.singleWheelBaseScore + comboS + bestS); comboNums++; } private void CalculateJudgeStepResult(Color color) { bool validity = curTargetColor == color; if (validity) { validityDecisionNums++; int comboS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * comboNums * m_ScoreData.comboMul); int bestS = m_IsBestHit ? Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.bestHitMul) + Random.Range(-1, 3) : 0; IncreaseScore(m_ScoreData.doubleWheelBaseScore + comboS + bestS); comboNums++; } else { invalidDecisionNums++; comboNums = 0; int falsePunitiveS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.doubleWheelFalsePunitiveMul) + Random.Range(-3, 3); IncreaseScore(falsePunitiveS * -1); } totalReactionTime += m_ObserveTimer.delay - m_ObserveTimer.remainingTime; } private Color RandomTargetColorType() { Color color = colors[Random.Range(0, colors.Count)]; while (color == curTargetColor) { color = colors[Random.Range(0, colors.Count)]; } return color; } private Vector3 RandomPosition() { List positions = curTargets.GetGameObjectWorldPosition(); Vector2 widthLimt = Vector2.zero; Vector2 heightLimt = Vector2.zero; switch (m_DifficultyType) { case DifficultyType.Standard: widthLimt = new Vector2(-4, 4); heightLimt = new Vector2(-1.5f, 1.5f); break; case DifficultyType.Advance: widthLimt = new Vector2(-8, 8); heightLimt = new Vector2(-1.5f, 3.5f); break; case DifficultyType.Professional: widthLimt = new Vector2(-8, 8); heightLimt = new Vector2(-1.5f, 5f); break; } Vector3 min = ExtraTool.GetScreenOffsetPosition(ExtraTool.Sphere_Diameter1_ScreenLeftBottomOffset, m_DifficultyData.targetDistance, widthLimt, heightLimt); Vector3 max = ExtraTool.GetScreenOffsetPosition(ExtraTool.Sphere_Diameter1_ScreenRightTopOffset, m_DifficultyData.targetDistance, widthLimt, heightLimt); if (ExtraTool.TryGetNonOverlapRamdonPos(positions, min, max, 1, out Vector3 ramdonPos, false)) { return ramdonPos; } else { return new Vector3(0, 0, m_DifficultyData.targetDistance); } } private void ResetTarget() { for (int i = 0; i < curTargets.Count; i++) { curTargets[i].IsRunning = false; GameObject.Destroy(curTargets[i].gameObject); } curTargets.Clear(); } } }