using System; using System.Collections; using System.Collections.Generic; using AibisDream.Framework; using AibisDream.Kit; using UnityEngine; using Random = UnityEngine.Random; namespace AibisDream.FixSystem { public class WhackMoleHandler { private static readonly WhackMoleSystem WhackMoleSystem = FixSystemCenter.SystemDic.Get(); private readonly WhackMoleData _data; #region 功能参数 private int _batchIdx; private readonly Dictionary _moleModules; private readonly List _batchHandlers; private WhackMoleRes _res; public event Action OnGameEnd; #endregion public WhackMoleHandler(WhackMoleData data) { _data = data; _batchIdx = 0; _moleModules = WhackMoleSystem.MoleModules; // 生成batch序列并链接 _batchHandlers = CreateBatchHandler(data); // 统计一些基本数据 CalcBaseData(); } private void CalcBaseData() { _res.totalMoleBatch = _data.totalBatchNum; for (int i = 0; i < _data.totalBatchNum; i++) { _res.totalMoleNum += _data.GetBatch(i).moleNum; } } public void Start() { foreach (var mole in _moleModules.Values) { mole.isInMoleGame = true; } WhackMoleSystem.StartAllFlicker(); ActionKit.Coroutine(_batchHandlers[_batchIdx].StartBatch).StartGlobal(); } private List CreateBatchHandler(WhackMoleData data) { List res = new(); for (int i = 0; i < data.totalBatchNum; i++) { var curHandler = new WhackMoleBatchHandler(_moleModules.Values, data, i); curHandler.OnBatchEnd += OnBatchEnd; res.Add(curHandler); } return res; } private void OnBatchEnd(int hitMoleNum) { _batchIdx++; _res.hitMoleNum += hitMoleNum; _res.passBatchNum++; if (_batchIdx >= _data.totalBatchNum) { WhackMoleSystem.StopAllFlicker(); OnGameEnd?.Invoke(_res); return; } // 继续下一个批次,如果有中间状态就在这里处理 ActionKit.Sequence().Delay(_data.batchGap).Coroutine(_batchHandlers[_batchIdx].StartBatch).StartGlobal(); } } public class WhackMoleBatchHandler { private readonly WhackMoleData _globalData; private readonly ISelector _moleSelector; private readonly List _lightGaps = new(); private readonly List _lightingMoles = new(); private bool _isBatchEnd; private int _hitMoleNum; public event Action OnBatchEnd; public WhackMoleBatchHandler(IEnumerable molesModules, WhackMoleData data, int index) { _globalData = data; var batchData = data.GetBatch(index); // 创建选择器 _moleSelector = new LimitedSelector(molesModules); // 设置亮起时间间隔 for (var i = 0; i < batchData.moleNum; i++) { var gap = Random.Range(batchData.durationRange.x, batchData.durationRange.y); _lightGaps.Add(gap); } _lightGaps.Sort(); } public IEnumerator StartBatch() { // 利用协程记时 float batchTime = 0f; while (!_isBatchEnd) { OnUpdate(batchTime); batchTime += Time.deltaTime; yield return null; } OnBatchEnd?.Invoke(_hitMoleNum); OnBatchEnd = null; } private void OnUpdate(float batchTime) { // 点亮一些模块,其他的继续闪烁 while (_lightGaps.Count > 0 && _lightGaps[0] <= batchTime) { var lightOnMole = _moleSelector.Select(); lightOnMole.LightOn(_globalData.moleExistTime); lightOnMole.OnLightMoleEnd += OnLightMoleEnd; // 最后同步其他容器 _lightGaps.RemoveAt(0); _lightingMoles.Add(lightOnMole); } } private void OnLightMoleEnd(MoleModule mole, bool isPlugin) { // 从亮起列表中移除 _lightingMoles.Remove(mole); if (isPlugin) _hitMoleNum++; // 当所有模块都熄灭的时候,游戏结束 if (_lightingMoles.Count <= 0 && _lightGaps.Count <= 0) { _isBatchEnd = true; } } } public struct WhackMoleRes { public int totalMoleBatch; public int failBatchNum; public int passBatchNum; public int totalMoleNum; public int hitMoleNum; } }