Properly clone notes from charts so that songs can be played more than once per session

This commit is contained in:
Luke Hubmayer-Werner 2020-05-03 20:36:43 +09:30
parent c76b49fe8d
commit f29d50b6dd
6 changed files with 104 additions and 22 deletions

63
RadialNoteHandler.tscn Normal file
View File

@ -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 )

View File

@ -127,7 +127,6 @@ func _input(event):
# write how many fingers are tapping the screen # write how many fingers are tapping the screen
func set_fingers(value): func set_fingers(value):
fingers = max(value, 0) fingers = max(value, 0)
# set_text("Fingers: %d" % fingers)
func set_button_state(index: int, state: bool): func set_button_state(index: int, state: bool):
var new_state = int(state) var new_state = int(state)

View File

@ -267,7 +267,7 @@ func _draw_score_screen(center: Vector2) -> Array:
total_score += note_score * notetype_weights[i] total_score += note_score * notetype_weights[i]
total_scoremax += note_count * 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 var score_idx = 0
for cutoff in Rules.SCORE_CUTOFFS: for cutoff in Rules.SCORE_CUTOFFS:
if overall_score >= cutoff: if overall_score >= cutoff:
@ -313,6 +313,7 @@ func _draw_gameplay(center: Vector2) -> Array:
func _draw(): func _draw():
var songs = len(Library.all_songs) var songs = len(Library.all_songs)
var score_screen_filter_alpha := 0.65
var size = 216 var size = 216
var outline_px = 3 var outline_px = 3
var center = Vector2(540.0, 540.0-160.0) # Vector2(0.0, -160.0) var center = Vector2(540.0, 540.0-160.0) # Vector2(0.0, -160.0)
@ -333,7 +334,7 @@ func _draw():
MenuMode.OPTIONS: MenuMode.OPTIONS:
pass pass
MenuMode.GAMEPLAY: MenuMode.GAMEPLAY:
GameTheme.set_screen_filter_alpha(progress) GameTheme.set_screen_filter_alpha(lerp(0.0, score_screen_filter_alpha, progress))
MenuMode.SCORE_SCREEN: MenuMode.SCORE_SCREEN:
_draw_score_screen(center_prev) _draw_score_screen(center_prev)
match menu_mode: match menu_mode:
@ -362,7 +363,7 @@ func _draw():
GameTheme.set_screen_filter_alpha(0.0) GameTheme.set_screen_filter_alpha(0.0)
touch_rects[menu_mode] = _draw_gameplay(center) touch_rects[menu_mode] = _draw_gameplay(center)
MenuMode.SCORE_SCREEN: 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) touch_rects[menu_mode] = _draw_score_screen(center)
ScoreText.show() ScoreText.show()

View File

@ -13,7 +13,7 @@ const RELEASE_SCORE_TYPES := {
NOTE_ROLL: -NOTE_ROLL NOTE_ROLL: -NOTE_ROLL
} }
class NoteBase: class NoteBase extends Resource:
var time_hit: float setget set_time_hit var time_hit: float setget set_time_hit
var time_death: float var time_death: float
var column: int 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 fposmod(GameTheme.RADIAL_COL_ANGLES[column] - GameTheme.RADIAL_COL_ANGLES[column_release], TAU)
return 0.0 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: 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) return NoteSlide.new(time_hit, column, duration, column_release, slide_type)

View File

@ -296,10 +296,6 @@ func activate_note(note, judgement):
match note.type: match note.type:
Note.NOTE_HOLD: Note.NOTE_HOLD:
note.is_held = true 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): func activate_note_release(note, judgement):
# Only for Hold, Slide # Only for Hold, Slide
@ -398,17 +394,21 @@ func _draw():
for note in active_notes: for note in active_notes:
var position : float = (t+GameTheme.note_forecast_beats-note.time_hit)/GameTheme.note_forecast_beats var position : float = (t+GameTheme.note_forecast_beats-note.time_hit)/GameTheme.note_forecast_beats
var scale := 1.0 var scale := 1.0
noteline_data.set_pixel(
i%16, i/16, Color( if note.hittable:
position/arr_div.x, noteline_data.set_pixel(
note.column/arr_div.y, i%16, i/16, Color(
GameTheme.RADIAL_COL_ANGLES[note.column]/arr_div.z 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: if position < GameTheme.INNER_NOTE_CIRCLE_RATIO:
scale *= position/GameTheme.INNER_NOTE_CIRCLE_RATIO scale *= position/GameTheme.INNER_NOTE_CIRCLE_RATIO
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 note_center = (GameTheme.RADIAL_UNIT_VECTORS[note.column] * position * GameTheme.receptor_ring_radius)
var color: PoolColorArray var color: PoolColorArray
match note.type: match note.type:
@ -491,7 +491,7 @@ func _input(event):
for i in range(len(active_slide_trails)-1, -1, -1): for i in range(len(active_slide_trails)-1, -1, -1):
var note = active_slide_trails[i] var note = active_slide_trails[i]
var center = note.get_position(note.progress) 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 note.progress += 0.09
if note.progress >= 1.0: if note.progress >= 1.0:
do_slide_release(note) do_slide_release(note)
@ -569,9 +569,10 @@ func load_track(song_key: String, difficulty_idx: int):
self.song_key = song_key self.song_key = song_key
set_time(-3.0) set_time(-3.0)
active_notes = [] active_notes = []
all_notes = []
next_note_to_load = 0 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] var data = Library.all_songs[song_key]
bpm = data.BPM bpm = data.BPM
sync_offset_audio = data.audio_offsets[0] 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]) VideoPlayer.update_aspect_ratio(data.video_dimensions[0]/data.video_dimensions[1])
# all_notes = FileLoader.Test.stress_pattern() # all_notes = FileLoader.Test.stress_pattern()
Note.process_note_list(all_notes) Note.process_note_list(all_notes, false)
for note in all_notes: for note in all_notes:
if note.type == Note.NOTE_SLIDE: if note.type == Note.NOTE_SLIDE:
slide_trail_meshes[note.slide_id] = make_slide_trail_mesh(note) 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]) SlideTrailHandler.remove_child(slide_trail_mesh_instances[note.slide_id])
slide_trail_mesh_instances.erase(note.slide_id) slide_trail_mesh_instances.erase(note.slide_id)
var idx = active_slide_trails.find(note) var idx = active_slide_trails.find(note)
if idx >= 0: if idx > -1:
active_slide_trails.remove(idx) active_slide_trails.remove(idx)
make_judgement_column('MISS', note.column_release) make_judgement_column('MISS', note.column_release)
scores[Note.NOTE_SLIDE]['MISS'] += 1 scores[Note.NOTE_SLIDE]['MISS'] += 1

View File

@ -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_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_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_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 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_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 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