-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNoteArrow.cs
More file actions
139 lines (114 loc) · 3.72 KB
/
NoteArrow.cs
File metadata and controls
139 lines (114 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
using System;
namespace FunkEngine;
using Godot;
public partial class NoteArrow : Sprite2D
{ //TextRect caused issues later :)
public static readonly string LoadPath = "res://Scenes/NoteManager/NoteArrow.tscn";
protected const float LeftBound = -200f;
protected static readonly Beat BeatBound = new Beat(8);
[Export]
public Sprite2D OutlineSprite;
[Export]
public Sprite2D IconSprite;
public ArrowData Data;
public Beat Beat => Data.Beat;
public ArrowType Type => Data.Type;
private double _beatTime;
public bool IsHit;
private bool _isQueued;
public override void _Ready()
{
ZIndex = 2;
}
public virtual void Init(CheckerData parentChecker, ArrowData arrowData, double beatTime)
{
Data = arrowData;
_beatTime = beatTime;
Position = new Vector2(GetNewPosX(), parentChecker.Node.GlobalPosition.Y);
RotationDegrees = parentChecker.Node.RotationDegrees;
IconSprite.Texture = arrowData.NoteRef.Texture;
IconSprite.Rotation = -Rotation;
OutlineSprite.Modulate = parentChecker.Color;
}
public void NoteHit()
{
if (IsHit)
return;
Modulate *= .7f;
IsHit = true;
}
public delegate void HittableEventHandler(NoteArrow note);
public event HittableEventHandler QueueForHit;
private void CheckHittable()
{
if (_isQueued || !(Beat - TimeKeeper.LastBeat <= Beat.One))
return;
_isQueued = true;
QueueForHit?.Invoke(this);
}
public delegate void MissedEventHandler(NoteArrow note);
public event MissedEventHandler Missed;
protected void RaiseMissed(NoteArrow note) => Missed?.Invoke(note);
protected virtual void CheckMissed()
{
if (IsHit || !(TimeKeeper.LastBeat - Beat > Beat.One))
return;
RaiseMissed(this);
}
public delegate void KillEventHandler(NoteArrow note);
public event KillEventHandler QueueForPool;
protected void RaiseKill(NoteArrow note) => QueueForPool?.Invoke(note);
public virtual void Recycle()
{
Visible = true;
ProcessMode = ProcessModeEnum.Inherit;
if (IsHit)
Modulate = Colors.White;
IsHit = false;
_isQueued = false;
}
private void BeatChecks()
{
CheckMissed();
CheckHittable();
}
protected virtual void PosChecks()
{
if (Position.X < LeftBound || TimeKeeper.LastBeat - Data.Beat > BeatBound)
{
if (!IsHit)
RaiseMissed(this);
RaiseKill(this);
}
}
public override void _Process(double delta)
{
BeatChecks(); //beat checks first, why? Because
Vector2 newPos = Position;
newPos.X = GetNewPosX();
if (!float.IsNaN(newPos.X))
Position = newPos;
PosChecks();
}
private float GetNewPosX()
{
double relativePosition =
(TimeKeeper.CurrentTime - _beatTime)
/ (TimeKeeper.SongLength)
* (TimeKeeper.ChartWidth * TimeKeeper.LoopsPerSong);
//If this should be placed for the next song replay, offset
double posOffset =
(
(Beat.Loop / TimeKeeper.LoopsPerSong)
> TimeKeeper.LastBeat.Loop / TimeKeeper.LoopsPerSong
)
? TimeKeeper.ChartWidth * TimeKeeper.LoopsPerSong
: 0;
return (float)(-relativePosition + posOffset);
}
//Is the passed in beat within range of this arrow's beat, for checking if player can place near this note
public virtual bool IsInRange(Beat incomingBeat)
{
return (int)Math.Round(Beat.BeatPos) == (int)Math.Round(incomingBeat.BeatPos);
}
}