Add note array and view.

This commit is contained in:
2026-01-25 03:26:34 +08:00
parent f16cf0fb96
commit 051ca8bcd8
16 changed files with 196 additions and 91 deletions

View File

@@ -0,0 +1,21 @@
## A NoteView that stores notes that exist on a lane.
class_name LaneView extends NoteView
## The lane notes will be filtered by.
@export var lane: int
## Get the array this LaneView refers to.
func get_data() -> NoteSubset:
return _lane_notes
func update_current_beat(beat: float) -> void:
_current_beat = beat
_update_view_relative_to_notes(_lane_notes)
# ======== Implementation ======== #
var _lane_notes: NoteSubset
func _set_data(p_notes: NoteArray) -> void:
notes = p_notes
_lane_notes = NoteSubset.get_notes_in_lane(p_notes, lane)
_reset_view()

View File

@@ -0,0 +1 @@
uid://cq818ut4pmunn

18
rhythm_game/note/note.gd Normal file
View File

@@ -0,0 +1,18 @@
class_name Note extends Object
enum TYPE {
TAP = 0,
HOLD_START = 1,
HOLD_END = 2
}
var hit_beat: float
var type: TYPE
var lane: int
func _init(p_hit_beat: float = -99.0, p_lane: int = 0, p_type: TYPE = TYPE.TAP) -> void:
hit_beat = p_hit_beat
lane = p_lane
type = p_type

View File

@@ -0,0 +1 @@
uid://cgxrnivh6rjje

View File

@@ -0,0 +1,44 @@
## An array of notes, stored as arrays of data.
## Notes are assumed to be sorted in ascending order by beat.
class_name NoteArray extends Node
## The ID of the note at [param index].
func id_at(index: int) -> int:
return index
## The beat of the note at [param index].
func beat_at(index: int) -> float:
return _beats.get(index)
## The type of the note at [param index].
func type_at(index: int) -> Note.TYPE:
return _types.get(index)
## The lane of the note at [param index].
func lane_at(index: int) -> int:
return _lanes.get(index)
## The number of notes in the array.
func size() -> int:
return _beats.size()
## Remove all notes in the array.
func clear() -> void:
_beats = []
_types = []
_lanes = []
# ======= IMPLEMENTATION ======= #
var _beats: Array[float] = []
var _types: Array[Note.TYPE] = []
var _lanes: Array[int] = []
func _append_note(note: Note) -> void:
_beats.append(note.hit_beat)
_types.append(note.type)
_lanes.append(note.lane)
func _append_note_data(beat: float, type: Note.TYPE, lane: int) -> void:
_beats.append(beat)
_types.append(type)
_lanes.append(lane)

View File

@@ -0,0 +1 @@
uid://8isyo4pxyj1r

View File

@@ -0,0 +1,25 @@
## Contain a subset of notes in a [NoteArray].
## Notes are expected to be sorted in ascending order by beat.
## The original index of a note can be found with [method id_at].
class_name NoteSubset extends NoteArray
## The array where notes in this subset come from.
var full_set: NoteArray
## The ID (index of note in full_set) of the note at [param index].
func id_at(index) -> int:
return _ids.get(index)
## Parse the given [param notes] and return a [class NoteSubset]
## containing only notes in [param lane].
static func get_notes_in_lane(notes: NoteArray, lane: int) -> NoteSubset:
var lane_notes: NoteSubset = NoteSubset.new()
lane_notes.full_set = notes
for i in range(notes.size( )):
if notes.lane_at(i) == lane:
lane_notes._ids.append(i)
lane_notes.append_note_data(notes.beat_at(i), notes.type_at(i), lane)
return lane_notes
## ====== IMPLEMENTATION ====== #
var _ids: Array[int] = []

View File

@@ -0,0 +1 @@
uid://dhaxabkmyajjv

View File

@@ -0,0 +1,19 @@
## Gets a range of notes in a NoteData relative to a current beat.
class_name NoteView extends View
## The full set of notes.
@export var notes: NoteArray = null: set = _set_notes
## Get the array this NoteView refers to.
func get_data() -> NoteArray:
return notes
func update_current_beat(beat: float) -> void:
_current_beat = beat
_update_view_relative_to_notes(notes)
# ======= IMPLEMENTATION ======= #
func _set_notes(p_notes: NoteArray) -> void:
notes = p_notes
_reset_view()

View File

@@ -0,0 +1 @@
uid://c7h7ue6kjgoha

68
rhythm_game/note/view.gd Normal file
View File

@@ -0,0 +1,68 @@
## Abstract class representing a range of notes in some kind of array,
## expressed by a beginning index and an ending index: [begin, end).
@abstract class_name View extends Node
## Get the array this View refers to.
@abstract func get_data() -> Variant
## Update the view to be relative to beat.
## Can be connected to a beat update signal.
@abstract func update_current_beat(beat: float) -> void
## Beginning of the range relative to te current beat where notes will be visible.
## Any notes where (hit_beat < current_beat + offset_begin) will NOT be visible.
@export var offset_begin: float = -4.0
## End of the range relative to the current beat where notes will be visible.
## Any notes where (hit_beat > current_beat + offset_end) will NOT be visible.
@export var offset_end: float = 4.0
## Return the index to the first element.
func begin() -> int:
return _begin
## Return the index after the last element (equal to last index + 1).
func end() -> int:
return _end
## Size of the range encompassed by begin() and end().
func size() -> int:
return int(_begin >= 0) * _end - _begin
# ======= IMPLEMENETATION ======= #
var _begin: int = -1
var _end: int = -1
var _current_beat: float = -999
var _previous_beat: float = -999
func _reset_view() -> void:
_begin = -1
_end = -1
_current_beat = -999
_previous_beat = -999
## Update the view to match _current_beat.
func _update_view_relative_to_notes(notes: NoteArray) -> void:
var new_begin = _begin
var new_end = _end
if _current_beat > _previous_beat:
# Update forward.
while(new_begin < notes.size()) and (notes.beat_at(new_begin) < _current_beat + offset_begin):
new_begin += 1
while(new_end < notes.size()) and (notes.beat_at(new_end) <= _current_beat + offset_end):
new_end += 1
elif _current_beat < _previous_beat:
# Update backward.
while(new_begin >= 0) and (notes.beat_at(new_begin) >= _current_beat + offset_begin):
_begin -= 1
while(new_end >= 0) and (notes.beat_at(new_end) > _current_beat + offset_end):
new_end -= 1
if(new_begin != _begin):
new_begin += 1
if(new_end != _end):
new_end += 1
_begin = new_begin
_end = new_end
_previous_beat = _current_beat

View File

@@ -0,0 +1 @@
uid://drrwatuw1yur