From f29d50b6dd09f6d08e175559c3f33a2a681fdbed Mon Sep 17 00:00:00 2001 From: Luke Hubmayer-Werner Date: Sun, 3 May 2020 20:36:43 +0930 Subject: [PATCH] Properly clone notes from charts so that songs can be played more than once per session --- RadialNoteHandler.tscn | 63 +++++++++++++++++++++++++++++++++++++++++ scripts/InputHandler.gd | 1 - scripts/Menu.gd | 7 +++-- scripts/Note.gd | 18 +++++++++++- scripts/NoteHandler.gd | 33 ++++++++++----------- scripts/Rules.gd | 4 ++- 6 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 RadialNoteHandler.tscn diff --git a/RadialNoteHandler.tscn b/RadialNoteHandler.tscn new file mode 100644 index 0000000..3137d0f --- /dev/null +++ b/RadialNoteHandler.tscn @@ -0,0 +1,63 @@ +[gd_scene load_steps=10 format=2] + +[ext_resource path="res://shaders/notelines.shader" type="Shader" id=1] +[ext_resource path="res://shaders/notemesh.shader" type="Shader" id=2] +[ext_resource path="res://scripts/NoteHandler.gd" type="Script" id=3] +[ext_resource path="res://assets/text-4k.png" type="Texture" id=4] +[ext_resource path="res://scripts/NotePainter.gd" type="Script" id=5] +[ext_resource path="res://scripts/NoteViewport.gd" type="Script" id=6] + +[sub_resource type="ShaderMaterial" id=3] +shader = ExtResource( 2 ) +shader_param/bps = null +shader_param/star_color = null +shader_param/held_color = null +shader_param/screen_size = null + +[sub_resource type="ShaderMaterial" id=4] +shader = ExtResource( 1 ) +shader_param/line_color = Color( 0.8, 0.8, 1, 0.8 ) +shader_param/line_color_double = Color( 1, 1, 0.6, 0.9 ) +shader_param/dot_color = Color( 1, 1, 1, 0.8 ) +shader_param/bps = 1.0 +shader_param/line_thickness = 0.012 +shader_param/line_thickness_min = 0.0 +shader_param/dot_thickness = 0.033 +shader_param/dot_fullbright_thickness = 0.013 +shader_param/max_angle = 1.0708 +shader_param/max_dist = 1.25 +shader_param/array_postmul = Vector3( 1, 1, 1 ) +shader_param/array_sidelen = 16 +shader_param/array_size = 256 + +[sub_resource type="CanvasItemMaterial" id=5] +blend_mode = 4 + +[node name="NoteHandler" type="Node2D"] +script = ExtResource( 3 ) + +[node name="Viewport" type="Viewport" parent="."] +size = Vector2( 540, 540 ) +transparent_bg = true +usage = 1 +render_target_v_flip = true +script = ExtResource( 6 ) + +[node name="Center" type="Node2D" parent="Viewport"] +position = Vector2( 270, 270 ) +scale = Vector2( 0.5, 0.5 ) + +[node name="SlideTrailHandler" type="Node2D" parent="Viewport/Center"] + +[node name="JudgeText" type="MeshInstance2D" parent="Viewport/Center"] +texture = ExtResource( 4 ) + +[node name="meshinstance" type="MeshInstance2D" parent="Viewport/Center"] +material = SubResource( 3 ) + +[node name="notelines" type="MeshInstance2D" parent="Viewport/Center"] +material = SubResource( 4 ) + +[node name="Painter" type="Node2D" parent="."] +material = SubResource( 5 ) +script = ExtResource( 5 ) diff --git a/scripts/InputHandler.gd b/scripts/InputHandler.gd index 6f4ee06..2a2a6ea 100644 --- a/scripts/InputHandler.gd +++ b/scripts/InputHandler.gd @@ -127,7 +127,6 @@ func _input(event): # write how many fingers are tapping the screen func set_fingers(value): fingers = max(value, 0) -# set_text("Fingers: %d" % fingers) func set_button_state(index: int, state: bool): var new_state = int(state) diff --git a/scripts/Menu.gd b/scripts/Menu.gd index def01ad..eb2b0c9 100644 --- a/scripts/Menu.gd +++ b/scripts/Menu.gd @@ -267,7 +267,7 @@ func _draw_score_screen(center: Vector2) -> Array: total_score += note_score * notetype_weights[i] total_scoremax += note_count * notetype_weights[i] - var overall_score = total_score/total_scoremax + var overall_score = total_score/max(total_scoremax, 1.0) var score_idx = 0 for cutoff in Rules.SCORE_CUTOFFS: if overall_score >= cutoff: @@ -313,6 +313,7 @@ func _draw_gameplay(center: Vector2) -> Array: func _draw(): var songs = len(Library.all_songs) + var score_screen_filter_alpha := 0.65 var size = 216 var outline_px = 3 var center = Vector2(540.0, 540.0-160.0) # Vector2(0.0, -160.0) @@ -333,7 +334,7 @@ func _draw(): MenuMode.OPTIONS: pass MenuMode.GAMEPLAY: - GameTheme.set_screen_filter_alpha(progress) + GameTheme.set_screen_filter_alpha(lerp(0.0, score_screen_filter_alpha, progress)) MenuMode.SCORE_SCREEN: _draw_score_screen(center_prev) match menu_mode: @@ -362,7 +363,7 @@ func _draw(): GameTheme.set_screen_filter_alpha(0.0) touch_rects[menu_mode] = _draw_gameplay(center) MenuMode.SCORE_SCREEN: - GameTheme.set_screen_filter_alpha(1.0) + GameTheme.set_screen_filter_alpha(score_screen_filter_alpha) touch_rects[menu_mode] = _draw_score_screen(center) ScoreText.show() diff --git a/scripts/Note.gd b/scripts/Note.gd index 44aa42c..fac6ad2 100644 --- a/scripts/Note.gd +++ b/scripts/Note.gd @@ -13,7 +13,7 @@ const RELEASE_SCORE_TYPES := { NOTE_ROLL: -NOTE_ROLL } -class NoteBase: +class NoteBase extends Resource: var time_hit: float setget set_time_hit var time_death: float var column: int @@ -172,6 +172,22 @@ class NoteSlide extends NoteBase: # Fancy charts have naked slides which necess return fposmod(GameTheme.RADIAL_COL_ANGLES[column] - GameTheme.RADIAL_COL_ANGLES[column_release], TAU) return 0.0 +static func copy_note(note: NoteBase): + # Honestly disappointed I couldn't find a better, more OOP solution for this. + var newnote: NoteBase + match note.type: + NOTE_TAP: + newnote = NoteTap.new(note.time_hit, note.column, note.is_break) + NOTE_STAR: + newnote = NoteStar.new(note.time_hit, note.column, note.is_break) + NOTE_HOLD: + newnote = NoteHold.new(note.time_hit, note.column, note.duration) + NOTE_SLIDE: + newnote = NoteSlide.new(note.time_hit, note.column, note.duration, note.column_release, note.slide_type) + NOTE_ROLL: + newnote = NoteRoll.new(note.time_hit, note.column, note.duration) + newnote.double_hit = note.double_hit + return newnote static func make_slide(time_hit: float, duration: float, column: int, column_release: int, slide_type:=SlideType.CHORD) -> NoteSlide: return NoteSlide.new(time_hit, column, duration, column_release, slide_type) diff --git a/scripts/NoteHandler.gd b/scripts/NoteHandler.gd index 2c79f0e..13fe821 100644 --- a/scripts/NoteHandler.gd +++ b/scripts/NoteHandler.gd @@ -296,10 +296,6 @@ func activate_note(note, judgement): match note.type: Note.NOTE_HOLD: note.is_held = true - Note.NOTE_SLIDE: - # Set up slide trail? - active_slide_trails.append(note) - note.progress = 0.0 func activate_note_release(note, judgement): # Only for Hold, Slide @@ -398,17 +394,21 @@ func _draw(): for note in active_notes: var position : float = (t+GameTheme.note_forecast_beats-note.time_hit)/GameTheme.note_forecast_beats var scale := 1.0 - noteline_data.set_pixel( - i%16, i/16, Color( - position/arr_div.x, - note.column/arr_div.y, - GameTheme.RADIAL_COL_ANGLES[note.column]/arr_div.z + + if note.hittable: + noteline_data.set_pixel( + i%16, i/16, Color( + position/arr_div.x, + note.column/arr_div.y, + GameTheme.RADIAL_COL_ANGLES[note.column]/arr_div.z + ) ) - ) - i += 1 + i += 1 + if position < GameTheme.INNER_NOTE_CIRCLE_RATIO: scale *= position/GameTheme.INNER_NOTE_CIRCLE_RATIO position = GameTheme.INNER_NOTE_CIRCLE_RATIO + var note_center = (GameTheme.RADIAL_UNIT_VECTORS[note.column] * position * GameTheme.receptor_ring_radius) var color: PoolColorArray match note.type: @@ -491,7 +491,7 @@ func _input(event): for i in range(len(active_slide_trails)-1, -1, -1): var note = active_slide_trails[i] var center = note.get_position(note.progress) - if (pos - center).length_squared() < 10000.0: + if (pos - center).length_squared() < Rules.SLIDE_RADIUS2: note.progress += 0.09 if note.progress >= 1.0: do_slide_release(note) @@ -569,9 +569,10 @@ func load_track(song_key: String, difficulty_idx: int): self.song_key = song_key set_time(-3.0) active_notes = [] - all_notes = [] next_note_to_load = 0 - all_notes = Library.get_song_charts(song_key).values()[difficulty_idx] + all_notes = [] + for note in Library.get_song_charts(song_key).values()[difficulty_idx]: + all_notes.append(Note.copy_note(note)) var data = Library.all_songs[song_key] bpm = data.BPM sync_offset_audio = data.audio_offsets[0] @@ -582,7 +583,7 @@ func load_track(song_key: String, difficulty_idx: int): VideoPlayer.update_aspect_ratio(data.video_dimensions[0]/data.video_dimensions[1]) # all_notes = FileLoader.Test.stress_pattern() - Note.process_note_list(all_notes) + Note.process_note_list(all_notes, false) for note in all_notes: if note.type == Note.NOTE_SLIDE: slide_trail_meshes[note.slide_id] = make_slide_trail_mesh(note) @@ -670,7 +671,7 @@ func _process(delta): SlideTrailHandler.remove_child(slide_trail_mesh_instances[note.slide_id]) slide_trail_mesh_instances.erase(note.slide_id) var idx = active_slide_trails.find(note) - if idx >= 0: + if idx > -1: active_slide_trails.remove(idx) make_judgement_column('MISS', note.column_release) scores[Note.NOTE_SLIDE]['MISS'] += 1 diff --git a/scripts/Rules.gd b/scripts/Rules.gd index 9a626c8..48c4173 100644 --- a/scripts/Rules.gd +++ b/scripts/Rules.gd @@ -13,8 +13,10 @@ const JUDGEMENT_TIMES_PRE := [0.040, 0.090, 0.125, 0.150] const JUDGEMENT_TIMES_POST := [0.040, 0.090, 0.125, 0.150] const JUDGEMENT_TIMES_RELEASE_PRE := [0.040, 0.090, 0.125, 0.150] const JUDGEMENT_TIMES_RELEASE_POST := [0.090, 0.140, 0.175, 0.200] # Small grace period -const JUDGEMENT_TIMES_SLIDE_PRE := [0.090, 0.240, 0.375, 60.000] # Small grace period, sort-of. Just be generous, really. +const JUDGEMENT_TIMES_SLIDE_PRE := [0.090, 0.240, 0.4, 60.000] # Small grace period, sort-of. Just be generous, really. const JUDGEMENT_TIMES_SLIDE_POST := [0.090, 0.140, 0.175, 0.200] const SCORE_STRINGS = ["SSS", "SS", "S", "A⁺", "A", "B⁺", "B", "C⁺", "C", "F"] const SCORE_CUTOFFS = [1.0, 0.975, 0.95, 0.9, 0.85, 0.8, 0.7, 0.6, 0.5] + +const SLIDE_RADIUS2 = 10000.0 # Radius of 100px