add split times to highscore

This commit is contained in:
interfisch 2025-01-14 23:57:26 +01:00
parent 34f4533b9f
commit 502d22475f
4 changed files with 113 additions and 14 deletions

View file

@ -1,10 +1,16 @@
[gd_scene load_steps=11 format=3 uid="uid://cotth8e5rtioe"] [gd_scene load_steps=14 format=3 uid="uid://cotth8e5rtioe"]
[ext_resource type="Script" path="res://scripts/game.gd" id="1_7syh4"] [ext_resource type="Script" path="res://scripts/game.gd" id="1_7syh4"]
[ext_resource type="Script" path="res://scripts/times.gd" id="2_80mhm"] [ext_resource type="Script" path="res://scripts/times.gd" id="2_80mhm"]
[ext_resource type="AudioStream" uid="uid://cdricwi06nttp" path="res://sounds/beep/countdown_beep_high.mp3" id="3_fdp2i"] [ext_resource type="AudioStream" uid="uid://cdricwi06nttp" path="res://sounds/beep/countdown_beep_high.mp3" id="3_fdp2i"]
[ext_resource type="AudioStream" uid="uid://v3eqa857k2xo" path="res://sounds/beep/countdown_beep.mp3" id="3_fv4j3"] [ext_resource type="AudioStream" uid="uid://v3eqa857k2xo" path="res://sounds/beep/countdown_beep.mp3" id="3_fv4j3"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_e0d0g"]
bg_color = Color(0.6, 0.6, 0.6, 0.294118)
[sub_resource type="Theme" id="Theme_y7g1t"]
Label/styles/normal = SubResource("StyleBoxFlat_e0d0g")
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_61sjv"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_61sjv"]
bg_color = Color(0.670588, 0.670588, 0.670588, 0.498039) bg_color = Color(0.670588, 0.670588, 0.670588, 0.498039)
skew = Vector2(0.333, 0) skew = Vector2(0.333, 0)
@ -103,6 +109,18 @@ tracks/6/keys = {
"update": 0, "update": 0,
"values": [Color(1, 1, 1, 1)] "values": [Color(1, 1, 1, 1)]
} }
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("splittime_label:modulate")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 0)]
}
[sub_resource type="Animation" id="Animation_gjxtp"] [sub_resource type="Animation" id="Animation_gjxtp"]
resource_name = "game_end" resource_name = "game_end"
@ -238,11 +256,28 @@ tracks/4/keys = {
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)] "values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
} }
[sub_resource type="Animation" id="Animation_60fqb"]
resource_name = "show_splittime"
length = 2.0
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("splittime_label:modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.3, 1.6, 2),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_wuihg"] [sub_resource type="AnimationLibrary" id="AnimationLibrary_wuihg"]
_data = { _data = {
"RESET": SubResource("Animation_ph30r"), "RESET": SubResource("Animation_ph30r"),
"game_end": SubResource("Animation_gjxtp"), "game_end": SubResource("Animation_gjxtp"),
"game_start": SubResource("Animation_5vgpy") "game_start": SubResource("Animation_5vgpy"),
"show_splittime": SubResource("Animation_60fqb")
} }
[node name="Game" type="Node2D"] [node name="Game" type="Node2D"]
@ -305,6 +340,25 @@ theme_override_font_sizes/font_size = 50
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
[node name="splittime_label" type="Label" parent="hud"]
modulate = Color(1, 1, 1, 0)
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -50.0
offset_top = -224.0
offset_right = 50.0
offset_bottom = -179.0
grow_horizontal = 2
grow_vertical = 2
theme = SubResource("Theme_y7g1t")
theme_override_font_sizes/font_size = 32
text = "123.21"
horizontal_alignment = 1
vertical_alignment = 1
[node name="overlaycolor" type="ColorRect" parent="hud"] [node name="overlaycolor" type="ColorRect" parent="hud"]
self_modulate = Color(1, 1, 1, 0) self_modulate = Color(1, 1, 1, 0)
offset_left = -25.0 offset_left = -25.0

View file

@ -3,6 +3,7 @@ extends CharacterBody2D
#Tutorial: https://www.youtube.com/watch?v=mJ1ZfGDTMCY t=15s #Tutorial: https://www.youtube.com/watch?v=mJ1ZfGDTMCY t=15s
signal car_finished(playerid,finalTime) signal car_finished(playerid,finalTime)
signal car_on_checkpoint(cplayerid,checkpointtimes,i)
const COLLISIONMASK_FINISH=3 #set in road_overlay const COLLISIONMASK_FINISH=3 #set in road_overlay
const COLLISIONMASK_CHECKPOINT=4 #set in road_overlay const COLLISIONMASK_CHECKPOINT=4 #set in road_overlay
@ -325,6 +326,7 @@ func check_markers():
if checkpoint_i>=0 and nextcp_i>=0: #found and there is a next checkpoint time free if checkpoint_i>=0 and nextcp_i>=0: #found and there is a next checkpoint time free
if (nextcp_i%checkpoints.size())==checkpoint_i: #this cp is next cp if (nextcp_i%checkpoints.size())==checkpoint_i: #this cp is next cp
checkpointtimes[nextcp_i]=Gamestate.getTimeElapsed() checkpointtimes[nextcp_i]=Gamestate.getTimeElapsed()
car_on_checkpoint.emit(playerid,checkpointtimes,nextcp_i)
#print("Player "+str(playerid)+" Checkpoint "+str(ray_cast_car.get_collider().name)) #print("Player "+str(playerid)+" Checkpoint "+str(ray_cast_car.get_collider().name))
#print("New CP array "+str(checkpointtimes)) #print("New CP array "+str(checkpointtimes))

View file

@ -12,7 +12,7 @@ extends Node2D
@onready var timer_close: Timer = $timer_close @onready var timer_close: Timer = $timer_close
@onready var highscore_label: Label = $hud/highscore_label @onready var highscore_label: Label = $hud/highscore_label
@onready var splittime_label: Label = $hud/splittime_label
const caroffset= 32+4 #space cars on start line const caroffset= 32+4 #space cars on start line
const caroffset_side= 16 const caroffset_side= 16
@ -29,6 +29,7 @@ var camera_zoom_out_lookahead_time=1 #predicted position of car in t seconds for
var running=false var running=false
var highscorecheckpointtimes=null
var time_close_keypressed=1 #seconds to wait after key pressed at endscreen var time_close_keypressed=1 #seconds to wait after key pressed at endscreen
@ -73,6 +74,7 @@ func _ready() -> void:
newcarinstance.setPosition(Vector2(caroffset_rear*-1*i_position,(fmod(i_position,2)-0.5)*2.0*caroffset_side)) newcarinstance.setPosition(Vector2(caroffset_rear*-1*i_position,(fmod(i_position,2)-0.5)*2.0*caroffset_side))
newcarinstance.setCheckpoints(checkpoints,Gamestate.getRounds()) newcarinstance.setCheckpoints(checkpoints,Gamestate.getRounds())
newcarinstance.getCharacterBody().car_finished.connect(_on_car_finished) newcarinstance.getCharacterBody().car_finished.connect(_on_car_finished)
newcarinstance.getCharacterBody().car_on_checkpoint.connect(_on_car_on_checkpoint)
var startmarker:Sprite2D=mapsceneinstance.get_node("startmarker") var startmarker:Sprite2D=mapsceneinstance.get_node("startmarker")
if startmarker != null: if startmarker != null:
@ -86,7 +88,7 @@ func _ready() -> void:
print("i_position="+str(i_position)+" carpos is ="+str(newcarinstance.getPosition())+" instancepos="+str(newcarinstance.position)+" colori="+str(player.colori)+" color="+str(player.color)) print("i_position="+str(i_position)+" carpos is ="+str(newcarinstance.getPosition())+" instancepos="+str(newcarinstance.position)+" colori="+str(player.colori)+" color="+str(player.color))
i+=1 i+=1
highscorecheckpointtimes=HighscoreHandler.loadHighcoreCheckpoints(Gamestate.getSelectedMapName(),"normal",str(Gamestate.getRounds()))
func custom_array_sort_rank(a, b): func custom_array_sort_rank(a, b):
@ -221,6 +223,26 @@ func _on_car_finished(playerid,finalTime) -> void:
if times_container.getPlayersFinished() == Gamestate.getPlayers().size(): #all players have finish times if times_container.getPlayersFinished() == Gamestate.getPlayers().size(): #all players have finish times
finishGame()# Game finished finishGame()# Game finished
func _on_car_on_checkpoint(playerid,checkpointtimes,i) -> void:
if Gamestate.getPlayers().size()==1 and highscorecheckpointtimes != null: #singleplayer and previous split times exista
# calculate split times
var timediff = checkpointtimes[i]-highscorecheckpointtimes[i]
timediff=round(timediff*1000)/1000
#splittime_label.visible=true
game_hud_animations.play("show_splittime")
if timediff==0: #same time or first entry
splittime_label.text=="+"+str(timediff)
splittime_label.self_modulate=Color(200,200,0)
elif timediff<0: #new highscore
splittime_label.text=str(timediff)
splittime_label.self_modulate=Color(0,0,200)
elif timediff>0: #worse time
splittime_label.text="+"+str(timediff)
splittime_label.self_modulate=Color(200,0,0)
func finishGame(): func finishGame():
@ -245,7 +267,7 @@ func finishGame():
if Gamestate.getPlayers().size()==1: #was played in singleplayer if Gamestate.getPlayers().size()==1: #was played in singleplayer
var timediff=HighscoreHandler.updateHighscore(Gamestate.getSelectedMapName(),"normal",str(Gamestate.getRounds()),getfinalTimeByPlayer(Gamestate.getPlayers()[0])) var timediff=HighscoreHandler.updateHighscore(Gamestate.getSelectedMapName(),"normal",str(Gamestate.getRounds()),getfinalTimeByPlayer(Gamestate.getPlayers()[0]),getcheckpointtimesByPlayer(Gamestate.getPlayers()[0]))
print("Timediff="+str(timediff)) print("Timediff="+str(timediff))
timediff=round(timediff*1000)/1000 timediff=round(timediff*1000)/1000
highscore_label.visible=true highscore_label.visible=true
@ -281,11 +303,21 @@ func custom_array_sort_player_finaltime(a, b):
#finalTimeB=c.getCharacterBody().finalTime #finalTimeB=c.getCharacterBody().finalTime
func getfinalTimeByPlayer(player): func getPlayerCB(player):
var cars=cars.get_children() var cars=cars.get_children()
for c in cars: for c in cars:
if c.reference_gamestateplayer==player: if c.reference_gamestateplayer==player:
return c.getCharacterBody().finalTime return c.getCharacterBody()
return null
func getfinalTimeByPlayer(player):
var p=getPlayerCB(player)
if p != null:
return p.finalTime
return null
func getcheckpointtimesByPlayer(player):
var p=getPlayerCB(player)
if p != null:
return p.checkpointtimes
return null return null
func _on_timer_close_timeout() -> void: func _on_timer_close_timeout() -> void:

View file

@ -4,12 +4,12 @@ const HIGHSCORE_FILE_PATH = "highscores.json"
func updateHighscore(mapname:String,preset:String,rounds:String,time:float): func updateHighscore(mapname:String,preset:String,rounds:String,time:float,checkpointtimes:Array[float]):
var highscores=loadHighscoreDict() var highscores=loadHighscoreDict()
var lasthighscore=loadHighscore(mapname,preset,rounds) var lasthighscore=loadHighscore(mapname,preset,rounds)
if lasthighscore !=null: if lasthighscore !=null:
if time<lasthighscore: #better time if time<lasthighscore: #better time
highscores[mapname][preset][rounds].append({"created":Time.get_unix_time_from_system(),"time":time}) highscores[mapname][preset][rounds].append({"created":Time.get_unix_time_from_system(),"time":time,"checkpoints":checkpointtimes})
storeHighscoreDict(highscores) storeHighscoreDict(highscores)
return time-lasthighscore return time-lasthighscore
else: #first entry for this map and config else: #first entry for this map and config
@ -22,22 +22,33 @@ func updateHighscore(mapname:String,preset:String,rounds:String,time:float):
highscores[mapname][preset]={} highscores[mapname][preset]={}
if !highscores[mapname][preset].has(rounds): if !highscores[mapname][preset].has(rounds):
print("rounds not known") print("rounds not known")
highscores[mapname][preset][rounds]=[{"created":Time.get_unix_time_from_system(),"time":time}] highscores[mapname][preset][rounds]=[{"created":Time.get_unix_time_from_system(),"time":time,"checkpoints":checkpointtimes}]
storeHighscoreDict(highscores) storeHighscoreDict(highscores)
return 0 return 0
func loadHighscore(mapname:String,preset:String,rounds:String): func loadHighscoredata(mapname:String,preset:String,rounds:String):
var highscores=loadHighscoreDict() var highscores=loadHighscoreDict()
if highscores.has(mapname): if highscores.has(mapname):
if highscores[mapname].has(preset): if highscores[mapname].has(preset):
if highscores[mapname][preset].has(rounds): if highscores[mapname][preset].has(rounds):
if highscores[mapname][preset][rounds].size()>0: if highscores[mapname][preset][rounds].size()>0:
return highscores[mapname][preset][rounds][highscores[mapname][preset][rounds].size()-1]["time"] #return last entry return highscores[mapname][preset][rounds][highscores[mapname][preset][rounds].size()-1] #return last entry
return {}
func loadHighscore(mapname:String,preset:String,rounds:String):
var highscoredata=loadHighscoredata(mapname,preset,rounds)
if highscoredata != null and highscoredata.has("time"):
return highscoredata["time"]
return null return null
func loadHighcoreCheckpoints(mapname:String,preset:String,rounds:String):
var highscoredata=loadHighscoredata(mapname,preset,rounds)
if highscoredata != null and highscoredata.has("checkpoints"):
return highscoredata["checkpoints"]
return null
func loadHighscoreDict(): func loadHighscoreDict():