This commit is contained in:
SoulliesOfficial
2025-07-26 04:20:25 -04:00
parent bae0bfbc20
commit abf81ece7b
196 changed files with 3909 additions and 964 deletions

View File

@@ -29,6 +29,16 @@ namespace Ichni.RhythmGame
{
return new FullScreenNearTimeJudgeUnit_BM();
}
public override bool CheckJudgeAvailability(InputUnit inputUnit)
{
if (inputUnit is InputUnitSwipe swipe && note is Flick flick)
{
return flick.CheckSwipeDirection(swipe);
}
return true;
}
}
namespace Beatmap

View File

@@ -7,10 +7,14 @@ namespace Ichni.RhythmGame
public class TouchAreaJudgeUnit : NoteJudgeUnit
{
public float areaRadius;
protected override GameObject GetHintImagePrefab() => GameManager.instance.basePrefabs.areaHint;
protected override GameObject GetHintImagePrefab()
{
return GameManager.instance.basePrefabs.areaHint;
}
private float CurrentScreenRatio() => Screen.width / 1920f;
public TouchAreaJudgeUnit(NoteBase note, float areaRadius) : base(note)
{
this.areaRadius = areaRadius;
@@ -18,7 +22,7 @@ namespace Ichni.RhythmGame
public override void UpdateJudge()
{
if(note.isFirstJudged) return;
if (note.isFirstJudged) return;
Vector2 noteScreenPosition = note.noteScreenPosition;
RectTransform canvasRect = GameManager.instance.judgeHintCanvas.GetComponent<RectTransform>();
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRect, noteScreenPosition, null, out Vector2 uiPosition))
@@ -37,21 +41,26 @@ namespace Ichni.RhythmGame
{
Vector2 inputScreenPosition = inputUnit.inputPosition;
Vector2 noteScreenPosition = note.noteScreenPosition;
float distance = Vector2.Distance(inputScreenPosition, noteScreenPosition);
//Debug.Log("Input Position: " + inputScreenPosition + ", Note Position: " + noteScreenPosition + ", Distance: " + distance);
if (distance <= areaRadius * CurrentScreenRatio())
if (distance <= areaRadius)
{
if (inputUnit is InputUnitSwipe swipe && note is Flick flick)
{
return flick.CheckSwipeDirection(swipe.swipeDirection);
return flick.CheckSwipeDirection(swipe);
}
Debug.Log("Input Position: " + inputScreenPosition +
", Note Position: " + noteScreenPosition +
", Distance: " + distance +
", Area Radius: " + areaRadius +
", Current Screen Ratio: " + CurrentScreenRatio());
return true;
}
return false;
}
}
@@ -74,7 +83,11 @@ namespace Ichni.RhythmGame
public override NoteJudgeUnit ConvertToGameType(NoteBase attachedNote)
{
return new TouchAreaJudgeUnit(attachedNote, areaRadius);
#if UNITY_EDITOR || UNITY_STANDALONE
return new FullScreenNearTimeJudgeUnit(attachedNote);
#elif UNITY_ANDROID || UNITY_IOS
return new TouchAreaJudgeUnit(attachedNote, areaRadius);//TODO:改这里
#endif
}
}
}

View File

@@ -13,6 +13,8 @@ namespace Ichni.RhythmGame
{
public partial class Flick : NoteBase
{
public NoteJudgeType preJudgeType;
public List<Vector2> availableFlickDirections;
public float flickBuffer = 0.5f;
@@ -66,22 +68,64 @@ namespace Ichni.RhythmGame
}
base.Update();
ExecuteFinalJudge(songTime);
}
protected override void RemoveFromCheckingList()
{
GameManager.instance.inputManager.checkingFlickList.Remove(this);
if (GameManager.instance.inputManager.checkingFlickList.Contains(this))
{
GameManager.instance.inputManager.checkingFlickList.Remove(this);
}
}
public override void ExecuteStartJudge()
{
base.ExecuteStartJudge();
isFinalJudged = true;
float triggerTime = GameManager.instance.songTime;
float timeDifference = triggerTime - exactJudgeTime;
if (GameManager.instance.inputManager.checkingFlickList.Contains(this))
NoteJudgeType startJudgeType = GetStartJudgeType(timeDifference);
if (startJudgeType != NoteJudgeType.Perfect)
{
GameManager.instance.inputManager.checkingFlickList.Remove(this);
return;
}
preJudgeType = startJudgeType;
isFirstJudged = true;
RemoveFromCheckingList();
}
public void ExecuteFinalJudge(float triggerTime)
{
if (isFirstJudged && !isFinalJudged && preJudgeType != NoteJudgeType.NotJudged &&
GameManager.instance.songTime >= exactJudgeTime)
{
if (preJudgeType == NoteJudgeType.Perfect)
{
Perfect(triggerTime);
}
else if (preJudgeType == NoteJudgeType.Good)
{
Good(triggerTime);
}
else if (preJudgeType == NoteJudgeType.Bad)
{
Bad(triggerTime);
}
else if (preJudgeType == NoteJudgeType.Miss)
{
Miss(triggerTime);
}
if (preJudgeType != NoteJudgeType.Miss)
{
noteAudioSubmodule.PlayGeneralJudgeAudios();
}
isFinalJudged = true;
}
}
}
@@ -93,8 +137,14 @@ namespace Ichni.RhythmGame
return noteJudgeSubmodule.judgeUnitList.All(judgeUnit => judgeUnit.CheckJudgeAvailability(inputUnitSwipe));
}
public bool CheckSwipeDirection(Vector2 screenSwipeDirection)
public bool CheckSwipeDirection(InputUnitSwipe inputUnitSwipe)
{
if (inputUnitSwipe.isGeneric)
{
Debug.Log($"输入方向 {inputUnitSwipe.swipeDirection} 是通用的,直接匹配成功。");
return true;
}
Camera gameCamera = GameManager.instance.cameraManager.gameCamera.gameCamera;
foreach (Vector2 localDir in availableFlickDirections)
@@ -113,18 +163,18 @@ namespace Ichni.RhythmGame
continue;
}
float dotProduct = Vector2.Dot(screenSwipeDirection, noteScreenDirection);
float dotProduct = Vector2.Dot(inputUnitSwipe.swipeDirection, noteScreenDirection);
// 4. 检查点积是否满足阈值
if (dotProduct >= flickBuffer)
{
// 匹配成功!无需再检查其他方向。
Debug.Log($"匹配成功! 输入方向 {screenSwipeDirection} 匹配了本地方向 {localDir} (屏幕投影: {noteScreenDirection}), 点积: {dotProduct}");
Debug.Log($"匹配成功! 输入方向 {inputUnitSwipe.swipeDirection} 匹配了本地方向 {localDir} (屏幕投影: {noteScreenDirection}), 点积: {dotProduct}");
return true;
}
}
Debug.Log($"匹配失败. 输入方向 {screenSwipeDirection} 未匹配任何允许的方向。");
Debug.Log($"匹配失败. 输入方向 {inputUnitSwipe.swipeDirection} 未匹配任何允许的方向。");
return false;
}
}

View File

@@ -184,6 +184,33 @@ namespace Ichni.RhythmGame
{
return isFirstJudged && noteJudgeSubmodule.judgeUnitList.All(judgeUnit => judgeUnit.CheckJudgeAvailability(inputUnitTouch));
}
protected override void SetJudgeArea()
{
if (noteJudgeSubmodule != null)
{
if (GameManager.instance.songTime > exactJudgeTime - 0.1f && !isFirstJudged)
{
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => !unit.isShowingJudge))
{
unit.SetShowingJudge(true);
}
}
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
unit.UpdateJudge();
}
if (GameManager.instance.songTime >= holdEndTime - Time.deltaTime)
{
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
unit.SetShowingJudge(false);
}
}
}
}
}
public partial class Hold
@@ -225,6 +252,8 @@ namespace Ichni.RhythmGame
noteScreenPosition = GameManager.instance.cameraManager.gameCamera.gameCamera.WorldToScreenPoint(noteVisual.transform.position);
}
SetJudgeArea();
foreach (EffectBase e in noteVisual.effectSubmodule.effectCollection["Generate"])
{
e.UpdateEffect(exactJudgeTime);

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using Dreamteck.Splines;
using Sirenix.OdinInspector;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.Serialization;
@@ -39,6 +40,8 @@ namespace Ichni.RhythmGame
public bool isFinalJudged;
public override int HierarchyPriority => -10;
[Title("Debug")] public TMP_Text judgeRankHint;
/// <summary>
/// 在MovableTrack上更新Note的位置注意HoldNote需要重写这个方法
/// </summary>
@@ -86,6 +89,8 @@ namespace Ichni.RhythmGame
gameObject.SetActive(false);
GameManager.instance.noteManager.RegisterNote(this, exactJudgeTime - beyondTime - 0.5f);
}
//judgeRankHint = Instantiate(GameManager.instance.basePrefabs.judgeRankHint, noteVisual.transform).GetComponent<TMP_Text>();
}
protected virtual void Update()
@@ -108,6 +113,10 @@ namespace Ichni.RhythmGame
noteScreenPosition = GameManager.instance.cameraManager.gameCamera.gameCamera.WorldToScreenPoint(noteVisual.transform.position);
}
SetJudgeArea();
//SetJudgeRankText();
foreach (EffectBase e in noteVisual.effectSubmodule.effectCollection["Generate"])
{
e.UpdateEffect(exactJudgeTime);
@@ -191,6 +200,12 @@ namespace Ichni.RhythmGame
}).AddTo(gameObject);
if (isOnTrack) track.childElementList.Remove(this);
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
unit.SetShowingJudge(false);
}
Destroy(gameObject, 1.2f); //注意所有特效时间不得超过1.2秒
}
@@ -207,6 +222,12 @@ namespace Ichni.RhythmGame
}).AddTo(gameObject);
if (isOnTrack) track.childElementList.Remove(this);
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
unit.SetShowingJudge(false);
}
Destroy(gameObject, 1.2f);
}
public virtual void Bad(float triggerTime){
@@ -222,6 +243,12 @@ namespace Ichni.RhythmGame
}).AddTo(gameObject);
if (isOnTrack) track.childElementList.Remove(this);
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
unit.SetShowingJudge(false);
}
Destroy(gameObject, 1.2f);
}}
@@ -237,17 +264,23 @@ namespace Ichni.RhythmGame
}).AddTo(gameObject);
if (isOnTrack) track.childElementList.Remove(this);
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
unit.SetShowingJudge(false);
}
Destroy(gameObject, 1.2f);
}
}
public abstract partial class NoteBase
{
protected void SetJudgeArea()
protected virtual void SetJudgeArea()
{
if (noteJudgeSubmodule != null)
{
if (GameManager.instance.songTime > exactJudgeTime - 0.25f && !isFirstJudged)
if (GameManager.instance.songTime > exactJudgeTime - 0.1f && !isFirstJudged)
{
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => !unit.isShowingJudge))
{
@@ -260,7 +293,7 @@ namespace Ichni.RhythmGame
unit.UpdateJudge();
}
if (GameManager.instance.songTime > exactJudgeTime + 0.25f)
if (GameManager.instance.songTime > exactJudgeTime + 0.1f)
{
foreach (NoteJudgeUnit unit in noteJudgeSubmodule.judgeUnitList.Where(unit => unit.isShowingJudge))
{
@@ -274,6 +307,34 @@ namespace Ichni.RhythmGame
{
return exactJudgeTime.CompareTo(other.exactJudgeTime);
}
private void SetJudgeRankText()
{
float triggerTime = GameManager.instance.songTime;
float timeDifference = triggerTime - exactJudgeTime;
NoteJudgeType startJudgeType = GetStartJudgeType(timeDifference);
if (startJudgeType == NoteJudgeType.Perfect)
{
judgeRankHint.text = "PERFECT";
judgeRankHint.color = Color.cyan;
}
else if (startJudgeType == NoteJudgeType.Good)
{
judgeRankHint.text = "GOOD";
judgeRankHint.color = Color.green;
}
else if (startJudgeType == NoteJudgeType.Bad)
{
judgeRankHint.text = "BAD";
judgeRankHint.color = Color.magenta;
}
else if (startJudgeType == NoteJudgeType.Miss)
{
judgeRankHint.text = "MISS";
judgeRankHint.color = Color.white;
}
}
}
public abstract partial class NoteBase

View File

@@ -73,11 +73,6 @@ namespace Ichni.RhythmGame
{
GameManager.instance.inputManager.checkingStayList.Remove(this);
}
protected override NoteJudgeType GetStartJudgeType(float timeDifference)
{
return judgeIntervals.GetNoteJudgeType(timeDifference);
}
public override void ExecuteStartJudge()
{
@@ -85,6 +80,12 @@ namespace Ichni.RhythmGame
float timeDifference = triggerTime - exactJudgeTime;
NoteJudgeType startJudgeType = GetStartJudgeType(timeDifference);
if (startJudgeType != NoteJudgeType.Perfect)
{
return;
}
preJudgeType = startJudgeType;
isFirstJudged = true;

View File

@@ -5,6 +5,7 @@ using System.Linq;
using Dreamteck.Splines;
using Ichni.RhythmGame.Beatmap;
using Lean.Pool;
using TMPro;
using UniRx;
using Unity.VisualScripting;
using UnityEngine;
@@ -24,7 +25,7 @@ namespace Ichni.RhythmGame
new TimeInterval(-0.15f, -0.15f), new TimeInterval(-0.15f, -0.125f),
new TimeInterval(-0.125f, -0.1f), new TimeInterval(-0.1f, 0.1f),
new TimeInterval(0.1f, 0.125f), new TimeInterval(0.125f, 0.15f), 0.15f);
if (parentElement.TryGetComponent(out Track track))
{
if (track.trackTimeSubmodule != null)