using System.Collections; using System.Collections.Generic; using System.Linq; using Ichni.RhythmGame; using Sirenix.OdinInspector; using UnityEngine; namespace Ichni { public partial class NoteJudgeManager : SerializedMonoBehaviour { public List checkingTapList; public List checkingStayList; public List checkingHoldList; public List checkingFlickList; public List inputUnitTapList; public List inputUnitTouchList; public List inputUnitSwipeList; private List _availableTapsBuffer = new List(30); private List _availableHoldsBuffer = new List(10); private List _availableFlicksBuffer = new List(10); private List _availableStaysBuffer = new List(30); private List _minTapsBuffer = new List(5); private List _minHoldsBuffer = new List(5); private List _minFlicksBuffer = new List(5); private InputUnitSwipe _cachedAssumedSwipe = new InputUnitSwipe(0, Vector2.zero, true, true, Vector2.zero); private void Start() { checkingTapList = new List(); checkingStayList = new List(); checkingHoldList = new List(); checkingFlickList = new List(); inputUnitTapList = new List(); inputUnitTouchList = new List(); inputUnitSwipeList = new List(); } public void Update() { if (!GameManager.Instance.songPlayer.isPlaying) { return; } float songTime = CoreServices.TimeProvider.SongTime; foreach (var swipe in inputUnitSwipeList) { _availableFlicksBuffer.Clear(); foreach (Flick flick in checkingFlickList) { if (flick.CheckJudgeAvailability(swipe)) { _availableFlicksBuffer.Add(flick); } } if (_availableFlicksBuffer.Count > 0) { if (swipe.isFirst) // 原 tapSwipeList 逻辑 { GetAllMinNotes(_availableFlicksBuffer, _minFlicksBuffer); // 提醒:内部也需防 new List if (_minFlicksBuffer.Count == 1) _minFlicksBuffer[0].ExecuteStartJudge(songTime); else if (_minFlicksBuffer.Count > 1) GetNearestNote(_minFlicksBuffer, swipe.inputPosition).ExecuteTapJudge(songTime); } else // 原 holdSwipeList 逻辑 { _availableFlicksBuffer.Sort(); _availableFlicksBuffer[0].ExecuteStartJudge(songTime); } } } /*foreach (InputUnitSwipe tapSwipe in tapSwipeList) { List availableFlicks = new List(); foreach (Flick flick in checkingFlickList) { if (flick.CheckJudgeAvailability(tapSwipe)) { availableFlicks.Add(flick); } } List minFlicks = GetAllMinNotes(availableFlicks); if (minFlicks.Count == 1) { minFlicks[0].ExecuteStartJudge(); } else if (minFlicks.Count > 1) { GetNearestNote(minFlicks, tapSwipe.inputPosition).ExecuteTapJudge(); } } foreach (InputUnitSwipe inputUnitSwipe in holdSwipeList) { List availableFlicks = new List(); foreach (Flick flick in checkingFlickList) { if (flick.CheckJudgeAvailability(inputUnitSwipe)) { availableFlicks.Add(flick); } } if (availableFlicks.Count > 0) { availableFlicks.Sort(); Flick closestFlick = availableFlicks[0]; closestFlick.ExecuteStartJudge(); } }*/ foreach (InputUnitTap inputUnitTap in inputUnitTapList) { _availableTapsBuffer.Clear(); _availableHoldsBuffer.Clear(); foreach (Tap tap in checkingTapList) { if (tap.CheckJudgeAvailability(inputUnitTap)) _availableTapsBuffer.Add(tap); } foreach (Hold hold in checkingHoldList) { if (hold.CheckJudgeAvailability(inputUnitTap)) _availableHoldsBuffer.Add(hold); } bool haveTap = _availableTapsBuffer.Count > 0; bool haveHold = _availableHoldsBuffer.Count > 0; Flick closestFlick = null; InputUnitSwipe assumedSwipe = new InputUnitSwipe(inputUnitTap.fingerId, inputUnitTap.inputPosition, true, true, Vector2.zero); foreach (Flick flick in checkingFlickList) { if (flick.CheckJudgeAvailability(assumedSwipe)) { if (closestFlick == null || flick.exactJudgeTime < closestFlick.exactJudgeTime) { closestFlick = flick; } } } if (haveHold && haveTap) { GetAllMinNotes(_availableHoldsBuffer, _minHoldsBuffer); GetAllMinNotes(_availableTapsBuffer, _minTapsBuffer); Hold closestHold = _minHoldsBuffer[0]; Tap closestTap = _minTapsBuffer[0]; bool holdBlockedByFlick = false; bool tapBlockedByFlick = false; if (closestFlick != null) { if (closestFlick.exactJudgeTime < closestHold.exactJudgeTime) { holdBlockedByFlick = true; } if (closestFlick.exactJudgeTime < closestTap.exactJudgeTime) { tapBlockedByFlick = true; } } if (!holdBlockedByFlick && closestHold.exactJudgeTime < closestTap.exactJudgeTime) { if (_minHoldsBuffer.Count == 1) { _minHoldsBuffer[0].ExecuteStartJudge(songTime); } else { GetNearestNote(_minHoldsBuffer, inputUnitTap.inputPosition).ExecuteStartJudge(songTime); } } else if (!tapBlockedByFlick) { if (_minTapsBuffer.Count == 1) { _minTapsBuffer[0].ExecuteStartJudge(songTime); } else { GetNearestNote(_minTapsBuffer, inputUnitTap.inputPosition).ExecuteStartJudge(songTime); } } } else if (haveHold) { GetAllMinNotes(_availableHoldsBuffer, _minHoldsBuffer); bool holdBlockedByFlick = closestFlick != null && closestFlick.exactJudgeTime < _minHoldsBuffer[0].exactJudgeTime; if (!holdBlockedByFlick) { if (_minHoldsBuffer.Count == 1) { _minHoldsBuffer[0].ExecuteStartJudge(songTime); } else { GetNearestNote(_minHoldsBuffer, inputUnitTap.inputPosition).ExecuteStartJudge(songTime); } } } else if (haveTap) { GetAllMinNotes(_availableTapsBuffer, _minTapsBuffer); bool tapBlockedByFlick = closestFlick != null && closestFlick.exactJudgeTime < _minTapsBuffer[0].exactJudgeTime; if (!tapBlockedByFlick) { if (_minTapsBuffer.Count == 1) { _minTapsBuffer[0].ExecuteStartJudge(songTime); } else { GetNearestNote(_minTapsBuffer, inputUnitTap.inputPosition).ExecuteStartJudge(songTime); } } } } foreach (InputUnitTouch inputUnitTouch in inputUnitTouchList) { _availableStaysBuffer.Clear(); foreach (Stay stay in checkingStayList) { if (stay.CheckJudgeAvailability(inputUnitTouch)) { _availableStaysBuffer.Add(stay); } } _availableHoldsBuffer.Clear(); foreach (Hold hold in checkingHoldList) { if (hold.CheckJudgeAvailability(inputUnitTouch)) { _availableHoldsBuffer.Add(hold); } } foreach (Stay stay in _availableStaysBuffer) { stay.ExecuteStartJudge(songTime); } foreach (Hold hold in _availableHoldsBuffer) { hold.ExecuteProcessJudge(); } } inputUnitTapList.Clear(); inputUnitTouchList.Clear(); inputUnitSwipeList.Clear(); } public void SetNewInputUnitTap(int fingerId, Vector2 inputPosition) { InputUnitTap inputUnitTap = new InputUnitTap(fingerId, inputPosition); if(!inputUnitTapList.Exists(x => x.fingerId == fingerId)) { inputUnitTapList.Add(inputUnitTap); } } public void SetNewInputUnitTouch(int fingerId, Vector2 inputPosition) { InputUnitTouch inputUnitTouch = new InputUnitTouch(fingerId, inputPosition); if(!inputUnitTouchList.Exists(x => x.fingerId == fingerId)) { inputUnitTouchList.Add(inputUnitTouch); } } public void SetNewInputUnitSwipe(int fingerId, Vector2 inputPosition, bool isGeneric, bool isFirst, Vector2 delta) { InputUnitSwipe inputUnitSwipe = new InputUnitSwipe(fingerId, inputPosition, isGeneric, isFirst, delta); if(!inputUnitSwipeList.Exists(x => x.fingerId == fingerId)) { inputUnitSwipeList.Add(inputUnitSwipe); } } } public partial class NoteJudgeManager { private void GetAllMinNotes(List availableFlicks, List destination) where T : NoteBase { destination.Clear(); float minTime = float.MaxValue; foreach (T note in availableFlicks) { if (note.exactJudgeTime < minTime) { minTime = note.exactJudgeTime; destination.Clear(); destination.Add(note); } else if (Mathf.Approximately(note.exactJudgeTime, minTime)) { destination.Add(note); } } } private T GetNearestNote(List notes, Vector2 inputPosition) where T : NoteBase { float minDistance = float.MaxValue; T closestNote = null; foreach (T note in notes) { float distance = Vector2.Distance(inputPosition, note.noteScreenPosition); if (distance < minDistance) { minDistance = distance; closestNote = note; } } return closestNote; } } public class InputUnit { public int fingerId; public Vector2 inputPosition; } public class InputUnitTap : InputUnit { public InputUnitTap(int fingerId, Vector2 inputPosition) { this.fingerId = fingerId; this.inputPosition = inputPosition; } } public class InputUnitTouch : InputUnit { public InputUnitTouch(int fingerId, Vector2 inputPosition) { this.fingerId = fingerId; this.inputPosition = inputPosition; } } public class InputUnitSwipe : InputUnit { public Vector2 swipeDirection; public bool isGeneric; public bool isFirst; public InputUnitSwipe(int fingerId, Vector2 inputPosition, bool isGeneric, bool isFirst, Vector2 swipeDirection) { this.fingerId = fingerId; this.inputPosition = inputPosition; this.isGeneric = isGeneric; this.isFirst = isFirst; this.swipeDirection = swipeDirection.normalized; } } }