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; private IActionController _controller; #region 功能参数 private int _batchIdx; private readonly Dictionary _moleModules; private readonly List _batchHandlers; public WhackMoleRes res; public event Action OnGameEnd; public event Action OnBatchEnd; #endregion public WhackMoleHandler(WhackMoleData data) { res = new WhackMoleRes(); _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(); _controller = ActionKit.Coroutine(_batchHandlers[_batchIdx].StartBatch).StartGlobal(); } private List CreateBatchHandler(WhackMoleData data) { List handlers = new(); for (int i = 0; i < data.totalBatchNum; i++) { var curHandler = new WhackMoleBatchHandler(_moleModules.Values, data, i); curHandler.OnBatchEnd += HandleBatch; handlers.Add(curHandler); } return handlers; } private void HandleBatch(int hitMoleNum) { _batchIdx++; res.hitMoleNum += hitMoleNum; res.passBatchNum++; if (_batchIdx >= _data.totalBatchNum && _data.totalBatchNum > 0) { OnGameEnd?.Invoke(); return; } OnBatchEnd?.Invoke(); // 继续下一个批次,如果有中间状态就在这里处理 _controller = ActionKit.Sequence().Delay(_data.GetBatchGap()).Coroutine(_batchHandlers[_batchIdx].StartBatch) .StartGlobal(); } public void EndWhackGame() { WhackMoleSystem.StopAllFlicker(); _controller.Reset(); _controller = null; } } 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; } }