// ================================================================ // // 显示所有的标记 private void draw_markers() { foreach (var marker in m_markers) { marker.setVisible(false); marker.hideLineNumberText(); } if (m_musicManager.IsPlaying()) { SongInfo song = m_musicManager.currentSongInfo; // 开始显示的标记(检索单元上更晚的那个位置) int begin = m_seekerBack.nextIndex; // 结束显示的标记(检索单元上更早的那个位置) int end = m_seekerFront.nextIndex; float x_offset; int marker_draw_index = 0; // 绘制用于提示命中时机的图标 for (int drawnIndex = begin; drawnIndex < end; drawnIndex++) { float size = ScoringManager.timingErrorToleranceGood * m_pixelsPerBeats; OnBeatActionInfo info = song.onBeatActionSequence[drawnIndex]; // tension值高时,跳跃动作的标记也变大 if (m_scoringManager.temper > ScoringManager.temperThreshold && info.playerActionType == PlayerActionEnum.Jump) { size *= 1.5f; } // 计算节奏圆到标记的X坐标偏移值 x_offset = info.triggerBeatTiming - m_musicManager.beatCount; x_offset *= m_pixelsPerBeats; float pos_x = markerOrigin.x + x_offset; float pos_y = markerOrigin.y; m_markers[marker_draw_index].draw(pos_x, pos_y, size); // 在开发模式下,显示文本文件中的行号 if (isDevelopmentMode) { m_markers[marker_draw_index].dispLineNumberText(info.line_number); } marker_draw_index++; } } }
// ================================================================ // // マーカーをぜんぶ表示する. private void draw_markers() { foreach (var marker in m_markers) { marker.setVisible(false); marker.hideLineNumberText(); } if (m_musicManager.IsPlaying()) { SongInfo song = m_musicManager.currentSongInfo; // 表示を開始するマーカー(遅れているシークユニットのシーク位置). int begin = m_seekerBack.nextIndex; // 表示を終了するマーカー(進んでいるシークユニットのシーク位置). int end = m_seekerFront.nextIndex; float x_offset; int marker_draw_index = 0; // アクションタイミングを示すアイコンを描画. for (int drawnIndex = begin; drawnIndex < end; drawnIndex++) { float size = ScoringManager.timingErrorToleranceGood * m_pixelsPerBeats; OnBeatActionInfo info = song.onBeatActionSequence[drawnIndex]; // テンションが高いとき、ジャンプアクションのマーカーを大きくする. if (m_scoringManager.temper > ScoringManager.temperThreshold && info.playerActionType == PlayerActionEnum.Jump) { size *= 1.5f; } // ビートサークルからマーカーまでの X 座標のオフセットを求める. x_offset = info.triggerBeatTiming - m_musicManager.beatCount; x_offset *= m_pixelsPerBeats; float pos_x = markerOrigin.x + x_offset; float pos_y = markerOrigin.y; m_markers[marker_draw_index].draw(pos_x, pos_y, size); // 開発モードのときは、テキストファイル中の行番号を表示する. if (isDevelopmentMode) { m_markers[marker_draw_index].dispLineNumberText(info.line_number); } marker_draw_index++; } } }
// 输出调试用的日志 private void DebugWriteLogPrev() { #if UNITY_EDITOR if (m_scoringUnitSeeker.isJustPassElement) { if (outScoringLog) { OnBeatActionInfo onBeatActionInfo = m_musicManager.currentSongInfo.onBeatActionSequence[m_scoringUnitSeeker.nextIndex - 1]; m_logWriter.WriteLine( onBeatActionInfo.triggerBeatTiming.ToString() + "," + "IdealAction,," + onBeatActionInfo.playerActionType.ToString() ); m_logWriter.Flush(); } } #endif }
public void DoAction(PlayerActionEnum actionType) { m_newPlayerAction = actionType; OnBeatActionInfo actionInfo = new OnBeatActionInfo(); actionInfo.triggerBeatTiming = m_musicManager.beatCountFromStart; actionInfo.playerActionType = m_newPlayerAction; m_lastActionInfo = actionInfo; if (actionType == PlayerActionEnum.HeadBanging) { gameObject.GetComponent <SimpleSpriteAnimation>().BeginAnimation(2, 1, false); } else if (actionType == PlayerActionEnum.Jump) { gameObject.GetComponent <SimpleActionMotor>().Jump(); gameObject.GetComponent <SimpleSpriteAnimation>().BeginAnimation(1, 1, false); } }
// 确认最近的艾tionInfo的索引 public int GetNearestPlayerActionInfoIndex() { SongInfo song = m_musicManager.currentSongInfo; int nearestIndex = 0; if (m_scoringUnitSeeker.nextIndex == 0) { // 如果目的位置是开头的话,没有前一个标记,所以不比较。 nearestIndex = 0; } else if (m_scoringUnitSeeker.nextIndex >= song.onBeatActionSequence.Count) { // 移动位置比排列的尺寸大的时候(过了最后的标记时间的时候) nearestIndex = song.onBeatActionSequence.Count - 1; } else { // 与前后的定时相比较 OnBeatActionInfo crnt_action = song.onBeatActionSequence[m_scoringUnitSeeker.nextIndex]; // 垃圾位置 OnBeatActionInfo prev_action = song.onBeatActionSequence[m_scoringUnitSeeker.nextIndex - 1]; // 希克位置的一个前 float act_timing = m_playerAction.lastActionInfo.triggerBeatTiming; if (crnt_action.triggerBeatTiming - act_timing < act_timing - prev_action.triggerBeatTiming) { // シーク位置(m_scoringUnitSeeker.nextIndex)の方が近かった. nearestIndex = m_scoringUnitSeeker.nextIndex; } else { // シーク位置のひとつ前(m_scoringUnitSeeker.nextIndex)の方が近かった. nearestIndex = m_scoringUnitSeeker.nextIndex - 1; } } return(nearestIndex); }
// 确认最近的ActionInfo的索引值 public int GetNearestPlayerActionInfoIndex() { SongInfo song = m_musicManager.currentSongInfo; int nearestIndex = 0; if (m_scoringUnitSeeker.nextIndex == 0) { // 定位位置如果在头部,不存在上一个标记所以不比较 nearestIndex = 0; } else if (m_scoringUnitSeeker.nextIndex >= song.onBeatActionSequence.Count) { // 如果定位位置比数组的尺寸还大(超过了最后标记的时刻) nearestIndex = song.onBeatActionSequence.Count - 1; } else { // 比较前后时间点的偏差 OnBeatActionInfo crnt_action = song.onBeatActionSequence[m_scoringUnitSeeker.nextIndex]; // 定位位置 OnBeatActionInfo prev_action = song.onBeatActionSequence[m_scoringUnitSeeker.nextIndex - 1]; // 上一个定位位置 float act_timing = m_playerAction.lastActionInfo.triggerBeatTiming; if (crnt_action.triggerBeatTiming - act_timing < act_timing - prev_action.triggerBeatTiming) { // 离定位位置(m_scoringUnitSeeker.nextIndex)更近 nearestIndex = m_scoringUnitSeeker.nextIndex; } else { // 离定位位置上一个位置(m_scoringUnitSeeker.nextIndex)更近 nearestIndex = m_scoringUnitSeeker.nextIndex - 1; } } return(nearestIndex); }
// 一番近いActionInfoのインデックスを確認. public int GetNearestPlayerActionInfoIndex() { SongInfo song = m_musicManager.currentSongInfo; int nearestIndex = 0; if (m_scoringUnitSeeker.nextIndex == 0) { // シーク位置が先頭だった場合、ひとつ前のマーカーは無いので比較しない. nearestIndex = 0; } else if (m_scoringUnitSeeker.nextIndex >= song.onBeatActionSequence.Count) { // シーク位置が配列のサイズより大きいとき(最後のマーカーの時刻を過ぎていたとき). nearestIndex = song.onBeatActionSequence.Count - 1; } else { // 前後のタイミングとのずれを比較. OnBeatActionInfo crnt_action = song.onBeatActionSequence[m_scoringUnitSeeker.nextIndex]; // シーク位置. OnBeatActionInfo prev_action = song.onBeatActionSequence[m_scoringUnitSeeker.nextIndex - 1]; // シーク位置のひとつ前. float act_timing = m_playerAction.lastActionInfo.triggerBeatTiming; if (crnt_action.triggerBeatTiming - act_timing < act_timing - prev_action.triggerBeatTiming) { // シーク位置(m_scoringUnitSeeker.nextIndex)の方が近かった. nearestIndex = m_scoringUnitSeeker.nextIndex; } else { // シーク位置のひとつ前(m_scoringUnitSeeker.nextIndex)の方が近かった. nearestIndex = m_scoringUnitSeeker.nextIndex - 1; } } return(nearestIndex); }
/// <summary> /// 玩家有一个操作,表现的玩家就做一个动作 /// </summary> /// <param name="actionType"></param> public void DoAction(int _iIndex) { if (!m_musicManager.IsPlaying()) { return; } if (m_scoringManager.temper < ScoringManager.temperThreshold)//-如果兴奋值比较低就一直播放点头的动作 { m_newPlayerAction[_iIndex] = PlayerActionEnum.HeadBanging; } else//-如果比较兴奋了就按照脚本的动作 { int iNearest = m_scoringManager.GetNearestPlayerActionInfoIndex(_iIndex); m_newPlayerAction[_iIndex] = m_musicManager.currentSongInfo.onBeatActionSequence[_iIndex][iNearest].playerActionType; } //获取当前在哪个拍子按下来了 OnBeatActionInfo actionInfo = new OnBeatActionInfo(); actionInfo.triggerBeatTiming = m_musicManager.beatCountFromStart; actionInfo.playerActionType = m_newPlayerAction[_iIndex]; m_lastActionInfo[_iIndex] = actionInfo; #if PLAYER //-播放相应的动画 if (actionType == PlayerActionEnum.HeadBanging) { gameObject.GetComponent <SimpleSpriteAnimation>().BeginAnimation(2, 1, false); } else if (actionType == PlayerActionEnum.Jump) { gameObject.GetComponent <SimpleActionMotor>().Jump(); gameObject.GetComponent <SimpleSpriteAnimation>().BeginAnimation(1, 1, false); } #endif }
/// <summary> /// 找到最近的谱面索引 /// </summary> /// <returns></returns> public int GetNearestPlayerActionInfoIndex(int _iIndex) { SongInfo song = m_musicManager.currentSongInfo; int nearestIndex = 0; List <OnBeatActionInfo> kBeatActionInfos = song.onBeatActionSequence[_iIndex]; SequenceSeeker <OnBeatActionInfo> kSeeker = m_kScoringUnitSeekers.GetSeeker(_iIndex); if (kSeeker.nextIndex == 0)//-如果目的位置是开头的话,没有前一个标记,所以不比较。 { nearestIndex = 0; } else if (kSeeker.nextIndex >= kBeatActionInfos.Count)//-当前索引的位置比序列的尺寸大的时候(过了最后的标记时间的时候)应该不会大于 { Debug.Assert(kSeeker.nextIndex > kBeatActionInfos.Count); nearestIndex = kBeatActionInfos.Count - 1; } else//与前后的定时相比较 { OnBeatActionInfo crnt_action = kBeatActionInfos[kSeeker.nextIndex];//-当前位置 OnBeatActionInfo prev_action = kBeatActionInfos[kSeeker.nextIndex - 1]; //-前一个位置 float act_timing = m_playerAction.GetLastActionInof(_iIndex).triggerBeatTiming; //-玩家在哪个拍子按下的 if (crnt_action.triggerBeatTiming - act_timing < act_timing - prev_action.triggerBeatTiming) //-如果是当前位置比较近 { nearestIndex = kSeeker.nextIndex; } else//-如果是前一个位置比较近 { nearestIndex = kSeeker.nextIndex - 1; } } return(nearestIndex); }
void OnGUI() { //スコア表示 GUI.Box(new Rect(15, 5, 100, 30), ""); GUI.Label(new Rect(20, 10, 90, 20), "Score: " + m_scoringManager.score); //ハイテンションのときの明滅色 if (m_scoringManager.temper > ScoringManager.temperThreshold) { m_blinkColor.g = m_blinkColor.b = 0.7f + 0.3f * Mathf.Abs( Time.frameCount % Application.targetFrameRate - Application.targetFrameRate / 2 ) / (float)Application.targetFrameRate; GUI.color = m_blinkColor; } //盛り上がりゲージ表示 Rect heatBarFrameRect = new Rect(180.0f, 20.0f, 100.0f, 20.0f); Rect heatBarRect = heatBarFrameRect; Rect heatBarLabelRect = heatBarFrameRect; heatBarRect.width *= m_scoringManager.temper; heatBarLabelRect.y = heatBarFrameRect.y - 20; GUI.Label(heatBarLabelRect, "Temper"); GUI.Box(heatBarFrameRect, ""); GUI.DrawTextureWithTexCoords( heatBarRect, temperBar, new Rect(0.0f, 0.0f, 1.0f * m_scoringManager.temper, 1.0f) ); GUI.color = Color.white; //このアイコンとアクションタイミングのアイコンが重なった時に入力 float markerSize = ScoringManager.timingErrorToleranceGood * m_pixelsPerBeats; Graphics.DrawTexture( new Rect(markerOrigin.x - markerSize / 2.0f, markerOrigin.y - markerSize / 2.0f, markerSize, markerSize) , beatPositionIcon ); if (m_musicManager.IsPlaying()) { SongInfo song = m_musicManager.currentSongInfo; // 表示を開始するマーカー. int begin = m_seekerBack.nextIndex; // 表示を終了するマーカー. int end = m_seekerFront.nextIndex; float x_offset; //アクションタイミングを示すアイコンを描画. for (int drawnIndex = begin; drawnIndex < end; drawnIndex++) { OnBeatActionInfo info = song.onBeatActionSequence[drawnIndex]; float size = ScoringManager.timingErrorToleranceGood * m_pixelsPerBeats; //テンションが高いとき、ジャンプアクションのマーカーを大きくする if (m_scoringManager.temper > ScoringManager.temperThreshold && info.playerActionType == PlayerActionEnum.Jump) { size *= 1.5f; } // 表示位置までのX座標のオフセットを求める. x_offset = info.triggerBeatTiming - m_musicManager.beatCount; x_offset *= m_pixelsPerBeats; Rect drawRect = new Rect( markerOrigin.x - size / 2.0f + x_offset, markerOrigin.y - size / 2.0f, size, size ); GUI.DrawTexture(drawRect, headbangingIcon); GUI.color = Color.white; // テキストファイル中の行番号を表示する. if (isDevelopmentMode) { GUI.skin = this.guiSkin; GUI.Label(new Rect(drawRect.x, drawRect.y - 10.0f, 50.0f, 30.0f), info.line_number.ToString()); GUI.skin = null; } } //アクションタイミングのヒットエフェクト if (m_rythmHitEffectCountDown > 0) { float scale = 2.0f - m_rythmHitEffectCountDown / (float)rythmHitEffectShowFrameDuration; if (m_lastInputScore >= ScoringManager.excellentScore) { scale *= 2.0f; } else if (m_lastInputScore > ScoringManager.missScore) { scale *= 1.2f; } else { scale *= 0.5f; } float baseSize = 32.0f; Rect drawRect3 = new Rect( markerOrigin.x - baseSize * scale / 2.0f, markerOrigin.y - baseSize * scale / 2.0f, baseSize * scale, baseSize * scale ); Graphics.DrawTexture(drawRect3, hitEffectIcon); m_rythmHitEffectCountDown--; } //メッセージを表示 if (m_messageShowCountDown > 0) { GUI.color = new Color(1, 1, 1, m_messageShowCountDown / 40.0f); GUI.DrawTexture(new Rect(20, 230, 150, 50), messageTexture, ScaleMode.ScaleAndCrop, true); GUI.color = Color.white; m_messageShowCountDown--; } } }
void OnGUI() { //得分显示 GUI.Box(new Rect(15, 5, 100, 30), ""); GUI.Label(new Rect(20, 10, 90, 20), "Score: " + m_scoringManager.score); //高情绪时的明灭色 if (m_scoringManager.temper > ScoringManager.temperThreshold) { m_blinkColor.g = m_blinkColor.b = 0.7f + 0.3f * Mathf.Abs( Time.frameCount % Application.targetFrameRate - Application.targetFrameRate / 2 ) / (float)Application.targetFrameRate; GUI.color = m_blinkColor; } //盛况显示 Rect heatBarFrameRect = new Rect(180.0f, 20.0f, 100.0f, 20.0f); Rect heatBarRect = heatBarFrameRect; Rect heatBarLabelRect = heatBarFrameRect; heatBarRect.width *= m_scoringManager.temper; heatBarLabelRect.y = heatBarFrameRect.y - 20; GUI.Label(heatBarLabelRect, "Temper"); GUI.Box(heatBarFrameRect, ""); GUI.DrawTextureWithTexCoords( heatBarRect, temperBar, new Rect(0.0f, 0.0f, 1.0f * m_scoringManager.temper, 1.0f) ); GUI.color = Color.white; //此图标和动作定时的图标重叠时输入 float markerSize = ScoringManager.timingErrorToleranceGood * m_pixelsPerBeats; Graphics.DrawTexture( new Rect(markerOrigin.x - markerSize / 2.0f, markerOrigin.y - markerSize / 2.0f, markerSize, markerSize) , beatPositionIcon ); if (m_musicManager.IsPlaying()) { SongInfo song = m_musicManager.currentSongInfo; // 开始显示标记索引 int begin = m_seekerBack.nextIndex; // 终止显示标记索引 int end = m_seekerFront.nextIndex; float x_offset; //显示动作时机的图标。 for (int drawnIndex = begin; drawnIndex < end; drawnIndex++) { OnBeatActionInfo info = song.onBeatActionSequence[drawnIndex]; float size = ScoringManager.timingErrorToleranceGood * m_pixelsPerBeats; //情绪高涨的时候,将跳跃动作的标记放大 if (m_scoringManager.temper > ScoringManager.temperThreshold && info.playerActionType == PlayerActionEnum.Jump) { size *= 1.5f; } // 求到显示位置的X坐标的偏移 x_offset = info.triggerBeatTiming - m_musicManager.beatCount; x_offset *= m_pixelsPerBeats; Rect drawRect = new Rect( markerOrigin.x - size / 2.0f + x_offset, markerOrigin.y - size / 2.0f, size, size ); GUI.DrawTexture(drawRect, headbangingIcon); GUI.color = Color.white; // 显示文本文件中的行号 if (isDevelopmentMode) { GUI.skin = this.guiSkin; GUI.Label(new Rect(drawRect.x, drawRect.y - 10.0f, 50.0f, 30.0f), info.line_number.ToString()); GUI.skin = null; } } //动作时机的成功效果 if (m_rythmHitEffectCountDown > 0) { float scale = 2.0f - m_rythmHitEffectCountDown / (float)rythmHitEffectShowFrameDuration; if (m_lastInputScore >= ScoringManager.excellentScore) { scale *= 2.0f; } else if (m_lastInputScore > ScoringManager.missScore) { scale *= 1.2f; } else { scale *= 0.5f; } float baseSize = 32.0f; Rect drawRect3 = new Rect( markerOrigin.x - baseSize * scale / 2.0f, markerOrigin.y - baseSize * scale / 2.0f, baseSize * scale, baseSize * scale ); Graphics.DrawTexture(drawRect3, hitEffectIcon); m_rythmHitEffectCountDown--; } //显示信息 if (m_messageShowCountDown > 0) { GUI.color = new Color(1, 1, 1, m_messageShowCountDown / 40.0f); GUI.DrawTexture(new Rect(20, 230, 150, 50), messageTexture, ScaleMode.ScaleAndCrop, true); GUI.color = Color.white; m_messageShowCountDown--; } } }
/// <summary> /// 读入谱面信息 /// </summary> /// <param name="reader"></param> /// <param name="line_number"></param> /// <returns></returns> private int ReadCSV_OnBeatAction(System.IO.TextReader reader, int line_number, int _iIndex) { string line; SequenceRegion region = new SequenceRegion(); List <OnBeatActionInfo> sequence = new List <OnBeatActionInfo>(); while ((line = reader.ReadLine()) != null) { line_number++; Debug.Log("line_number :" + _iIndex + " " + line_number); string[] lineCells = line.Split(','); switch (lineCells[0]) { case "regionParameters": region.name = lineCells[1]; //-区域的名字调试用 region.totalBeatCount = float.Parse(lineCells[2]); //-一共多少拍 region.repeatPosition = float.Parse(lineCells[3]); //-部分重复单位(节拍数) break; case "scoringUnitSequenceRegion-End": //-区域结束,应该只有一块 { region.triggerBeatTiming = m_onBeatActionInfoRegionOffset[_iIndex - 1]; songInfo.onBeatActionRegionSequence.Add(region); for (float repeatOffest = 0; repeatOffest < region.totalBeatCount; repeatOffest += region.repeatPosition) { foreach (OnBeatActionInfo onBeatActionInfo in sequence) { if (onBeatActionInfo.triggerBeatTiming + repeatOffest > region.totalBeatCount) { break; } OnBeatActionInfo cloned = onBeatActionInfo.GetClone() as OnBeatActionInfo; cloned.triggerBeatTiming += m_onBeatActionInfoRegionOffset[_iIndex - 1] + repeatOffest; songInfo.onBeatActionSequence[_iIndex - 1].Add(cloned); } } m_onBeatActionInfoRegionOffset[_iIndex - 1] += region.totalBeatCount; } return(line_number); // 因为↑有return,所以这个break不被执行. //break; case "SingleShot": { OnBeatActionInfo onBeatActionInfo = new OnBeatActionInfo(); if (lineCells[2] != "") { onBeatActionInfo.playerActionType = (PlayerActionEnum)System.Enum.Parse(typeof(PlayerActionEnum), lineCells[2]); } else //-默认就是HeadBanging { onBeatActionInfo.playerActionType = PlayerActionEnum.HeadBanging; } Debug.Log("triggerBeatTiming :" + float.Parse(lineCells[1])); onBeatActionInfo.triggerBeatTiming = float.Parse(lineCells[1]); //-记录行号 onBeatActionInfo.line_number = line_number; sequence.Add(onBeatActionInfo); } break; } ; } Debug.LogError("ScoringUnitSequenceRegion.ReadCSV: ParseError - missing ScoringUnitSequenceRegion-End"); return(line_number); }
// Update is called once per frame void Update() { m_additionalScore = 0; float additionalTemper = 0; bool hitBefore = false; bool hitAfter = false; if (m_musicManager.IsPlaying()) { float delta_count = m_musicManager.beatCount - m_musicManager.previousBeatCount; // 执行单元定位 m_scoringUnitSeeker.ProceedTime(delta_count); // 如果玩家发生了操作,则进行成绩判定 if (m_playerAction.currentPlayerAction != PlayerActionEnum.None) { // 取得位于玩家输入的时机之后,或者之前(取更近的)的标记索引位置 int nearestIndex = GetNearestPlayerActionInfoIndex(); SongInfo song = m_musicManager.currentSongInfo; // 标记的位置(marker_act) OnBeatActionInfo marker_act = song.onBeatActionSequence[nearestIndex]; // 玩家的操作输入(player_act). OnBeatActionInfo player_act = m_playerAction.lastActionInfo; // 计算玩家输入和标记的时间差 m_lastResult.timingError = player_act.triggerBeatTiming - marker_act.triggerBeatTiming; m_lastResult.markerIndex = nearestIndex; //比较“距离最近的标记”和“最后输入成功的标记” if (nearestIndex == m_previousHitIndex) { // 对于执行过一次判断的标记,再次输入时 m_additionalScore = 0; } else { // 首次被点击的标记 // 进行时机判断 m_additionalScore = CheckScore(nearestIndex, m_lastResult.timingError, out additionalTemper); } if (m_additionalScore > 0) { // 输入成功 // 为了避免同一个标记被判断两次,保存最后判断的标记 m_previousHitIndex = nearestIndex; // 判断过程中会用到 // ・定位位置的标记(hitAftere) // ・定位位置前一个标记(hitBefore) // if (nearestIndex == m_scoringUnitSeeker.nextIndex) { hitAfter = true; } else { hitBefore = true; } //成功时的演出 OnScoreAdded(nearestIndex); } else { // 输入失败(时机相差太多) //发生了动作不是加分就是减分 m_additionalScore = missScore; additionalTemper = missHeatupRate; } m_score += m_additionalScore; temper += additionalTemper; m_onPlayGUI.RythmHitEffect(m_previousHitIndex, m_additionalScore); // 输入用于调试的日志 DebugWriteLogPrev(); DebugWriteLogPost(hitBefore, hitAfter); } if (m_scoringUnitSeeker.nextIndex > 0) { m_scoreRate = m_score / (m_scoringUnitSeeker.nextIndex * excellentScore); } } }
//Vector3 m_kVerctorTemp = Vector3.zero; /// <summary> /// Drew the specified _iIndex and markerSize. /// </summary> /// <returns>The drew.</returns> /// <param name="_iIndex">I index.</param> /// <param name="markerSize">Marker size.</param> void Drew(int _iIndex, float markerSize) { //-X的位置,每个需要增加m_fMarkWeight,因为是用GUI渲染需要再减去markerSize / 2.0f float x = m_fMarkerOriginX + m_fMarkWeight + m_fMarkWeight * 2 * _iIndex - markerSize / 2.0f; float y = m_fMarkerOriginY - m_fMarkWeight; SongInfo song = m_musicManager.currentSongInfo; //标记开始和结束索引显示。 int begin = m_kSeekersBack.GetSeeker(_iIndex).nextIndex; int end = m_kSeekersFront.GetSeeker(_iIndex).nextIndex; //绘制一个显示动作时间的图标。 for (int drawnIndex = begin; drawnIndex < end; drawnIndex++) { if (HitIndex[_iIndex] == drawnIndex) { continue; } OnBeatActionInfo info = song.onBeatActionSequence[_iIndex][drawnIndex]; //当兴奋值高,并且是跳跃的时候,放大一些 if (m_scoringManager.temper > ScoringManager.temperThreshold && info.playerActionType == PlayerActionEnum.Jump) { markerSize *= 1.2f; } // 求到显示位置的X坐标的偏移,用提前显示的轨道播放的位置减去当前播放拍子的差值 float fYoffset = info.triggerBeatTiming - m_musicManager.beatCountFromStart; //-Debug.Log("fYoffset:" + fYoffset); fYoffset *= m_pixelsPerBeatsY;//-时间乘以速度等于距离 Rect drawRect = new Rect(x , y - fYoffset , markerSize , markerSize); GUI.DrawTexture(drawRect, headbangingIcon); GUI.color = Color.white; // 在文本文件中显示行号。 if (isDevelopmentMode) { GUI.skin = this.guiSkin; GUI.Label(new Rect(drawRect.x , drawRect.y - 10.0f , 50.0f * fScale , 30.0f * fScale), info.line_number.ToString()); GUI.skin = null; } } #if false //-调试用,画出命中的位置 for (int i = 0; i < 4; i++) { OnBeatActionInfo sTestInfo = song.onBeatActionSequence[_iIndex][m_kSeeker.GetSeeker(i).nextIndex]; float fYoffset = sTestInfo.triggerBeatTiming - m_musicManager.beatCountFromStart; fYoffset *= m_pixelsPerBeatsY; Rect drawRect = new Rect(x , m_fMarkerOriginY - markerSize / 2.0f , markerSize , markerSize); GUI.DrawTexture(drawRect, hitEffectIcon); } #endif //-点中爆裂的效果 if (m_rythmHitEffectCountDown[_iIndex] > 0) { float scale = 2.0f - m_rythmHitEffectCountDown[_iIndex] / (float)rythmHitEffectShowFrameDuration;//-依据点击效果的时间确认缩放,一开始1倍,最后是2倍,逐渐变大 //-再依据上一次的得分调整倍率 if (m_lastInputScore >= ScoringManager.excellentScore) { scale *= 2.0f; } else if (m_lastInputScore > ScoringManager.missScore) { scale *= 1.2f; } else { scale *= 0.5f; } float fSize = markerSize * scale; Rect drawRect3 = new Rect( x + markerSize / 2.0f - fSize / 2.0f, y - fSize / 2.0f, fSize, fSize); GUI.DrawTexture(drawRect3, hitEffectIcon); //Vector3 kPos1 = new Vector3(x // , m_fMarkerOriginY, Camera.main.nearClipPlane); //Vector3 kPos2 = Camera.main.ScreenToWorldPoint(kPos1); //Debug.Log("Pos : " + kPos1 + " : " + kPos2); //m_kHitEffects[_iIndex].transform.position = kPos2; //m_kHitEffects[_iIndex].active = true; //m_kHitEffects[_iIndex].GetComponent<SimpleSpriteAnimation>().BeginAnimation(0, 8); m_rythmHitEffectCountDown[_iIndex]--; } //else //{ // m_kHitEffects[_iIndex].active = false; //} //显示Perfect,Good,Bad三种提示 if (m_messageShowCountDown[_iIndex] > 0) { GUI.color = new Color(1, 1, 1, m_messageShowCountDown[_iIndex] / 40.0f); GUI.DrawTexture(new Rect(x , y - m_fMarkWeight - 80 * fScale , 150 * fScale , 80 * fScale) , messageTexture , ScaleMode.ScaleToFit , true); GUI.color = Color.white; m_messageShowCountDown[_iIndex]--; } float fx = x + markerSize / 2.0f; float fy = Screen.height - y + m_fMarkWeight * 2;//- - RhythmGameObject[_iIndex].transform.position = new Vector3(fx, fy, 0.0f); }
private int ReadCSV_OnBeatAction(System.IO.TextReader reader, int line_number) { string line; SequenceRegion region = new SequenceRegion(); List <OnBeatActionInfo> sequence = new List <OnBeatActionInfo>(); while ((line = reader.ReadLine()) != null) { line_number++; string[] lineCells = line.Split(','); switch (lineCells[0]) { case "regionParameters": region.name = lineCells[1]; region.totalBeatCount = float.Parse(lineCells[2]); region.repeatPosition = float.Parse(lineCells[3]); break; case "scoringUnitSequenceRegion-End": { region.triggerBeatTiming = m_onBeatActionInfoRegionOffset; songInfo.onBeatActionRegionSequence.Add(region); for (float repeatOffest = 0; repeatOffest < region.totalBeatCount; repeatOffest += region.repeatPosition) { foreach (OnBeatActionInfo onBeatActionInfo in sequence) { if (onBeatActionInfo.triggerBeatTiming + repeatOffest > region.totalBeatCount) { break; } OnBeatActionInfo cloned = onBeatActionInfo.GetClone() as OnBeatActionInfo; cloned.triggerBeatTiming += m_onBeatActionInfoRegionOffset + repeatOffest; songInfo.onBeatActionSequence.Add(cloned); } } m_onBeatActionInfoRegionOffset += region.totalBeatCount; return(line_number); } // ↑已经有 return 所以这个 break 不会被执行 //break; case "SingleShot": { OnBeatActionInfo onBeatActionInfo = new OnBeatActionInfo(); if (lineCells[2] != "") { onBeatActionInfo.playerActionType = (PlayerActionEnum)System.Enum.Parse(typeof(PlayerActionEnum), lineCells[2]); } else { onBeatActionInfo.playerActionType = PlayerActionEnum.HeadBanging; } onBeatActionInfo.triggerBeatTiming = float.Parse(lineCells[1]); // 记录下定义的行号用于调试 onBeatActionInfo.line_number = line_number; sequence.Add(onBeatActionInfo); } break; } ; } Debug.LogError("ScoringUnitSequenceRegion.ReadCSV: ParseError - missing ScoringUnitSequenceRegion-End"); return(line_number); }
/// <summary> /// Process the specified _iIndex. /// </summary> /// <returns>The process.</returns> /// <param name="_iIndex">I index.</param> void Process(int _iIndex) { float additionalTemper = 0; #if false bool hitBefore = false; bool hitAfter = false; #endif SequenceSeeker <OnBeatActionInfo> kSeeker = m_kScoringUnitSeekers.GetSeeker(_iIndex); int nearestIndex = GetNearestPlayerActionInfoIndex(_iIndex); SongInfo song = m_musicManager.currentSongInfo; if (song.onBeatActionSequence[_iIndex] == null) { Debug.Log("Out of range : " + _iIndex); } if (nearestIndex >= song.onBeatActionSequence[_iIndex].Count) { //-Debug.Log("Out of range : " + nearestIndex + " >= " + song.onBeatActionSequence[_iIndex].Count); return; } OnBeatActionInfo marker_act = song.onBeatActionSequence[_iIndex][nearestIndex]; //-找到最近的谱面 OnBeatActionInfo player_act = m_playerAction.GetLastActionInof(_iIndex); //-找到玩家操作的信息 bool bHit = false; if (marker_act.triggerBeatTiming <= m_musicManager.beatCountFromStart && nearestIndex != m_previousHitIndex && DebugTest == true) { bHit = true; OnBeatActionInfo actionInfo = new OnBeatActionInfo(); actionInfo.triggerBeatTiming = m_musicManager.beatCountFromStart; actionInfo.playerActionType = PlayerActionEnum.Jump; player_act = actionInfo; } if (m_playerAction.GetCurrentPlayerAction(_iIndex) != PlayerActionEnum.None || bHit)//-如果这一拍玩家有操作??? { m_lastResults[_iIndex].timingError = player_act.triggerBeatTiming - marker_act.triggerBeatTiming;//-找到玩家操作的拍子和最近谱面时间的差值 m_lastResults[_iIndex].markerIndex = nearestIndex; if (nearestIndex == m_previousHitIndex)//-如果已经判定过了,则扣分 { m_fAdditionalScore = missScore; additionalTemper = missHeatupRate; } else//-计算得分 { m_fAdditionalScore = CheckScore(nearestIndex , m_lastResults[_iIndex].timingError , out additionalTemper); } if (m_fAdditionalScore > 0)//-得分 { //-记录当前的索引,防止将相同的标记判定为两次 m_previousHitIndex = nearestIndex; #if false if (nearestIndex == kSeeker.nextIndex)//-判断当前按下的是前一个还是后一个 { hitAfter = true; } else { hitBefore = true; } #endif //增加分数的时候播放动画 OnScoreAdded(_iIndex, nearestIndex); } m_fScore += m_fAdditionalScore; temper += additionalTemper; m_onPlayGUI.RythmHitEffect(_iIndex , m_previousHitIndex , m_fAdditionalScore , m_fScore); #if false //-记录日志 DebugWriteLogPrev(); DebugWriteLogPost(hitBefore, hitAfter); #endif } if (kSeeker.nextIndex > 0)//-如果还没结束,计算得分率,用总分数,除以假设全部是最佳的得分 { m_scoreRate = m_fScore / (kSeeker.nextIndex * excellentScore); } }
// Update is called once per frame void Update() { m_additionalScore = 0; float additionalTemper = 0; bool hitBefore = false; bool hitAfter = false; if (m_musicManager.IsPlaying()) { float delta_count = m_musicManager.beatCount - m_musicManager.previousBeatCount; // シークユニットの実行 m_scoringUnitSeeker.ProceedTime(delta_count); // プレイヤーの入力があったら、成否判定をする. if (m_playerAction.currentPlayerAction != PlayerActionEnum.None) { // プレイヤーが入力したタイミングの直後、また直前(近い方)のマーカーの // インデックスを取得する. int nearestIndex = GetNearestPlayerActionInfoIndex(); SongInfo song = m_musicManager.currentSongInfo; // マーカーの位置(marker_act). OnBeatActionInfo marker_act = song.onBeatActionSequence[nearestIndex]; // プレイヤーの入力(player_act). OnBeatActionInfo player_act = m_playerAction.lastActionInfo; // プレイヤーの入力とマーカーとの、タイミングのずれを計算. m_lastResult.timingError = player_act.triggerBeatTiming - marker_act.triggerBeatTiming; m_lastResult.markerIndex = nearestIndex; //「一番近いマーカー」と「最後に入力成功したマーカー」を比較 if (nearestIndex == m_previousHitIndex) { // 一度判定済みのマーカーに対して、再度入力されたとき. m_additionalScore = 0; } else { // 初めてクリックされたマーカー. // タイミングの判定をする. m_additionalScore = CheckScore(nearestIndex, m_lastResult.timingError, out additionalTemper); } if (m_additionalScore > 0) { // 入力成功. // 同じマーカーを二回判定してしまわないよう、最後に判定された // マーカーを覚えておく. m_previousHitIndex = nearestIndex; // 判定に使われたのが // ・シーク位置のマーカー(hitAftere) // ・シーク位置のいっこ前のマーカー(hitBefore) // なのか、判定する. // if (nearestIndex == m_scoringUnitSeeker.nextIndex) { hitAfter = true; } else { hitBefore = true; } //成功時の演出. OnScoreAdded(nearestIndex); } else { // 入力失敗(タイミングが大きくずれていた). //アクションをとったのに加点が無ければ減点. m_additionalScore = missScore; additionalTemper = missHeatupRate; } m_score += m_additionalScore; temper += additionalTemper; m_onPlayGUI.RythmHitEffect(m_previousHitIndex, m_additionalScore); // デバッグ用ログ出力. DebugWriteLogPrev(); DebugWriteLogPost(hitBefore, hitAfter); } if (m_scoringUnitSeeker.nextIndex > 0) { m_scoreRate = m_score / (m_scoringUnitSeeker.nextIndex * excellentScore); } } }