[WIP] Scores can be saved. Screen filter blocks out video on scorescreen.

This commit is contained in:
Luke Hubmayer-Werner 2019-12-10 23:57:33 +10:30
parent 1a9a5c5eac
commit 92b83416a3
6 changed files with 144 additions and 18 deletions

View File

@ -64,13 +64,22 @@ var COLOR_ARRAY_DOUBLE_MISS_8 := PoolColorArray([
COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS
]) ])
var screen_filter := Color(0.0, 0.0, 0.0, 0.2) var screen_filter_min_alpha := 0.2
var screen_filter := Color(0.0, 0.0, 0.0, screen_filter_min_alpha)
signal screen_filter_changed()
var receptor_color := Color.blue var receptor_color := Color.blue
var bezel_color := Color.black var bezel_color := Color.black
var RADIAL_COL_ANGLES := PoolRealArray() # ideally const var RADIAL_COL_ANGLES := PoolRealArray() # ideally const
var RADIAL_UNIT_VECTORS := PoolVector2Array() # ideally const var RADIAL_UNIT_VECTORS := PoolVector2Array() # ideally const
func set_screen_filter_alpha(alpha: float):
# Scale to minimum alpha
var new_alpha = lerp(screen_filter_min_alpha, 1.0, alpha)
if new_alpha != screen_filter.a:
screen_filter = Color(screen_filter.r, screen_filter.g, screen_filter.b, new_alpha)
emit_signal("screen_filter_changed")
func init_radial_values(): func init_radial_values():
for i in range(Rules.COLS): for i in range(Rules.COLS):
var angle = deg2rad(fposmod(Rules.FIRST_COLUMN_ANGLE_DEG + (i * Rules.COLS_ANGLE_DEG), 360.0)) var angle = deg2rad(fposmod(Rules.FIRST_COLUMN_ANGLE_DEG + (i * Rules.COLS_ANGLE_DEG), 360.0))

92
Menu.gd
View File

@ -21,11 +21,14 @@ var currently_playing := false
var scorescreen_song_key := "" var scorescreen_song_key := ""
var scorescreen_score_data := {} var scorescreen_score_data := {}
var scorescreen_datetime := {}
var scorescreen_saved := false
var touch_rects = [] var touch_rects = []
var TitleFont := preload("res://assets/MenuTitleFont.tres") var TitleFont := preload("res://assets/MenuTitleFont.tres")
var GenreFont := preload("res://assets/MenuGenreFont.tres") var GenreFont := preload("res://assets/MenuGenreFont.tres")
var ScoreFont := preload("res://assets/MenuScoreFont.tres")
var snd_interact := preload("res://assets/softclap.wav") var snd_interact := preload("res://assets/softclap.wav")
func scan_library(): func scan_library():
@ -55,6 +58,23 @@ func scan_library():
else: else:
print("An error occurred when trying to access the songs directory: ", err) print("An error occurred when trying to access the songs directory: ", err)
func save_score():
var rootdir = "user://scores"
var dir = Directory.new()
dir.make_dir_recursive(rootdir)
var data = {}
data.score_data = scorescreen_score_data
data.song_key = scorescreen_song_key
var json = JSON.print(data)
var file = File.new()
var err = file.open(rootdir + "/{year}{month}{day}T{hour}{minute}{second}.json".format(scorescreen_datetime), File.WRITE)
if err != OK:
print(err)
return err
file.store_string(json)
file.close()
scorescreen_saved = true
func _ready(): func _ready():
scan_library() scan_library()
$"/root/main/NoteHandler".connect("finished_song", self, "finished_song") $"/root/main/NoteHandler".connect("finished_song", self, "finished_song")
@ -175,26 +195,37 @@ func _draw_score_screen(center: Vector2) -> Array:
var song_key = scorescreen_song_key var song_key = scorescreen_song_key
var x = center.x var x = center.x
var y = center.y - 200 var y = center.y - 200
var x_songtile = x - 120
var x_score = x + 120
var x2 = x - 360 var x2 = x - 360
var x_spacing = 116 var x_spacing = 116
var y_spacing = 48 var y_spacing = 48
var y1 = y + size + y_spacing var y1 = y
var y2 = y1 + 120 var y2 = y + size + y_spacing*2
draw_songtile(song_key, Vector2(x-size/2.0, y), size, false, selected_difficulty, 3) var tex_judgement_text = $"/root/main/NoteHandler".tex_judgement_text
draw_string_centered(TitleFont, Vector2(x, y+size), song_defs[song_key]["title"], Color(0.95, 0.95, 1.0)) var judgement_text_scale = 0.667
var judgement_text_width = 256 * judgement_text_scale
var judgement_text_height = 64 * judgement_text_scale
draw_songtile(song_key, Vector2(x_songtile-size/2.0, y), size, false, selected_difficulty, 3)
draw_string_centered(TitleFont, Vector2(x_songtile, y+size), song_defs[song_key]["title"], Color(0.95, 0.95, 1.0))
var notestrs = ["Tap", "Hold", "Slide"] var notestrs = ["Tap", "Hold", "Slide"]
var judgestrs = Array(Rules.JUDGEMENT_STRINGS + ["Miss"]) var judgestrs = Array(Rules.JUDGEMENT_STRINGS + ["Miss"])
var judge_scores = [1.0, 0.9, 0.75, 0.5, 0.0] var judge_scores = [1.0, 0.9, 0.75, 0.5, 0.0]
var notetype_weights = [1.0, 2.0, 2.0] var notetype_weights = [1.0, 2.0, 2.0]
var notetype_scores = [] var notecount_total = 0
var notetype_counts = [] var notecount_early = 0
var notecount_late = 0
var total_score = 0.0 var total_score = 0.0
var total_scoremax = 0.0 var total_scoremax = 0.0
for i in len(judgestrs): for i in len(judgestrs):
# For each judgement type, print a column header # For each judgement type, print a column header
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(i+1), y2), judgestrs[i], Color(0.95, 0.95, 1.0)) # draw_string_centered(TitleFont, Vector2(x2+x_spacing*(i+1), y2), judgestrs[i], Color(0.95, 0.95, 1.0))
draw_texture_rect_region(tex_judgement_text, Rect2(x2+x_spacing*(i+1)-judgement_text_width/2.0, y2, judgement_text_width, judgement_text_height), Rect2(0, 128*(i+3), 512, 128))
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(len(judgestrs)+1), y2), "Score", Color(0.95, 0.95, 1.0)) draw_string_centered(TitleFont, Vector2(x2+x_spacing*(len(judgestrs)+1), y2), "Score", Color(0.95, 0.95, 1.0))
for i in len(notestrs): for i in len(notestrs):
# For each note type, make a row and print scores # For each note type, make a row and print scores
draw_string_centered(TitleFont, Vector2(x2, y2+y_spacing*(i+1)), notestrs[i]+"s:", Color(0.95, 0.95, 1.0)) draw_string_centered(TitleFont, Vector2(x2, y2+y_spacing*(i+1)), notestrs[i]+"s:", Color(0.95, 0.95, 1.0))
@ -208,14 +239,16 @@ func _draw_score_screen(center: Vector2) -> Array:
score = scorescreen_score_data[i]["MISS"] score = scorescreen_score_data[i]["MISS"]
else: else:
score = scorescreen_score_data[i][j] + scorescreen_score_data[i][-j] score = scorescreen_score_data[i][j] + scorescreen_score_data[i][-j]
notecount_early += scorescreen_score_data[i][-j]
notecount_late += scorescreen_score_data[i][j]
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(j+1), y2+y_spacing*(i+1)), str(score), Color(0.95, 0.95, 1.0)) draw_string_centered(TitleFont, Vector2(x2+x_spacing*(j+1), y2+y_spacing*(i+1)), str(score), Color(0.95, 0.95, 1.0))
notecount_total += score # Kinda redundant, will probably refactor eventually
note_count += score note_count += score
note_score += score * judge_scores[j] note_score += score * judge_scores[j]
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(len(judgestrs)+1), y2+y_spacing*(i+1)), "%2.2f%%"%(note_score/note_count*100.0), Color(0.95, 0.95, 1.0)) draw_string_centered(TitleFont, Vector2(x2+x_spacing*(len(judgestrs)+1), y2+y_spacing*(i+1)), "%2.2f%%"%(note_score/note_count*100.0), Color(0.95, 0.95, 1.0))
notetype_counts.append(note_count)
notetype_scores.append(note_score)
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/total_scoremax
var score_idx = 0 var score_idx = 0
for cutoff in Rules.SCORE_CUTOFFS: for cutoff in Rules.SCORE_CUTOFFS:
@ -223,10 +256,27 @@ func _draw_score_screen(center: Vector2) -> Array:
break break
else: else:
score_idx += 1 score_idx += 1
draw_string_centered(TitleFont, Vector2(x, y1), Rules.SCORE_STRINGS[score_idx], Color(0.95, 0.95, 1.0)) # $ScoreText.draw_string_centered(ScoreFont, Vector2(x_score, y1), Rules.SCORE_STRINGS[score_idx], Color(1.0, 1.0, 1.0))
draw_string_centered(TitleFont, Vector2(x, y1+y_spacing), "%2.3f%%"%(overall_score*100.0), Color(0.95, 0.95, 1.0)) # $ScoreText.draw_string_centered(TitleFont, Vector2(x_score, y1+y_spacing*3), "%2.3f%%"%(overall_score*100.0), Color(1.0, 1.0, 1.0))
# touchrects.append({rect=r, chart_idx=diff}) draw_string_centered(ScoreFont, Vector2(x_score, y1), Rules.SCORE_STRINGS[score_idx], Color(1.0, 1.0, 1.0))
touchrects.append({rect=Rect2(-450.0, 150.0, 900.0, 300.0), next_menu=MenuMode.SONG_SELECT}) draw_string_centered(TitleFont, Vector2(x_score, y1+y_spacing*3), "%2.3f%%"%(overall_score*100.0), Color(1.0, 1.0, 1.0))
draw_string_centered(TitleFont, Vector2(x, y2+y_spacing*4), "Early : Late", Color(0.95, 0.95, 1.0))
draw_string_centered(TitleFont, Vector2(x, y2+y_spacing*5), "%3d%% : %3d%%"%[notecount_early*100/notecount_total, notecount_late*100/notecount_total], Color(0.95, 0.95, 1.0))
var rect_songselect := Rect2(-100.0, 300.0, 400.0, 100.0)
draw_rect(rect_songselect, Color.red)
draw_string_centered(TitleFont, Vector2(x+100, 320), "Song Select", Color(0.95, 0.95, 1.0))
touchrects.append({rect=rect_songselect, next_menu=MenuMode.SONG_SELECT})
var rect_save := Rect2(-300.0, 300.0, 180.0, 100.0)
if not scorescreen_saved:
draw_rect(rect_save, Color.blue)
draw_string_centered(TitleFont, Vector2(x-210, 320), "Save", Color(0.95, 0.95, 1.0))
touchrects.append({rect=rect_save, action="save"})
else:
draw_rect(rect_save, Color.darkgray)
draw_string_centered(TitleFont, Vector2(x-210, 320), "Saved", Color(0.95, 0.95, 1.0))
return touchrects return touchrects
@ -251,7 +301,7 @@ func _draw():
MenuMode.OPTIONS: MenuMode.OPTIONS:
pass pass
MenuMode.GAMEPLAY: MenuMode.GAMEPLAY:
pass GameTheme.set_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:
@ -262,20 +312,23 @@ func _draw():
MenuMode.OPTIONS: MenuMode.OPTIONS:
pass pass
MenuMode.GAMEPLAY: MenuMode.GAMEPLAY:
pass GameTheme.set_screen_filter_alpha(1.0 - progress)
MenuMode.SCORE_SCREEN: MenuMode.SCORE_SCREEN:
_draw_score_screen(center_next) _draw_score_screen(center_next)
else: else:
match menu_mode: match menu_mode:
MenuMode.SONG_SELECT: MenuMode.SONG_SELECT:
GameTheme.set_screen_filter_alpha(1.0)
touch_rects[menu_mode] = _draw_song_select(center) touch_rects[menu_mode] = _draw_song_select(center)
MenuMode.CHART_SELECT: MenuMode.CHART_SELECT:
GameTheme.set_screen_filter_alpha(1.0)
touch_rects[menu_mode] = _draw_chart_select(center) touch_rects[menu_mode] = _draw_chart_select(center)
MenuMode.OPTIONS: MenuMode.OPTIONS:
pass pass
MenuMode.GAMEPLAY: MenuMode.GAMEPLAY:
pass GameTheme.set_screen_filter_alpha(0.0)
MenuMode.SCORE_SCREEN: MenuMode.SCORE_SCREEN:
GameTheme.set_screen_filter_alpha(1.0)
touch_rects[menu_mode] = _draw_score_screen(center) touch_rects[menu_mode] = _draw_score_screen(center)
func set_menu_mode(mode): func set_menu_mode(mode):
@ -305,11 +358,18 @@ func touch_select_chart(touchdict):
func touch_score_screen(touchdict): func touch_score_screen(touchdict):
if touchdict.has("next_menu"): if touchdict.has("next_menu"):
SFXPlayer.play(SFXPlayer.Type.NON_POSITIONAL, self, snd_interact, 0.0)
set_menu_mode(touchdict.next_menu) set_menu_mode(touchdict.next_menu)
elif touchdict.has("action"):
SFXPlayer.play(SFXPlayer.Type.NON_POSITIONAL, self, snd_interact, 0.0)
if touchdict.action == "save":
save_score()
func finished_song(song_key, score_data): func finished_song(song_key, score_data):
scorescreen_song_key = song_key scorescreen_song_key = song_key
scorescreen_score_data = score_data scorescreen_score_data = score_data
scorescreen_datetime = OS.get_datetime()
scorescreen_saved = false
set_menu_mode(MenuMode.SCORE_SCREEN) set_menu_mode(MenuMode.SCORE_SCREEN)

View File

@ -26,3 +26,5 @@ func _draw():
for i in range(len(receptor_centers)): for i in range(len(receptor_centers)):
draw_circle(receptor_centers[i], receptor_px/2, GameTheme.receptor_color) draw_circle(receptor_centers[i], receptor_px/2, GameTheme.receptor_color)
func _ready():
GameTheme.connect("screen_filter_changed", self, "update")

View File

@ -16,5 +16,5 @@ const JUDGEMENT_TIMES_RELEASE_POST := [0.090, 0.140, 0.175, 0.200] # Small grac
const JUDGEMENT_TIMES_SLIDE_PRE := [0.090, 0.140, 0.175, 0.200] # Small grace period, sort-of const JUDGEMENT_TIMES_SLIDE_PRE := [0.090, 0.140, 0.175, 0.200] # Small grace period, sort-of
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]

View File

@ -76,6 +76,8 @@ material = SubResource( 2 )
[node name="Menu" type="Node2D" parent="."] [node name="Menu" type="Node2D" parent="."]
script = ExtResource( 8 ) script = ExtResource( 8 )
[node name="ScoreText" type="Node2D" parent="Menu"]
[node name="Bezel" type="Node2D" parent="."] [node name="Bezel" type="Node2D" parent="."]
script = ExtResource( 9 ) script = ExtResource( 9 )

53
shaders/scoretext.tres Normal file
View File

@ -0,0 +1,53 @@
[gd_resource type="ShaderMaterial" load_steps=2 format=2]
[sub_resource type="Shader" id=1]
code = "shader_type canvas_item;
//render_mode unshaded;
uniform float bps;
uniform vec4 star_color : hint_color;
uniform vec4 held_color : hint_color;
uniform vec2 screen_size;
//void vertex() {
//}
void fragment() {
vec4 sample = texture(TEXTURE, UV);
float color_scale = sample.r;
float bright_scale = (sample.g+sample.b)/2.0;
float dist = distance(FRAGCOORD.xy, screen_size/2.0);
float dist_norm = dist*1.8 / screen_size.y;
if (COLOR.rgb == star_color.rgb){
// Star ripple
COLOR.rg += dist_norm*0.33;
COLOR.rgb *= mix(abs(0.5-mod(TIME*bps*2.0+dist_norm, 1.0)), 1.0, 0.75);
COLOR.rgb *= color_scale; // Preserve black outlines
COLOR.rgb = mix(COLOR.rgb, vec3(1.0), bright_scale); // Preserve white outlines
} else if (COLOR.rgb == held_color.rgb){
// Hold note being held, flashy effects
COLOR.b *= mix(2.0*abs(0.5-mod(TIME*bps*2.0+dist_norm, 1.0)), 1.0, 0.35);
COLOR.g *= mix(1.0 - 2.0*abs(0.5-mod(TIME*bps*0.5+dist_norm, 1.0)), 0.0, 0.35);
COLOR.r *= mix(abs(0.5-mod(TIME*bps, 1.0)), 1.0, 0.85);
if (color_scale < 0.5){ // Make black outlines shine
COLOR.rgb = mix(COLOR.rgb, vec3(mix(dist_norm, abs(0.5-mod(TIME*bps*8.0, 1.0)), 0.33)), 1.0-(color_scale*2.0));
}
COLOR.rgb = mix(COLOR.rgb, vec3(1.0), 0.33); // brighten overall
COLOR.rgb = mix(COLOR.rgb, vec3(0.25), bright_scale); // Invert white outlines
} else {
COLOR.gb += 0.1;
COLOR.rgb *= mix(abs(0.5-mod(TIME*bps, 1.0)), 1.0, 0.85);
COLOR.rgb *= color_scale; // Preserve black outlines
COLOR.rgb = mix(COLOR.rgb, vec3(1.0), bright_scale); // Preserve white outlines
}
COLOR.a = clamp(COLOR.a*texture(TEXTURE, UV).a, 0.0, 1.0);
}"
[resource]
shader = SubResource( 1 )
shader_param/bps = null
shader_param/star_color = null
shader_param/held_color = null
shader_param/screen_size = null