Properly clone notes from charts so that songs can be played more than once per session
This commit is contained in:
parent
c76b49fe8d
commit
f29d50b6dd
|
@ -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 )
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue