//(協程)獲得中獎報酬 //[param] prize = 中獎獎金 , prizeInfoList = 所有線段的中獎資訊列表 public IEnumerator Cor_GetPrize(int prize, List <PrizeLineInfo> prizeInfoList) { if (prize <= 0) { yield break; //中獎獎金小於0, 直接結束程序 } //金幣收集特效 List <PrizeLineInfo> _infoList = new List <PrizeLineInfo>(); _infoList.AddRange(prizeInfoList); //複製一份新的資訊列表 _infoList.RemoveAll((PrizeLineInfo x) => //篩掉沒有中獎的線段 { if (x.sumPrize <= 0) { return(true); } else { return(false); } }); List <Vector2> worldPosList = new List <Vector2>(); for (int i = 0; i < _infoList.Count; i++) { for (int j = 0; j < _infoList[i].drawedPosList.Count; j++) { Vector2 _pos = ScrollManager.Instance.Dict_cdnToWorldPos[_infoList[i].drawedPosList[j]]; //從座標編號轉換成世界位置 worldPosList.Add(_pos); //將世界位置加入列表 ParticleEffectController.Instance.OneShotEffect(ParticleEffectType.金幣收集, _pos, true, _infoList[i].sumPrize); } } AudioManagerScript.Instance.PlayAudioClip("SE金幣"); //中獎圖格特效 worldPosList = ListExtensibleScript <Vector2> .RepetitionFilter(worldPosList); for (int i = 0; i < worldPosList.Count; i++) { ParticleEffectController.Instance.OneShotEffect(ParticleEffectType.中獎圖格, worldPosList[i], true); } //累積拉霸等級獎金 Coroutine cor_UnlockPrize = StartCoroutine(SpinLevelPanel.Instance.Cor_AccumulateUnlockPrize(prize)); yield return(new WaitForSeconds(gainMoneyEffectDelay)); //獲得獎金 Coroutine cor_Set = StartCoroutine(Cor_SetMoney(nowMoney + prize, true)); //等待拉霸等級解鎖&獲得獎金特效 yield return(cor_UnlockPrize); yield return(cor_Set); }
//創建燈號 private void BuildLamps(object sender, BuildLampsEventArgs eventArgs) { GameObject _prefab = LevelLampManager.Instance.lampPrefab; //取得燈號物件預置體 LotteryLineSetting _setting = eventArgs.setting; //取得設定集 List <LineDrawer> _activeLineList = eventArgs.activeLines; //取得有效線段列表 List <int> _preBuildList = new List <int>(); //待創建等級列表 for (int i = 0; i < _activeLineList.Count; i++) //遍歷所有線段 { if ((columnSide == WindowSide.左側 && _activeLineList[i].coordinates[0].y == rowNumber) || //窗格在左側 且 中獎線的左端點列數與窗格列數相符何時 (columnSide == WindowSide.右側 && _activeLineList[i].coordinates[_activeLineList[i].coordinates.Count - 1].y == rowNumber)) //窗格在右側 且 中獎線的右端點列數與窗格列數相符何時 { _preBuildList.Add(_activeLineList[i].level); //加入等級列表 } } _preBuildList = ListExtensibleScript <int> .RepetitionFilter(_preBuildList); //篩掉重複值 _preBuildList.Sort(); //排序 if (rowNumber < 0) { _preBuildList.Reverse(); //列號為負值時(下方列), 倒轉燈號等級順序(使之對稱) } float _height = LevelLampManager.Instance.defaultHeight; //取得燈號預設高度 for (int i = 0; i < _preBuildList.Count; i++) //逐一設定燈號 { if (lampList.Count < i + 1) //若燈號物件不足時, 創立新物件 { GameObject _go = Instantiate(_prefab, this.transform); //創立物件 LevelLamp _lamp = _go.GetComponent <LevelLamp>(); //取得腳本 lampList.Add(_lamp); //加入列表 } lampList[i].Initialize(_preBuildList[i], _setting.lotteryLineLevelList[_preBuildList[i] - 1].lineColor, _setting.lotteryLineLevelList[_preBuildList[i] - 1].inactiveColor, _height); //設定燈號 } for (int i = _preBuildList.Count; i < lampList.Count; i++) //暫時隱藏多餘的燈號 { lampList[i].Invalid(); } }
//--------------------------------------------------------------------------------------------------------------------------------------------- //拉霸 public void PullLever() { if (leverCanUse) //拉桿可控制時 { SetOperationState(false); //操作狀態設為禁止 SlotLevel _nowSlot = ScrollManager.Instance.slotLevelLayoutSetting[nowSlotLevel]; //取得拉霸等級設定 SpinModePack _spinModeList = ListExtensibleScript <SpinModePack> .RandomReturn(_nowSlot.spinModeSetting); //取得旋轉模式列表 ScrollManager.Instance.Spin(_spinModeList, _nowSlot.linkTime); //ScrollManager.Instance.Spin(true, 12, 2f, 0.6f); } else if (leverCanSnap) //捲軸旋轉中, 手動中斷捲軸 { //當拉霸動畫尚未撥放完畢時, 禁止操作拉霸 AnimatorStateInfo _leverAnimInfo = ScrollManager.Instance.leverAnim.GetCurrentAnimatorStateInfo(0); if ((_leverAnimInfo.IsName("lever_spin") || _leverAnimInfo.IsName("lever_snap")) && _leverAnimInfo.normalizedTime <= 1) { return; } if (ScrollBehavior.s_scrollRollingStates != null && ScrollBehavior.s_scrollRollingStates.Length > 0) { for (int i = 0; i < ScrollBehavior.s_scrollRollingStates.Length; i++) //當有任何捲軸處於旋轉狀態時, 操控拉霸依序中斷旋轉 { if (ScrollBehavior.s_scrollRollingStates[i]) { AudioManagerScript.Instance.PlayAudioClip("SE捲軸中斷"); ScrollManager.Instance.leverAnim.Play("lever_snap", 0, 0); //撥放捲軸中斷動畫 ScrollBehavior.s_scrollRollingStates[i] = false; break; } } } } }
//捲軸旋轉(協程) //[param] spinModeList = 旋轉模式 , linkTime = 牽動等待時間 , isTest = 測試與否 private IEnumerator Cor_BeginSpin(List <SpinMode> spinModeList, float linkTime, bool isTest) { if (!isTest) //測試的狀況跳過 { if (spinModeList.Count != scrollCount && spinModeList.Count != 1) { throw new System.Exception("[ERROR]輸入的旋轉模式設定有誤!"); } //旋轉前準備 if (MoneyManager.Instance.nowMoney < BetController.Instance.nowBetMoney) { AudioManagerScript.Instance.PlayAudioClip("SE取消"); Coroutine moneyNotEnough = StartCoroutine(MoneyManager.Instance.Cor_MoneyNotEnough()); //錢不夠提示 yield return(moneyNotEnough); GameController.Instance.SetOperationState(true); //操作狀態設為允許 yield break; } leverAnim.Play("lever_spin", 0, 0); //撥放動畫 AudioManagerScript.Instance.PlayAudioClip("SE拉桿"); StartCoroutine(MoneyManager.Instance.Cor_SetMoney(MoneyManager.Instance.nowMoney - BetController.Instance.nowBetMoney, false)); //扣除賭金 StopAllElementAnimation(); //停止所有圖格動畫 } //預估旋轉結果 List <List <ElementImageType> > spinResult = BuildResultScroll(); //旋轉結果 List <SensorInfo> blocksResult = new List <SensorInfo>(); //將旋轉結果的圖格列表形式轉換成捲軸偵測器形式 for (int i = 0; i < posSensorArray.Count; i++) { SensorInfo _info = new SensorInfo(); //建立偵測器 _info.coordinate = posSensorArray[i].coordinate; _info.elementType = spinResult[(int)posSensorArray[i].coordinate.x][i % visibleElementCount]; blocksResult.Add(_info); //加入列表 } //Debug.Log("BlocksResult Test -------------"); //for (int i = 0; i < blocksResult.Count; i++) //{ // Debug.Log(string.Format("({0}, {1}) = {2}", blocksResult[i].coordinate.x, blocksResult[i].coordinate.y, blocksResult[i].elementType)); //} List <PrizeLineInfo> prizeLineDistribution = new List <PrizeLineInfo>(); //中獎資訊列表 int prizeTotal = 0; //總獎金 List <LineDrawer> _workingLineList = LotteryLineManager.Instance.GetWorkingLines(); //取得有效線段 List <Vector2> _drawedPosList = new List <Vector2>(); //中獎圖格座標列表 for (int i = 0; i < _workingLineList.Count; i++) //遍歷所有線段是否中獎 { PrizeLineInfo _pInfo = _workingLineList[i].RewardJudgement(blocksResult, PrizeTableManager.Instance.prizeTable.m_data); //判斷該線段中獎資訊, 並將其儲存 _drawedPosList.AddRange(_pInfo.drawedPosList); //加入中獎圖格座標列表 if (_pInfo.sumPrize > 0) //有中獎時 { prizeTotal += _pInfo.sumPrize; //總獎金累計 } prizeLineDistribution.Add(_pInfo); } //Debug.Log("總計中獎獎金 = " + prizeTotal); //for (int i = 0; i < prizeLineDistribution.Count; i++) //{ // Debug.Log(string.Format("等級 {0} 合計中獎獎金 = {1}", prizeLineDistribution[i].lineLevel, prizeLineDistribution[i].sumPrize)); //} #if UNITY_EDITOR if (isTest) //測試的狀況 { TestPanelManager.Instance.FeedbackSimulateResult(prizeLineDistribution); //儲存模擬結果 yield break; } #endif _drawedPosList = ListExtensibleScript <Vector2> .RepetitionFilter(_drawedPosList); //篩掉列表中的重複元素 //捲軸旋轉狀態 bool[] _stateArr = new bool[scrollCount]; for (int i = 0; i < _stateArr.Length; i++) { _stateArr[i] = false; } ScrollBehavior.s_scrollRollingStates = _stateArr; //初始化旋轉狀態 GameController.Instance.leverCanSnap = true; //可手動中斷捲軸 //捲軸旋轉動畫 //float _delayTime = 0; //捲軸煞停延遲時間 for (int i = 0; i < scrollCount; i++) //逐個捲軸執行旋轉動作 { int _index = 0; if (spinModeList.Count > 1) { _index = i; //若為統一旋轉模式則List索引固定為0, 若個別指定則索引值隨迴圈變動 } bool _dir = spinModeList[_index].direction; //旋轉方向 float _speed = spinModeList[_index].elementSpeed; //旋轉速度 float _time = spinModeList[_index].spinTime; //旋轉時間 float _sliderSpeed = ((_dir ? _speed : -_speed) / (scrollGroup[i].elementChain.Count - visibleElementCount)) * Time.fixedDeltaTime; //換算速度(圖格速度 ➡ 拉條速度) StartCoroutine(scrollGroup[i].Cor_ScrollSpin(_sliderSpeed, _time, spinResult[i], scrollStartingCurve)); if (i == scrollCount - 1) //最後一個捲軸動作時, 紀錄煞停延遲時間 { //_delayTime = ( (float)( visibleElementCount + 1 ) / ( scrollGroup[i].elementChain.Count - visibleElementCount ) ) / ( Mathf.Abs(_sliderSpeed) * ( 1f / Time.fixedDeltaTime ) ); //Debug.Log("SliderSpeed(/s) = " + ( ( Mathf.Abs(_sliderSpeed) * ( 1f / Time.fixedDeltaTime ) ) )); //Debug.Log("Vc = " + visibleElementCount); //Debug.Log("t - Vc = " + ( scrollGroup[i].elementChain.Count - visibleElementCount )); //Debug.Log("Vc / (t - Vc) = " + ( (float)visibleElementCount / ( scrollGroup[i].elementChain.Count - visibleElementCount ) )); //Debug.Log("DelayTime = " + _delayTime); break; } yield return(new WaitForSeconds(linkTime)); } for (int i = 0; i < scrollCount; i++) //等待所有捲軸旋轉完畢 { yield return(new WaitWhile(() => scrollGroup[i].isRolling)); } yield return(new WaitForSeconds(brakeBufferTime)); GameController.Instance.leverCanSnap = false; //禁止手動中斷捲軸 PositionSensorEventArgs eventArgs = new PositionSensorEventArgs(visibleElementCount * scrollCount); if (SpinJudged != null) { SpinJudged.Invoke(this, eventArgs); } yield return(new WaitUntil(() => (eventArgs.overNumber == 0))); //等待所有圖格位置偵測器觸發結束 //for (int i = 0; i < eventArgs.SpinResultList.Count; i++) //{ // Debug.Log(string.Format("[{0}] ({1}, {2}) : {3}", i, eventArgs.SpinResultList[i].coordinate.x, eventArgs.SpinResultList[i].coordinate.y, eventArgs.SpinResultList[i].elementType)); //} //旋轉結果 previousSpinResult = eventArgs.SpinResultList; //記錄拉霸結果 PlayElementAnimation(ElementAnimationType.中獎, _drawedPosList, true); //中獎圖格特效 yield return(StartCoroutine(MoneyManager.Instance.Cor_GetPrize(prizeTotal, prizeLineDistribution))); //獲得獎金 GameController.Instance.SetOperationState(true); //操作狀態設為允許 }
//中獎判定 //[output] List<PrizeInfo> = 中獎資訊列表 //[param] sensorInfo = 位置偵測器資訊(各座標上對應的圖格類型) , prizeTable = 支付表設定 public PrizeLineInfo RewardJudgement(List <SensorInfo> sensorInfo, List <PrizeCombination> prizeTableSource) { PrizeLineInfo _resultList = new PrizeLineInfo(); if (level == 0 || !isWorking) { return(null); //中獎線等級為0 或 線段未啟用 則不計算中獎 } List <ElementImageType> _imageLine = new List <ElementImageType>(); //線上的圖格類型 for (int i = 0; i < coordinates.Count; i++) //遍歷線上所有點的座標 { for (int j = 0; j < sensorInfo.Count; j++) //遍歷所有圖格資訊 { if (sensorInfo[j].coordinate == coordinates[i]) //取得指定位置上的圖格 { _imageLine.Add(sensorInfo[j].elementType); continue; } } } if (_imageLine.Count != coordinates.Count) { throw new System.Exception("[ERROR]線段各點座標與圖格位置座標不完全一致"); } //for (int i = 0; i < _imageLine.Count; i++) //{ // Debug.Log(string.Format("({0}, {1}) : {2}", coordinates[i].x, coordinates[i].y, _imageLine[i])); //} List <PrizeCombination> prizeTable = new List <PrizeCombination>(); prizeTable.AddRange(prizeTableSource); //排序支付表組合(組合長度多排到少) prizeTable.Sort((PrizeCombination x, PrizeCombination y) => { if (x.combinations.Count > y.combinations.Count) { return(-1); } if (x.combinations.Count < y.combinations.Count) { return(1); } return(0); }); List <PrizeCombination> _drawedCombs = new List <PrizeCombination>(); //判定成功(有中獎)的支付表組合 //Debug.Log("[ 線段 " + this.gameObject.name + " 開始判斷]"); for (int i = 0; i < prizeTable.Count; i++) //逐一檢查支付表所有組合 { bool _isMatch = false; //任一項有符合(淺層判斷) bool _matchPass = false; //跳過淺層判斷 for (int j = 0; j < _imageLine.Count; j++) //若線上有任一狂野符號, 直接進入深層判斷(中獎判斷) { if (ScrollManager.Instance.Dict_wildSymbol[_imageLine[j]]) { _matchPass = true; _isMatch = true; break; } } if (!_matchPass) //沒有狂野符號時, 檢測線上所有圖格是否有任意一項與支付表組合圖格相符(淺層判斷) { if (prizeTable[i].PureTest()) //若組合為純元素構成(只輸入一個圖格類型, 節省遍歷時間) { _isMatch = ElementListMatchTest(_imageLine, new List <ElementImageType>() { prizeTable[i].combinations[0] }); } else //若組合為混和元素構成 { _isMatch = ElementListMatchTest(_imageLine, prizeTable[i].combinations); } } if (_isMatch) //若有任意一項圖格相符時, 深入判斷中獎與否 { int _prize = 0; //中獎獎金 for (int j = 0; j < _drawedCombs.Count; j++) //判斷中獎的組合是否包含此組合 { _prize += prizeTable[i].Comparison(_drawedCombs[j].combinations).prizeMoney; } if (_prize == 0) //已經中獎的組合如果有包含此組合, 則跳過此組合的判斷, 避免重複中獎 { CombinationPrizeInfo _cbInfo = prizeTable[i].Comparison(_imageLine); //取得中獎資訊 if (_cbInfo.prizeMoney > 0) //若獎金大於0(有中獎) { _drawedCombs.Add(prizeTable[i]); //加入判定成功組合列表 for (int j = 0; j < _cbInfo.matchedPosList.Count; j++) //對照索引值紀錄相應的座標 { _resultList.drawedPosList.Add(coordinates[_cbInfo.matchedPosList[j]]); } _resultList.AddCombinationItem(_cbInfo); } } } } _resultList.lineLevel = level; //設定中獎線等級 _resultList.drawedPosList = ListExtensibleScript <Vector2> .RepetitionFilter(_resultList.drawedPosList); //篩掉列表中的重複元素 return(_resultList); }