Add scenes, static scene-finding mechanism, and scene pool for visual hold/tap notes.

This commit is contained in:
2026-01-30 00:35:01 +08:00
parent 81c8374058
commit dfac4bbfa5
15 changed files with 195 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
class_name HoldNote extends NoteVisual
var start_id: int
var end_id: int

View File

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

View File

@@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://dq5ocf0272tet"]
[node name="HoldNote" type="Node2D" unique_id=495232990]

View File

@@ -0,0 +1,27 @@
class_name NoteAnimator extends NoteView
@export var pool: NotePool
## TODO WARNING: This is currently only implemented for beat updates
## going forward in time.
func update_current_beat(beat: float) -> void:
var old_begin: int = _begin
var old_end: int = _end
super.update_current_beat(beat) # Update _begin and _end.
_update_note_visuals(old_begin, _begin)
_update_note_visuals(old_end, _end)
# ======== IMPLEMENTATION ======== #
var _note_map: Dictionary[int, NoteVisual]
func _update_note_visuals(index_begin: int, index_end: int) -> void:
for i: int in range(index_begin, index_end):
# TODO: Either get or return node from pool,
# depending on if index_begin > or < than index_end.
pass
func _set_notes(p_notes: NoteArray) -> void:
notes = p_notes
_reset_view()

View File

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

View File

@@ -0,0 +1,84 @@
class_name NotePool extends Node
@export_group("Start")
## Tap notes to spawn on [method _ready].
@export var tap_size: int = 30
## Hold notes to spawn on [method _ready].
@export var hold_size: int = 10
@export_group("Skin")
## [StringName] of the tap note skin to use.
@export var tap_skin: StringName = "default"
## [StringName] of the hold note skin to use.
@export var hold_skin: StringName = "default"
func get_note(type: NoteVisual.TYPE) -> NoteVisual:
var note: NoteVisual
# TODO: Implement.
return note
## Get a tap note. Instantiates one if no free nodes are available.
func get_tap() -> TapNote:
var tap: TapNote = _free_taps.pop_back()
if tap == null:
tap = _instantiate_tap()
_used_taps[tap] = true
return tap
## Return a tap note.
func return_tap(tap: TapNote) -> void:
var parent: Node = tap.get_parent()
if parent:
parent.remove_child(tap)
if not _used_taps.erase(tap):
push_warning(
"Returning tap note ", tap,
" that was not spawned by pool ", self, "."
)
_free_taps.append(tap)
## Get a hold note. Instantiates one if no free nodes are available.
func get_hold() -> HoldNote:
var hold: HoldNote = _free_holds.pop_back()
if hold == null:
hold = _instantiate_hold()
_used_holds[hold] = true
return hold
## Return a hold note.
func return_hold(hold: HoldNote) -> void:
var parent: Node = hold.get_parent()
if parent:
parent.remove_child(hold)
if not _used_holds.erase(hold):
push_warning(
"Returning hold note ", hold,
" that was not spawned by pool ", self, "."
)
_free_holds.append(hold)
## Spawn the given number of notes.
func reserve(taps: int, holds: int) -> void:
for i: int in range(taps):
_free_taps.append(_instantiate_tap())
for i: int in range(holds):
_free_holds.append(_instantiate_hold())
# ========= IMPLEMENTATION ========= #
var _free_taps: Array[TapNote]
var _used_taps: Dictionary[TapNote, bool]
var _free_holds: Array[HoldNote]
var _used_holds: Dictionary[HoldNote, bool]
func _instantiate_tap() -> TapNote:
return NoteScenes.get_tap(tap_skin).instantiate() as TapNote
func _instantiate_hold() -> HoldNote:
return NoteScenes.get_tap(tap_skin).instantiate() as HoldNote

View File

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

View File

@@ -0,0 +1,26 @@
## Static class that stores references to note scenes.
class_name NoteScenes extends Object
static func get_tap(skin: StringName = "default") -> PackedScene:
if _tap_scenes.has(skin):
return _tap_scenes[skin]
else:
push_warning("Tap note skin [", skin, "] does not exist.")
return _tap_scenes["default"]
static func get_hold(skin: StringName = "default") -> PackedScene:
if _hold_scenes.has(skin):
return _hold_scenes[skin]
else:
push_warning("Hold note skin [", skin, "] does not exist.")
return _hold_scenes["default"]
# ======== IMPLEMENTATION ======== #
static var _tap_scenes: Dictionary[StringName, PackedScene] = {
"default": load("uid://dq5ocf0272tet")
}
static var _hold_scenes: Dictionary[StringName, PackedScene] = {
"default": load("uid://jbgxbhfpj806")
}

View File

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

View File

@@ -0,0 +1,10 @@
@abstract class_name NoteVisual extends Node2D
enum TYPE {
TAP = 0,
HOLD = 1
}
@abstract func reset() -> void
@abstract func in_use() -> bool

View File

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

View File

@@ -0,0 +1,9 @@
class_name TapNote extends NoteVisual
var id: int = -1
func reset() -> void:
id = -1
func in_use() -> bool:
return id >= 0

View File

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

View File

@@ -0,0 +1,21 @@
[gd_scene format=3 uid="uid://jbgxbhfpj806"]
[ext_resource type="Script" uid="uid://1qve2pqu1yr4" path="res://rhythm_game/note/visual/tap/tap_note.gd" id="1_kuk3o"]
[node name="TapNote" type="Node2D" unique_id=1341974559]
script = ExtResource("1_kuk3o")
metadata/_custom_type_script = "uid://1qve2pqu1yr4"
[node name="ColorRect" type="ColorRect" parent="." unique_id=743279305]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -29.0
offset_top = -6.0
offset_right = 29.0
offset_bottom = 6.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.928887, 0.8138475, 0, 1)

View File

@@ -9,6 +9,7 @@
[ext_resource type="Script" uid="uid://bbpyym0kgujev" path="res://rhythm_game/metronome.gd" id="7_nsyv8"]
[ext_resource type="Script" uid="uid://8isyo4pxyj1r" path="res://rhythm_game/note/array/note_array.gd" id="9_10cpq"]
[ext_resource type="Script" uid="uid://c7h7ue6kjgoha" path="res://rhythm_game/note/view/note_view.gd" id="9_74aio"]
[ext_resource type="Script" uid="uid://clog51kfg2rsb" path="res://rhythm_game/note/visual/note_pool.gd" id="10_74aio"]
[sub_resource type="Resource" id="Resource_10cpq"]
script = ExtResource("5_nsyv8")
@@ -40,4 +41,8 @@ script = ExtResource("9_74aio")
notes = NodePath("../AllChartNotes")
metadata/_custom_type_script = "uid://c7h7ue6kjgoha"
[node name="NotePool" type="Node" parent="." unique_id=621311008]
script = ExtResource("10_74aio")
metadata/_custom_type_script = "uid://clog51kfg2rsb"
[connection signal="ticked" from="Conductor" to="Metronome" method="on_conductor_ticked"]