From 502d22475f583b683dc2f1ac77075bdce4bcbb5e Mon Sep 17 00:00:00 2001 From: Fisch Date: Tue, 14 Jan 2025 23:57:26 +0100 Subject: [PATCH] add split times to highscore --- scenes/game.tscn | 58 +++++++++++++++++++++++++++++++++++-- scripts/car.gd | 2 ++ scripts/game.gd | 44 ++++++++++++++++++++++++---- scripts/highscoreHandler.gd | 23 +++++++++++---- 4 files changed, 113 insertions(+), 14 deletions(-) diff --git a/scenes/game.tscn b/scenes/game.tscn index f72e755..b918873 100644 --- a/scenes/game.tscn +++ b/scenes/game.tscn @@ -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/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://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"] bg_color = Color(0.670588, 0.670588, 0.670588, 0.498039) skew = Vector2(0.333, 0) @@ -103,6 +109,18 @@ tracks/6/keys = { "update": 0, "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"] 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)] } +[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"] _data = { "RESET": SubResource("Animation_ph30r"), "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"] @@ -305,6 +340,25 @@ theme_override_font_sizes/font_size = 50 horizontal_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"] self_modulate = Color(1, 1, 1, 0) offset_left = -25.0 diff --git a/scripts/car.gd b/scripts/car.gd index 1f61f46..1a3f087 100644 --- a/scripts/car.gd +++ b/scripts/car.gd @@ -3,6 +3,7 @@ extends CharacterBody2D #Tutorial: https://www.youtube.com/watch?v=mJ1ZfGDTMCY t=15s signal car_finished(playerid,finalTime) +signal car_on_checkpoint(cplayerid,checkpointtimes,i) const COLLISIONMASK_FINISH=3 #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 (nextcp_i%checkpoints.size())==checkpoint_i: #this cp is next cp 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("New CP array "+str(checkpointtimes)) diff --git a/scripts/game.gd b/scripts/game.gd index 54d8341..fd5ec09 100644 --- a/scripts/game.gd +++ b/scripts/game.gd @@ -12,7 +12,7 @@ extends Node2D @onready var timer_close: Timer = $timer_close @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_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 highscorecheckpointtimes=null 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.setCheckpoints(checkpoints,Gamestate.getRounds()) 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") if startmarker != null: @@ -86,8 +88,8 @@ 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)) i+=1 - - + highscorecheckpointtimes=HighscoreHandler.loadHighcoreCheckpoints(Gamestate.getSelectedMapName(),"normal",str(Gamestate.getRounds())) + func custom_array_sort_rank(a, b): return a.rank > b.rank #a>b = higher rank (more wins) -> better start position @@ -221,6 +223,26 @@ func _on_car_finished(playerid,finalTime) -> void: if times_container.getPlayersFinished() == Gamestate.getPlayers().size(): #all players have finish times 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(): @@ -245,7 +267,7 @@ func finishGame(): 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)) timediff=round(timediff*1000)/1000 highscore_label.visible=true @@ -281,11 +303,21 @@ func custom_array_sort_player_finaltime(a, b): #finalTimeB=c.getCharacterBody().finalTime -func getfinalTimeByPlayer(player): +func getPlayerCB(player): var cars=cars.get_children() for c in cars: 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 func _on_timer_close_timeout() -> void: diff --git a/scripts/highscoreHandler.gd b/scripts/highscoreHandler.gd index 265840b..eaea490 100644 --- a/scripts/highscoreHandler.gd +++ b/scripts/highscoreHandler.gd @@ -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 lasthighscore=loadHighscore(mapname,preset,rounds) if lasthighscore !=null: if time0: - 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 +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():