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; using System.Linq; namespace ShotSimulator.Train { public class MemoryShotTrainHandle : BaseTrainHandle { private List RandomColors = new List() { Color.red,Color.yellow,Color.green,Color.blue, new Color(1,165f/255f,0),//³بة« new Color(148f/255f,0,211f/255f),//×دة« new Color(1,192f/255,203f/255f)//·غة« }; private Color curTargetColor; private List falseColors = new List(); private int curGenerateTargetNumIndex; private List generateTargetNum = new List { 4, 5 }; private List generateTargetPos = new List(); private float curTargetDistance; private JudgeShotStep curStep = JudgeShotStep.Observe; private TimeTask m_ObserveTimer; private TimeTask m_IntervalTimer; private List curTargets = new List(); private MemoryShotTrainDifficultyData m_DifficultyData; private MemoryShotTrainScoreData m_ScoreData; protected float totalReactionTime; private float invalidDecisionNums; private float validityDecisionNums; private float curObaserveFinishTime; 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 MemoryShotTrainHandle(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; TimerSystem.GetInstance().RemoveTimeTask(m_IntervalTimer); m_IntervalTimer = null; falseColors.Clear(); curGenerateTargetNumIndex = 0; generateTargetPos.Clear(); curTargetDistance = 0; totalReactionTime = 0; invalidDecisionNums = 0; validityDecisionNums = 0; curObaserveFinishTime = 0; m_TotalHitNum = 0; m_MissHitNum = 0; } public override void StartTrain() { base.StartTrain(); SwitchTrainStep(JudgeShotStep.Observe); } public override void PauseTrain() { base.PauseTrain(); if (m_ObserveTimer != null) { m_ObserveTimer.pause = true; } if (m_IntervalTimer != null) { m_IntervalTimer.pause = true; } } public override void ContinueTrain() { base.ContinueTrain(); if (m_ObserveTimer != null) { m_ObserveTimer.pause = false; } if (m_IntervalTimer != null) { m_IntervalTimer.pause = false; } } public override void CalculateTrainResult() { SetResultMetricsDataValue(MetricsType.ReactionTime, Math.Round(totalReactionTime / (invalidDecisionNums + validityDecisionNums), 2)); SetResultMetricsDataValue(MetricsType.DeactionAccurancy, Math.Round(validityDecisionNums / (invalidDecisionNums + validityDecisionNums), 2)); SetResultMetricsDataValue(MetricsType.VisualMemory, validityDecisionNums); } #endregion private void UpdatePrecision() { double totalShot = TotalHitNum + MissHitNum; double precision = 0; if (totalShot != 0) { precision = Math.Round(TotalHitNum / totalShot, 2); } SetResultMetricsDataValue(MetricsType.Precision, precision); } #region ShotTarget private void OnShottedTargetEvent(BaseShotTarget target) { if (curStep == JudgeShotStep.Judge) { if (target != null) { CalculateShootResult((target as SphereShotTarget).defaultColor); SwitchTrainStep(JudgeShotStep.Observe); TotalHitNum++; } else { comboNums = 0; MissHitNum++; } } } #endregion private void SwitchTrainStep(JudgeShotStep step) { ResetTarget(); curStep = step; switch (curStep) { case JudgeShotStep.Observe: ExecuteObserveStepTarget(); break; case JudgeShotStep.Judge: ExecuteJudgeStepTarget(); break; } } private void ExecuteObserveStepTarget() { generateTargetPos.Clear(); falseColors.Clear(); falseColors.AddRange(RandomColors); falseColors.FisherYatesShuffle(); curTargetColor = falseColors[0]; falseColors.RemoveAt(0); int removeNum = falseColors.Count - generateTargetNum[curGenerateTargetNumIndex % generateTargetNum.Count]; while (removeNum > 0) { falseColors.RemoveAt(0); removeNum--; } curTargetDistance = Random.Range(5f, 7f); for (int i = 0; i < falseColors.Count; i++) { GameObject obj = GameObject.Instantiate(Resources.Load("Prefabs/SphereTarget")); SphereShotTarget target = obj.GetComponent(); curTargets.Add(target); target.onClickCanChangeColor = false; target.onHoveringCanChangeColor = false; target.defaultColor = falseColors[i]; Vector3 pos = RandomPosition(); generateTargetPos.Add(pos); target.Init(1, ReduceHealthTriggerType.None, false, ReduceHealthType.Per, MotionType.None, pos); target.IsRunning = true; } curGenerateTargetNumIndex++; m_ObserveTimer = TimerSystem.GetInstance().AddTimeTask(ObserveTimeOut, m_DifficultyData.observeTime); } private void ExecuteJudgeStepTarget() { StartBestHitTimer(); //falseColors.FisherYatesShuffle(); int index = Random.Range(0, falseColors.Count); for (int i = 0; i < falseColors.Count; 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 == index ? curTargetColor : falseColors[i]; target.Init(1, ReduceHealthTriggerType.OnClick, false, ReduceHealthType.Per, MotionType.None, generateTargetPos[i]); } } private void ObserveTimeOut() { ResetTarget(); m_IntervalTimer = TimerSystem.GetInstance().AddTimeTask(IntervalTimerTimeOut, 0.5f); } private void IntervalTimerTimeOut() { curObaserveFinishTime = m_TaskTimer.remainingTime; SwitchTrainStep(JudgeShotStep.Judge); } private void CalculateShootResult(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) : 0; IncreaseScore(m_ScoreData.doubleWheelBaseScore + comboS + bestS); comboNums++; } else { invalidDecisionNums++; comboNums = 0; int falsePunitiveS = Mathf.CeilToInt(m_ScoreData.doubleWheelBaseScore * m_ScoreData.doubleWheelFalsePunitiveMul); IncreaseScore(falsePunitiveS * -1); } totalReactionTime += (curObaserveFinishTime - m_TaskTimer.remainingTime); } private Vector3 RandomPosition() { List positions = curTargets.GetGameObjectWorldPosition(); Vector2 widthLimt = new Vector2(-4, 4); Vector2 heightLimt = new Vector2(-1.5f, 1.5f); Vector3 min = ExtraTool.GetScreenOffsetPosition(ExtraTool.Sphere_Diameter1_ScreenLeftBottomOffset, curTargetDistance, widthLimt, heightLimt); Vector3 max = ExtraTool.GetScreenOffsetPosition(ExtraTool.Sphere_Diameter1_ScreenRightTopOffset, curTargetDistance, widthLimt, heightLimt); if (ExtraTool.TryGetNonOverlapRamdonPos(positions, min, max, 1, out Vector3 ramdonPos, false)) { return ramdonPos; } else { return new Vector3(0, 0, curTargetDistance); } } private void ResetTarget() { for (int i = 0; i < curTargets.Count; i++) { curTargets[i].IsRunning = false; GameObject.Destroy(curTargets[i].gameObject); } curTargets.Clear(); } } }