mirror of
https://github.com/2394425147/astrodx.git
synced 2025-12-14 08:06:19 +08:00
327 lines
10 KiB
C#
327 lines
10 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using AstroDX.Contexts.Gameplay.Behaviours.Slide.SlideMarkers;
|
|
using AstroDX.Contexts.Gameplay.Interactions;
|
|
using AstroDX.Contexts.Gameplay.PlayerScope;
|
|
using AstroDX.Contexts.Gameplay.SlideGenerators;
|
|
using AstroDX.Globals;
|
|
using Medicine;
|
|
using SimaiSharp.Structures;
|
|
using UnityEngine;
|
|
|
|
namespace AstroDX.Contexts.Gameplay.Behaviours.Slide.Handlers
|
|
{
|
|
public class FanSlideSegmentHandler : SlideSegmentHandler
|
|
{
|
|
private const int Margin = 2;
|
|
private const int ArrowCount = 11;
|
|
|
|
private readonly List<FanSlideArrow> _arrows = new();
|
|
private readonly Vector2[] _endPositions;
|
|
|
|
private readonly List<List<TouchInteractable>> _interactableGroups = new();
|
|
|
|
private readonly Vector2 _startPosition;
|
|
private readonly Vector2[] _ups;
|
|
|
|
private int _interactionReceivedState;
|
|
|
|
private SlideStarBehaviour[] _stars;
|
|
|
|
public FanSlideSegmentHandler(SlideBehaviour slideBehaviour,
|
|
SlideSegment segment,
|
|
Location startLocation) :
|
|
base(slideBehaviour)
|
|
{
|
|
var vertices = segment.vertices.ToList();
|
|
vertices.Insert(0, startLocation);
|
|
|
|
_startPosition = SlideGenerator.GetPosition(vertices[0]);
|
|
|
|
var ccwEndLocation = startLocation;
|
|
ccwEndLocation.index += 3;
|
|
|
|
var centerEndLocation = startLocation;
|
|
centerEndLocation.index += 4;
|
|
|
|
var cwEndLocation = startLocation;
|
|
cwEndLocation.index += 5;
|
|
|
|
_endPositions = new[]
|
|
{
|
|
SlideGenerator.GetPosition(ccwEndLocation),
|
|
SlideGenerator.GetPosition(centerEndLocation),
|
|
SlideGenerator.GetPosition(cwEndLocation)
|
|
};
|
|
|
|
_ups = new[]
|
|
{
|
|
_endPositions[0] - _startPosition,
|
|
_endPositions[1] - _startPosition,
|
|
_endPositions[2] - _startPosition
|
|
};
|
|
|
|
_stars = new[]
|
|
{
|
|
SlideManager.slideStars.Get(),
|
|
SlideManager.slideStars.Get(),
|
|
SlideManager.slideStars.Get()
|
|
};
|
|
|
|
foreach (var star in _stars) star.Initialize(ParentPath, ParentNote.parentCollection);
|
|
|
|
GenerateSensors();
|
|
GenerateArrows();
|
|
}
|
|
|
|
[Inject.Single]
|
|
private SlideManager SlideManager { get; }
|
|
|
|
[Inject.Single]
|
|
private TouchManager TouchManager { get; }
|
|
|
|
public override float GetLength()
|
|
{
|
|
return RenderManager.PlayFieldRadius * 2;
|
|
}
|
|
|
|
public override void OnUpdate(float segmentT)
|
|
{
|
|
if (IsJudgementTarget)
|
|
CheckInteraction();
|
|
|
|
UpdateSlideStarPosition(segmentT);
|
|
UpdateArrowOpacity();
|
|
}
|
|
|
|
private void UpdateArrowOpacity()
|
|
{
|
|
var timeSinceNoteStart = TimeSinceSlideStart + ParentPath.delay;
|
|
|
|
var alpha = 0.8f;
|
|
if (timeSinceNoteStart < 0)
|
|
{
|
|
var colorPoint = Mathf.InverseLerp(-Persistent.Settings.Gameplay.slideFadeInDuration,
|
|
0,
|
|
(float)timeSinceNoteStart);
|
|
|
|
alpha = Mathf.Lerp(0, 0.8f, colorPoint);
|
|
}
|
|
|
|
foreach (var arrow in _arrows.Select(a => a.spriteRenderer))
|
|
{
|
|
var color = arrow.color;
|
|
color.a = alpha;
|
|
|
|
arrow.color = color;
|
|
}
|
|
}
|
|
|
|
private void CheckInteraction()
|
|
{
|
|
if (_interactionReceivedState == 0)
|
|
{
|
|
if (!_interactableGroups[0][0].GetSlideJudgement())
|
|
return;
|
|
|
|
_interactionReceivedState = 1;
|
|
foreach (var slideArrow in _arrows
|
|
.Where(a => a.interactionGroupIndex == 0)
|
|
.ToList())
|
|
{
|
|
_arrows.Remove(slideArrow);
|
|
slideArrow.ExitSequence();
|
|
}
|
|
}
|
|
|
|
if (_interactionReceivedState >= 3)
|
|
{
|
|
Cleared = true;
|
|
return;
|
|
}
|
|
|
|
for (var groupIndex = _interactionReceivedState; groupIndex < 3; groupIndex++)
|
|
{
|
|
foreach (var interactable in
|
|
_interactableGroups[groupIndex]
|
|
.Where(interactable => interactable.GetSlideJudgement())
|
|
.ToList())
|
|
_interactableGroups[groupIndex].Remove(interactable);
|
|
|
|
if (_interactableGroups[groupIndex].Count > 0 ||
|
|
_interactionReceivedState < groupIndex)
|
|
continue;
|
|
|
|
foreach (var slideArrow in _arrows
|
|
.Where(a => a.interactionGroupIndex == _interactionReceivedState)
|
|
.ToList())
|
|
{
|
|
_arrows.Remove(slideArrow);
|
|
slideArrow.ExitSequence();
|
|
}
|
|
|
|
_interactionReceivedState++;
|
|
}
|
|
}
|
|
|
|
public override float GetRemainingLength()
|
|
{
|
|
return (3 - _interactionReceivedState) / 3f * GetLength();
|
|
}
|
|
|
|
public override void OnDestroy()
|
|
{
|
|
base.OnDestroy();
|
|
|
|
foreach (var slideArrow in _arrows)
|
|
SlideManager.fanSlideArrows.Release(slideArrow);
|
|
|
|
foreach (var star in _stars)
|
|
SlideManager.slideStars.Release(star);
|
|
}
|
|
|
|
private void UpdateSlideStarPosition(float segmentT)
|
|
{
|
|
if (disposed || _stars is null)
|
|
return;
|
|
|
|
for (var index = 0; index < _stars.Length; index++)
|
|
{
|
|
var star = _stars[index];
|
|
|
|
if (star == null)
|
|
continue;
|
|
|
|
var transform = star.transform;
|
|
|
|
if (segmentT >= 1 && indexInSlide != ParentPath.segments.Count - 1)
|
|
{
|
|
transform.localScale = Vector3.one * Persistent.Settings.Gameplay.noteScale;
|
|
star.Appearance.Color = new Color(1, 1, 1, 0);
|
|
|
|
continue;
|
|
}
|
|
|
|
var position = Vector3.Lerp(_startPosition,
|
|
_endPositions[index],
|
|
segmentT);
|
|
|
|
transform.localPosition = position;
|
|
transform.up = _ups[index];
|
|
|
|
if (TimeSinceSlideStart < 0 &&
|
|
indexInSlide == 0 &&
|
|
ParentNote.slideMorph != SlideMorph.SuddenIn)
|
|
{
|
|
var interpolation =
|
|
Mathf.InverseLerp(-ParentPath.delay, 0,
|
|
(float)TimeSinceSlideStart);
|
|
transform.localScale = new Vector3(interpolation, interpolation) *
|
|
Persistent.Settings.Gameplay.noteScale;
|
|
star.Appearance.Color = new Color(1, 1, 1, interpolation);
|
|
|
|
return;
|
|
}
|
|
|
|
if (segmentT < 0)
|
|
return;
|
|
|
|
transform.localScale = Vector3.one * Persistent.Settings.Gameplay.noteScale;
|
|
star.Appearance.Color = Color.white;
|
|
}
|
|
}
|
|
|
|
public override void GetJudgementVector(out Vector2 position, out float rotation)
|
|
{
|
|
position = _endPositions[1];
|
|
rotation = Mathf.Atan2(_ups[1].y, _ups[1].x);
|
|
}
|
|
|
|
private void GenerateSensors()
|
|
{
|
|
_interactableGroups.AddRange(new List<TouchInteractable>[]
|
|
{
|
|
new()
|
|
{
|
|
TouchManager.GetCollider(new Location
|
|
{
|
|
group = NoteGroup.ASensor,
|
|
index = ParentNote.location.index
|
|
})
|
|
},
|
|
new()
|
|
{
|
|
TouchManager.GetCollider(new Location
|
|
{
|
|
group = NoteGroup.BSensor,
|
|
index = (ParentNote.location.index + 2) %
|
|
8
|
|
}),
|
|
TouchManager.GetCollider(new Location
|
|
{
|
|
group = NoteGroup.BSensor,
|
|
index = (ParentNote.location.index + 6) %
|
|
8
|
|
})
|
|
},
|
|
new()
|
|
{
|
|
TouchManager.GetCollider(new Location
|
|
{
|
|
group = NoteGroup.ASensor,
|
|
index = (ParentNote.location.index + 5) %
|
|
8
|
|
}),
|
|
TouchManager.GetCollider(new Location
|
|
{
|
|
group = NoteGroup.ASensor,
|
|
index = (ParentNote.location.index + 3) %
|
|
8
|
|
}),
|
|
TouchManager.GetCollider(new Location
|
|
{
|
|
group = NoteGroup.ASensor,
|
|
index = (ParentNote.location.index + 4) %
|
|
8
|
|
})
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
private void GenerateArrows()
|
|
{
|
|
var halfMargin = Mathf.RoundToInt(Margin / 2f);
|
|
for (var i = 0;
|
|
i < ArrowCount;
|
|
i++)
|
|
{
|
|
var position = Vector3.Lerp(_startPosition,
|
|
_endPositions[1],
|
|
(float)(i + halfMargin) / (ArrowCount + Margin));
|
|
|
|
var arrow = SlideManager.fanSlideArrows.Get();
|
|
arrow.Initialize(position,
|
|
_ups[1],
|
|
ArrowCount,
|
|
i,
|
|
isBreak,
|
|
isEach);
|
|
|
|
AssignArrows(arrow, i);
|
|
}
|
|
}
|
|
|
|
private void AssignArrows(FanSlideArrow arrow, int index)
|
|
{
|
|
_arrows.Add(arrow);
|
|
|
|
if (index < ArrowCount / 3f)
|
|
arrow.interactionGroupIndex = 0;
|
|
else if (index < ArrowCount * 2 / 3f)
|
|
arrow.interactionGroupIndex = 1;
|
|
else
|
|
arrow.interactionGroupIndex = 2;
|
|
}
|
|
}
|
|
} |