small racing game im working on
33 files changed, 509 insertions, 405 deletions
@@ -2,3 +2,6 @@ movie.* *.blend1 addons/ +*.x86_64 +godot.lock +export_presets.cfg diff --git a/assets/cars/kenney_sedan/sedan.blend b/assets/cars/kenney_sedan/sedan.blend Binary files differindex 5b1d311..755ede5 100644 --- a/assets/cars/kenney_sedan/sedan.blend +++ b/assets/cars/kenney_sedan/sedan.blend diff --git a/assets/cars/kenney_sedan/sedan.blend.import b/assets/cars/kenney_sedan/sedan.blend.import index cc6db4d..485d322 100644 --- a/assets/cars/kenney_sedan/sedan.blend.import +++ b/assets/cars/kenney_sedan/sedan.blend.import @@ -26,8 +26,10 @@ skins/use_named_skins=true animation/import=true animation/fps=30 animation/trimming=false +animation/remove_immutable_tracks=true import_script/path="" _subresources={} +gltf/embedded_image_handling=1 blender/nodes/visible=0 blender/nodes/punctual_lights=true blender/nodes/cameras=true diff --git a/assets/cars/kenney_sedan/sedan.tscn b/assets/cars/kenney_sedan/sedan.tscn index 8ac24bf..fd2d275 100644 --- a/assets/cars/kenney_sedan/sedan.tscn +++ b/assets/cars/kenney_sedan/sedan.tscn @@ -17,6 +17,7 @@ albedo_color = Color(0.239216, 0.239216, 0.239216, 1) [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_gjgu8"] resource_name = "paintRed" +transparency = 1 vertex_color_use_as_albedo = true albedo_color = Color(1, 0.227451, 0.360134, 1) metallic = 1.0 @@ -342,6 +343,7 @@ collision_layer = 2 collision_mask = 3 mass = 3.0 physics_material_override = SubResource("PhysicsMaterial_grep7") +freeze = true [node name="Coll" type="CollisionShape3D" parent="Ball"] shape = SubResource("SphereShape3D_2sf22") diff --git a/assets/textures/base-noise.png.import b/assets/textures/base-noise.png.import index f949462..7431d5e 100644 --- a/assets/textures/base-noise.png.import +++ b/assets/textures/base-noise.png.import @@ -4,23 +4,22 @@ importer="texture" type="CompressedTexture2D" uid="uid://11wgfnak257h" path.s3tc="res://.godot/imported/base-noise.png-1465006bf87670e88934396a47068ff4.s3tc.ctex" -path.etc2="res://.godot/imported/base-noise.png-1465006bf87670e88934396a47068ff4.etc2.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/textures/base-noise.png" -dest_files=["res://.godot/imported/base-noise.png-1465006bf87670e88934396a47068ff4.s3tc.ctex", "res://.godot/imported/base-noise.png-1465006bf87670e88934396a47068ff4.etc2.ctex"] +dest_files=["res://.godot/imported/base-noise.png-1465006bf87670e88934396a47068ff4.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 mipmaps/generate=true diff --git a/assets/textures/grass.png.import b/assets/textures/grass.png.import index 8b746fe..df819ed 100644 --- a/assets/textures/grass.png.import +++ b/assets/textures/grass.png.import @@ -4,23 +4,22 @@ importer="texture" type="CompressedTexture2D" uid="uid://dyk71hogwv01g" path.s3tc="res://.godot/imported/grass.png-44de1b601ed5e0482c9aa195977ab90c.s3tc.ctex" -path.etc2="res://.godot/imported/grass.png-44de1b601ed5e0482c9aa195977ab90c.etc2.ctex" metadata={ -"imported_formats": ["s3tc", "etc2"], +"imported_formats": ["s3tc_bptc"], "vram_texture": true } [deps] source_file="res://assets/textures/grass.png" -dest_files=["res://.godot/imported/grass.png-44de1b601ed5e0482c9aa195977ab90c.s3tc.ctex", "res://.godot/imported/grass.png-44de1b601ed5e0482c9aa195977ab90c.etc2.ctex"] +dest_files=["res://.godot/imported/grass.png-44de1b601ed5e0482c9aa195977ab90c.s3tc.ctex"] [params] compress/mode=2 +compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 -compress/bptc_ldr=0 compress/normal_map=0 compress/channel_pack=0 mipmaps/generate=true @@ -1,14 +1,16 @@ extends Camera3D +class_name CarCamera -var follow_this: Node3D -@export var target_distance = 3.0 -@export var target_height = 2.0 +@export var target_distance = 9.0 +@export var target_height = 4.0 -var last_lookat +var follow_this: Node3D +var last_lookat: Vector3 func _ready(): - set_physics_process(false) - + global_position = follow_this.global_position + (follow_this.global_transform.basis.z * target_distance) + look_at(follow_this.global_position) + last_lookat = follow_this.global_position func target() -> Vector3: var delta_v := global_position - follow_this.global_position @@ -32,9 +34,5 @@ func _physics_process(delta): look_at(last_lookat, Vector3(0.0, 1.0, 0.0)) -func _on_race_created_car(car: Car) -> void: +func _init(car: Car) -> void: follow_this = car.car_mesh - global_position = follow_this.global_position + (follow_this.global_transform.basis.z * target_distance) - look_at(follow_this.global_position) - last_lookat = follow_this.global_position - set_physics_process(true) diff --git a/classes/car.gd b/classes/car.gd index 0786a0f..5ecd629 100644 --- a/classes/car.gd +++ b/classes/car.gd @@ -28,6 +28,7 @@ var _steering := 0.0 func _ready(): $Ball/DebugMesh.visible = show_debug ground_ray.add_exception(ball) + set_physics_process(false) func steer(to: float) -> void: _steering = clamp(lerpf(_steering, -to, wheel_turn_speed), -max_steering_range, max_steering_range) @@ -66,9 +67,9 @@ func kph() -> float: func spin_kph() -> float: return (ball.angular_velocity.length_squared() / 12) -func limit() -> void: - ball.linear_damp = max(.1 * (kph() - limit_speed), 0) if kph() > limit_speed else 0.0 - ball.angular_damp = max(.1 * (spin_kph() - limit_spin), 0) if spin_kph() > limit_spin else 0.0 +func limit(delta: float) -> void: + ball.linear_damp = max((.5 * delta) * (kph() - limit_speed), 0) if kph() > limit_speed else 0.0 + ball.angular_damp = max(5 * (spin_kph() - limit_spin), 0) if spin_kph() > limit_spin else 0.0 func _physics_process(delta: float) -> void: move_mesh(delta) @@ -85,8 +86,7 @@ func _physics_process(delta: float) -> void: skid_l.emitting = drift skid_r.emitting = drift - limit() - + limit(delta) turn(delta) floor_mesh(delta) @@ -95,3 +95,7 @@ func align_with_y(xform: Transform3D, new_y: Vector3) -> Transform3D: xform.basis.x = -xform.basis.z.cross(new_y) xform.basis = xform.basis.orthonormalized() return xform + +func start() -> void: + ball.freeze = false + set_physics_process(true) diff --git a/classes/timer.gd b/classes/timer.gd new file mode 100644 index 0000000..01684b5 --- /dev/null +++ b/classes/timer.gd @@ -0,0 +1,26 @@ +extends Node +class_name GameTimer + +var elapsed_time: float = 0.0 + +func _ready() -> void: + stop() + +func start() -> void: + set_process(true) + +func stop() -> void: + set_process(false) + +func now() -> float: + return elapsed_time + +## format a number of seconds into m:s.ms +static func format(time: float) -> String: + return "%01d:%02d.%02d" % [time / 60, fmod(time, 60), fmod(time * 1000, 100)] + +func fmt_now() -> String: + return GameTimer.format(elapsed_time) + +func _process(delta: float) -> void: + elapsed_time += delta
\ No newline at end of file diff --git a/classes/trackdata.gd b/classes/trackdata.gd index 3ac8175..225a385 100644 --- a/classes/trackdata.gd +++ b/classes/trackdata.gd @@ -4,7 +4,7 @@ extends Resource const SaveLoad := preload("res://addons/@bendn/remap/private/SaveLoadUtils.gd") var time: float -var checkpoints: Array[PackedFloat32Array] +var checkpoints: Array#[PackedFloat32Array] var positional := { origins = PackedVector3Array(), rotations = PackedVector3Array(), @@ -17,7 +17,7 @@ func data() -> Dictionary: func _init(num_checkpoints := 0, laps := 0) -> void: for i in laps: - var arr: PackedFloat32Array = [] + var arr := [] arr.resize(num_checkpoints + 1) arr.fill(-1) checkpoints.append(arr) diff --git a/globals.gd b/globals.gd new file mode 100644 index 0000000..7cb7939 --- /dev/null +++ b/globals.gd @@ -0,0 +1,3 @@ +extends Node + +var playing: TrackResource @@ -3,5 +3,10 @@ "name": "@bendn/remap", "version": "5.0.6", "integrity": "sha512-lfB0Vx/fmXhnrTttiG+sr33EFAlAEopDq9lX2bn3z+pp3dzSuMtTaRwbkUN8ndbuwfPa8Dm+NghUX2s3wHQFLQ==" + }, + { + "name": "@bendn/splitter", + "version": "1.0.3", + "integrity": "sha512-A9z9qjP1Zvz3RnRuyRUrCK96ocAFDq3If/Gx+a/GgiGm3RhLIq0O0UWwWihSHEWcQlgZ9yUpLTPosfXEER3mhA==" } ]
\ No newline at end of file diff --git a/godot.package b/godot.package index c9a13a2..2e6c546 100644 --- a/godot.package +++ b/godot.package @@ -1,2 +1,3 @@ [packages] "@bendn/remap" = '5.0.6' +"@bendn/splitter" = '1.0.3' diff --git a/project.godot b/project.godot index db3c969..8bc881f 100644 --- a/project.godot +++ b/project.godot @@ -11,17 +11,20 @@ config_version=5 [application] config/name="tracer" -run/main_scene="res://race.tscn" +run/main_scene="res://start.tscn" config/use_custom_user_dir=true config/custom_user_dir_name="tracer" config/features=PackedStringArray("4.0") +[autoload] + +Globals="*res://globals.gd" + [display] window/size/viewport_width=1920 window/size/viewport_height=1080 -window/stretch/mode="viewport" -window/stretch/aspect="expand" +window/stretch/aspect="ignore" [editor] @@ -1,17 +1,22 @@ extends Node3D +class_name Race @export var car_scene: PackedScene @export var ghost_scene: PackedScene -@export var track: TrackLoader -@export var splits: Control -@export var timer: Control -@onready var data := TrackSaveableData.new(track.checkpoints.size(), track.track.laps) -@onready var best_time_data := TrackSaveableData._load(saves % track.track.name) +@export var track_loader_scene: PackedScene + +# in order of initialization +var track_res: TrackResource +var track: TrackLoader +var data: TrackSaveableData +var best_time_data: TrackSaveableData var car: Car var ghost: GhostCar -var current_lap := 0 var start_frame: int + +var current_lap := 0 var playing := false +var timer := GameTimer.new() const SaveLoad := preload("res://addons/@bendn/remap/private/SaveLoadUtils.gd") const saves := "user://%s.trackdata" @@ -20,6 +25,10 @@ signal next_lap signal created_car(car: Car) signal created_ghost(ghost: GhostCar) signal finished +signal split(time: float, prev_time: float) + +func initialize(t: TrackResource) -> void: + track_res = t func mkghost() -> void: var g: Node3D = ghost_scene.instantiate() @@ -28,48 +37,57 @@ func mkghost() -> void: add_child(ghost) ghost.global_position = best_time_data.loadshot(0)[0] ghost.global_rotation = best_time_data.loadshot(0)[1] + ghost.hide() created_ghost.emit(ghost) -func _ready() -> void: - set_physics_process(false) - if best_time_data: - mkghost() +func mkcar() -> void: car = HumanCar.attach(car_scene) - add_child(car) - car.ball.freeze = true car.visible = false - car.global_position = track.start_pos + Vector3.UP * 3.5 - car.set_deferred(&"rotation", track.start_rot + Vector3.UP * PI) - await get_tree().process_frame - car.global_position = car.global_position - (car.ball.global_transform.basis.z * 2) # bump forward a teensy bit + add_child(car) + car.rotation = track.start_rot + Vector3(0, PI, -PI/2) + # car.set_deferred(&"rotation", track.start_rot + Vector3(0, PI, -PI/2)) + car.global_position = track.start_pos + Vector3(0, 2, 0) - (car.ball.global_transform.basis.z * 2) # bump forward a teensy bit car.visible = true created_car.emit(car) print("car created") + +func _ready() -> void: + set_physics_process(false) + track = track_loader_scene.instantiate() + track.track = track_res + add_child(track) + data = TrackSaveableData.new(track_res.checkpoints.size(), track_res.laps) + best_time_data = TrackSaveableData._load(saves % track_res.name) + mkcar() + if best_time_data: + mkghost() + connect_checkpoints() + add_child(timer) + +func connect_checkpoints() -> void: for i in len(track.checkpoints): - track.checkpoints[i].collected.connect( - (func passed_cp(cp: int) -> void: if playing and data.checkpoints[current_lap][i] < 0: collect(cp)) - .bind(i)) - - track.finish.collected.connect( - func passed_finish() -> void: - if !playing: return - for i in len(data.checkpoints[current_lap]) - 1: # no any() function on packedfloat32 - if data.checkpoints[current_lap][i] < 0: - return - collect(-1) - if track.track.laps - 1 == current_lap: - finished.emit() - playing = false - print("finished") - if not best_time_data or data.time < best_time_data.time: - print("new pb!") - SaveLoad.save(saves % track.track.name, data.data()) - # best_time_data = data # this messes with the ghost, and doesnt matter yet anyways (until i can reset) - data = TrackSaveableData.new(track.checkpoints.size()) - else: - current_lap += 1 - next_lap.emit() - ) + track.checkpoints[i].collected.connect(passed_cp.bind(i)) + track.finish.collected.connect(passed_finish) + +func passed_cp(cp: int) -> void: if playing and data.checkpoints[current_lap][cp] < 0: collect(cp) + +func passed_finish() -> void: + if !playing: return + for i in len(data.checkpoints[current_lap]) - 1: + if data.checkpoints[current_lap][i] < 0: + return + collect(-1) + if track_res.laps - 1 == current_lap: + finished.emit() + playing = false + print("finished") + if not best_time_data or data.time < best_time_data.time: + print("new pb!") + SaveLoad.save(saves % track_res.name, data.data()) + data = TrackSaveableData.new(track.checkpoints.size()) + else: + current_lap += 1 + next_lap.emit() func _physics_process(_delta: float) -> void: data.snapshot(car) @@ -86,12 +104,14 @@ func _physics_process(_delta: float) -> void: func collect(cp: int) -> void: var time := best_time_data.get_time(current_lap, cp) if best_time_data else -1.0 - time = best_time_data.time if (not track.track.laps or track.track.laps == current_lap + 1) and cp == -1 and time != -1.0 else time - splits.update(timer.now(), time) + time = best_time_data.time if (not track_res.laps or track_res.laps == current_lap + 1) and cp == -1 and time != -1.0 else time + split.emit(timer.now(), time) data.collect(current_lap, cp, timer.now()) -func _on_intro_camera_race_started() -> void: +func start() -> void: + timer.start() start_frame = Engine.get_physics_frames() playing = true + car.start() set_physics_process(true) @@ -1,280 +1,21 @@ -[gd_scene load_steps=28 format=3 uid="uid://cech6c4yrmcvq"] +[gd_scene load_steps=8 format=3 uid="uid://cech6c4yrmcvq"] [ext_resource type="Script" path="res://race.gd" id="1_ckbwd"] [ext_resource type="Environment" uid="uid://biwshm46yl62v" path="res://default_env.tres" id="2_pnp7e"] [ext_resource type="PackedScene" uid="uid://bbj2agqv581cd" path="res://assets/cars/kenney_sedan/sedan.blend" id="3_cb3p0"] [ext_resource type="CameraAttributesPractical" uid="uid://nhsovwj5hjip" path="res://cam.tres" id="3_jx550"] -[ext_resource type="Material" uid="uid://bdyn312e6c3ll" path="res://assets/mats/grass.tres" id="4_i1mlf"] -[ext_resource type="Script" path="res://cam.gd" id="5_nb035"] -[ext_resource type="Curve3D" uid="uid://u2f56xx8h2re" path="res://tracks/multilap_test_curve.tres" id="5_yk721"] -[ext_resource type="Resource" uid="uid://crye0ijvmtsyb" path="res://tracks/multilap_test.tres" id="6_506fu"] [ext_resource type="PackedScene" uid="uid://ccn1nk1a0b0sa" path="res://assets/cars/kenney_sedan/sedan.tscn" id="6_nu32e"] -[ext_resource type="Theme" uid="uid://ch2uo5qd8ubx6" path="res://ui/theme.tres" id="7_6itw5"] -[ext_resource type="Script" path="res://ui/speedometer.gd" id="8_awr5n"] -[ext_resource type="Script" path="res://ui/timer.gd" id="9_dn61b"] -[ext_resource type="Script" path="res://ui/map.gd" id="10_58kgt"] +[ext_resource type="PackedScene" uid="uid://cd4a5y0hi58ks" path="res://scenes/floor.tscn" id="10_p60d8"] [ext_resource type="PackedScene" uid="uid://clw61td2wh84w" path="res://scenes/track.tscn" id="11_6q53c"] -[ext_resource type="PackedScene" uid="uid://nkh2xi7tnumc" path="res://ui/splits/splits.tscn" id="14_ge1w6"] -[ext_resource type="Texture2D" uid="uid://bfe4ytl0vjosb" path="res://ui/assets/line.png" id="14_n0r0n"] -[ext_resource type="Script" path="res://ui/intro_cam.gd" id="14_yajvg"] -[ext_resource type="Script" path="res://ui/laps.gd" id="16_mxur4"] -[ext_resource type="Texture2D" uid="uid://b3nmp7eyu0hjk" path="res://ui/assets/flag.png" id="16_rp311"] -[ext_resource type="Texture2D" uid="uid://b6ad1yrgtg6qk" path="res://ui/assets/player_indicator.png" id="17_ptq57"] -[ext_resource type="Texture2D" uid="uid://dkbrx7rpa8dvc" path="res://ui/assets/ghost.png" id="18_v7a53"] -[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_tkhh8"] - -[sub_resource type="PlaneMesh" id="PlaneMesh_ta0cd"] -material = ExtResource("4_i1mlf") -size = Vector2(5000, 5000) - -[sub_resource type="Gradient" id="Gradient_2kvil"] -offsets = PackedFloat32Array(0, 0.178744, 0.454106, 0.719807, 1) -colors = PackedColorArray(0.85098, 0.85098, 0.85098, 1, 0.942823, 0.942823, 0.942822, 1, 0.868985, 0.868985, 0.868985, 1, 0.838897, 0.838897, 0.838897, 1, 0.85098, 0.85098, 0.85098, 1) - -[sub_resource type="Animation" id="Animation_2si4r"] -length = 0.001 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("Counter:text") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 1, -"values": [" -"] -} - -[sub_resource type="Animation" id="Animation_uaks0"] -resource_name = "count_in" -length = 3.0 -step = 0.5 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("Counter:text") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0, 1, 2, 3), -"transitions": PackedFloat32Array(1, 1, 1, 1), -"update": 1, -"values": ["[center][b]3[/b][/center]", "[center][b]2[/b][/center] -", "[center][b]1[/b][/center] -", ""] -} -tracks/1/type = "value" -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/path = NodePath("Counter:theme_override_colors/default_color") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/keys = { -"times": PackedFloat32Array(0, 3), -"transitions": PackedFloat32Array(1, 1), -"update": 0, -"values": [Color(1, 0.360784, 0.227451, 1), Color(0.980392, 0.737255, 0, 1)] -} -tracks/2/type = "method" -tracks/2/imported = false -tracks/2/enabled = true -tracks/2/path = NodePath("CanvasLayer/HBoxContainer/Panel2/Timer") -tracks/2/interp = 1 -tracks/2/loop_wrap = true -tracks/2/keys = { -"times": PackedFloat32Array(3), -"transitions": PackedFloat32Array(1), -"values": [{ -"args": [], -"method": &"start" -}] -} -tracks/3/type = "method" -tracks/3/imported = false -tracks/3/enabled = true -tracks/3/path = NodePath("Counter") -tracks/3/interp = 1 -tracks/3/loop_wrap = true -tracks/3/keys = { -"times": PackedFloat32Array(), -"transitions": PackedFloat32Array(), -"values": [] -} -tracks/4/type = "method" -tracks/4/imported = false -tracks/4/enabled = true -tracks/4/path = NodePath("Camera") -tracks/4/interp = 1 -tracks/4/loop_wrap = true -tracks/4/keys = { -"times": PackedFloat32Array(3), -"transitions": PackedFloat32Array(1), -"values": [{ -"args": [], -"method": &"make_current" -}] -} - -[sub_resource type="AnimationLibrary" id="AnimationLibrary_hplnw"] -_data = { -"RESET": SubResource("Animation_2si4r"), -"count_in": SubResource("Animation_uaks0") -} - -[node name="race" type="Node3D" node_paths=PackedStringArray("track", "splits", "timer")] +[node name="race" type="Node3D"] script = ExtResource("1_ckbwd") car_scene = ExtResource("6_nu32e") ghost_scene = ExtResource("3_cb3p0") -track = NodePath("Track") -splits = NodePath("CanvasLayer/Splits") -timer = NodePath("CanvasLayer/HBoxContainer/Panel2/Timer") - -[node name="Track" parent="." instance=ExtResource("11_6q53c")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) -curve = ExtResource("5_yk721") -track = ExtResource("6_506fu") - -[node name="Camera" type="Camera3D" parent="."] -transform = Transform3D(0.226651, 0, -0.973976, 0, 1, 0, 0.973976, 0, 0.226651, -25.1963, 1.82268, -2.33777) -far = 500.0 -script = ExtResource("5_nb035") -target_distance = 9.0 -target_height = 4.0 +track_loader_scene = ExtResource("11_6q53c") [node name="Env" type="WorldEnvironment" parent="."] environment = ExtResource("2_pnp7e") camera_attributes = ExtResource("3_jx550") -[node name="Ground" type="StaticBody3D" parent="."] -metadata/_edit_lock_ = true -metadata/_edit_group_ = true - -[node name="CollisionShape" type="CollisionShape3D" parent="Ground"] -shape = SubResource("WorldBoundaryShape3D_tkhh8") - -[node name="MeshInstance" type="MeshInstance3D" parent="Ground"] -mesh = SubResource("PlaneMesh_ta0cd") - -[node name="CanvasLayer" type="CanvasLayer" parent="."] - -[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer"] -anchors_preset = 12 -anchor_top = 1.0 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_top = -105.0 -grow_horizontal = 2 -grow_vertical = 0 -theme = ExtResource("7_6itw5") -theme_override_constants/separation = 50 -alignment = 1 - -[node name="Panel" type="PanelContainer" parent="CanvasLayer/HBoxContainer"] -layout_mode = 2 - -[node name="Speedometer" type="Label" parent="CanvasLayer/HBoxContainer/Panel"] -custom_minimum_size = Vector2(0, 105) -layout_mode = 2 -size_flags_horizontal = 4 -text = "龍 0km/h" -horizontal_alignment = 1 -vertical_alignment = 1 -script = ExtResource("8_awr5n") - -[node name="Panel2" type="PanelContainer" parent="CanvasLayer/HBoxContainer"] -layout_mode = 2 - -[node name="Timer" type="Label" parent="CanvasLayer/HBoxContainer/Panel2"] -custom_minimum_size = Vector2(0, 105) -layout_mode = 2 -size_flags_horizontal = 4 -text = "祥 0:00:00" -horizontal_alignment = 1 -vertical_alignment = 1 -script = ExtResource("9_dn61b") - -[node name="MiniMap" type="Line2D" parent="CanvasLayer" node_paths=PackedStringArray("track")] -texture_repeat = 2 -width = 40.0 -default_color = Color(0.854902, 0.854902, 0.854902, 1) -gradient = SubResource("Gradient_2kvil") -texture = ExtResource("14_n0r0n") -texture_mode = 1 -antialiased = true -script = ExtResource("10_58kgt") -track = NodePath("../../Track") -player_color = Color(1, 0.388235, 0.321569, 1) -finish_indicator = ExtResource("16_rp311") -player_indicator = ExtResource("17_ptq57") -ghost_indicator = ExtResource("18_v7a53") - -[node name="Splits" parent="CanvasLayer" instance=ExtResource("14_ge1w6")] -visible = false - -[node name="Laps" type="PanelContainer" parent="CanvasLayer" node_paths=PackedStringArray("track", "label")] -anchors_preset = 2 -anchor_top = 1.0 -anchor_bottom = 1.0 -offset_left = 10.0 -offset_top = -80.0 -offset_right = 105.0 -grow_vertical = 0 -theme = ExtResource("7_6itw5") -script = ExtResource("16_mxur4") -track = NodePath("../../Track") -label = NodePath("Label") - -[node name="Label" type="Label" parent="CanvasLayer/Laps"] -layout_mode = 2 -size_flags_horizontal = 4 -theme_override_font_sizes/font_size = 50 -text = " 1/3" -horizontal_alignment = 1 -vertical_alignment = 1 - -[node name="IntroCamera" type="Camera3D" parent="." node_paths=PackedStringArray("main_cam", "track", "count_player")] -transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) -current = true -far = 500.0 -script = ExtResource("14_yajvg") -main_cam = NodePath("../Camera") -track = NodePath("../Track") -count_player = NodePath("../CountPlayer") - -[node name="Counter" type="RichTextLabel" parent="."] -custom_minimum_size = Vector2(1400, 0) -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -20.0 -offset_top = -20.0 -offset_right = 20.0 -offset_bottom = 20.0 -grow_horizontal = 2 -grow_vertical = 2 -theme_override_colors/default_color = Color(0.980392, 0.737255, 0, 1) -theme_override_colors/font_outline_color = Color(0, 0, 0, 1) -theme_override_constants/outline_size = 50 -theme_override_font_sizes/bold_font_size = 800 -bbcode_enabled = true -text = " -" -fit_content = true - -[node name="CountPlayer" type="AnimationPlayer" parent="."] -libraries = { -"": SubResource("AnimationLibrary_hplnw") -} - -[connection signal="created_car" from="." to="Camera" method="_on_race_created_car"] -[connection signal="created_car" from="." to="CanvasLayer/HBoxContainer/Panel/Speedometer" method="_on_race_created_car"] -[connection signal="created_car" from="." to="CanvasLayer/MiniMap" method="_on_race_created_car"] -[connection signal="created_car" from="." to="IntroCamera" method="_on_race_created_car"] -[connection signal="created_ghost" from="." to="CanvasLayer/MiniMap" method="_on_race_created_ghost"] -[connection signal="next_lap" from="." to="CanvasLayer/Laps" method="increment"] -[connection signal="race_started" from="IntroCamera" to="." method="_on_intro_camera_race_started"] +[node name="Ground" parent="." instance=ExtResource("10_p60d8")] diff --git a/scenes/floor.tscn b/scenes/floor.tscn new file mode 100644 index 0000000..b000e39 --- /dev/null +++ b/scenes/floor.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=3 uid="uid://cd4a5y0hi58ks"] + +[ext_resource type="Material" uid="uid://bdyn312e6c3ll" path="res://assets/mats/grass.tres" id="1_g7360"] + +[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_tkhh8"] + +[sub_resource type="PlaneMesh" id="PlaneMesh_ta0cd"] +material = ExtResource("1_g7360") +size = Vector2(5000, 5000) + +[node name="Ground" type="StaticBody3D"] +metadata/_edit_lock_ = true +metadata/_edit_group_ = true + +[node name="CollisionShape" type="CollisionShape3D" parent="."] +shape = SubResource("WorldBoundaryShape3D_tkhh8") + +[node name="MeshInstance" type="MeshInstance3D" parent="."] +mesh = SubResource("PlaneMesh_ta0cd") diff --git a/scenes/race_high.tscn b/scenes/race_high.tscn new file mode 100644 index 0000000..3c2a1a9 --- /dev/null +++ b/scenes/race_high.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=5 format=3 uid="uid://calx1puxr4eng"] + +[ext_resource type="Script" path="res://scenes/race_highlevel.gd" id="1_q8hua"] +[ext_resource type="PackedScene" uid="uid://cech6c4yrmcvq" path="res://race.tscn" id="2_q333e"] +[ext_resource type="PackedScene" uid="uid://vok7fdcyec68" path="res://ui/hud.tscn" id="3_xp6f0"] +[ext_resource type="PackedScene" uid="uid://clpo7rt0vkudy" path="res://ui/countdown.tscn" id="4_llox4"] + +[node name="race_high" type="Node"] +script = ExtResource("1_q8hua") +race_scene = ExtResource("2_q333e") +hud_scene = ExtResource("3_xp6f0") +countdown_scene = ExtResource("4_llox4") + +[node name="tester" type="ColorRect" parent="."] +custom_minimum_size = Vector2(1920, 1038) +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0, 0, 0, 1) diff --git a/scenes/race_highlevel.gd b/scenes/race_highlevel.gd new file mode 100644 index 0000000..904a00b --- /dev/null +++ b/scenes/race_highlevel.gd @@ -0,0 +1,29 @@ +extends Splitscreen + +@export var race_scene: PackedScene +@export var hud_scene: PackedScene +@export var countdown_scene: PackedScene + +var race: Race +var huds: Array[HUD] + +func _ready() -> void: + race = race_scene.instantiate() + race.initialize(Globals.playing) + add_child(race) + add_player() + super() + +# cant call it join because of overriding and stuff +func add_player() -> void: + var c_cam := CarCamera.new(race.car) + var i_cam := IntroCam.new(Globals.playing, c_cam) + var v := join() + v.viewport.add_child(c_cam) + v.viewport.add_child(i_cam) + var hud = hud_scene.instantiate() + hud.assigned.emit(race.car, race.ghost, race.timer, race.track) + v.add_child(hud) + race.split.connect(hud.splits.update) + race.next_lap.connect(hud.laps.increment) + i_cam.finished.connect(func(): var countdown := countdown_scene.instantiate(); v.add_child(countdown); countdown.finished.connect(func(): race.start())) diff --git a/scenes/track-base.gd b/scenes/track-base.gd index fdf2b7b..bffb716 100644 --- a/scenes/track-base.gd +++ b/scenes/track-base.gd @@ -111,10 +111,10 @@ func _update(): if track.laps == 1: var s: Start = make_follower(track.start_scene, track.start_location, track.start_scale, track.start_needs_collision) start_pos = s.global_position - start_rot = s.rotation + start_rot = s.global_rotation else: start_pos = finish.global_position - start_rot = finish.rotation + start_rot = finish.global_rotation start_rot = start_rot.snapped(Vector3(PI/2, PI/2, PI/2)) # loopage @@ -1,6 +1,10 @@ -[gd_scene load_steps=2 format=3 uid="uid://bvfqaoqjsxj73"] +[gd_scene load_steps=6 format=3 uid="uid://bvfqaoqjsxj73"] [ext_resource type="Theme" uid="uid://ch2uo5qd8ubx6" path="res://ui/theme.tres" id="1_gm0ws"] +[ext_resource type="Script" path="res://ui/tracks.gd" id="2_po2ce"] +[ext_resource type="Resource" uid="uid://crye0ijvmtsyb" path="res://tracks/multilap_test.tres" id="3_0yjp1"] +[ext_resource type="Resource" uid="uid://de46bcu1ivmtq" path="res://tracks/test.tres" id="4_3xqvr"] +[ext_resource type="PackedScene" uid="uid://calx1puxr4eng" path="res://scenes/race_high.tscn" id="5_m5kci"] [node name="start" type="Control"] layout_mode = 3 @@ -11,20 +15,29 @@ grow_horizontal = 2 grow_vertical = 2 theme = ExtResource("1_gm0ws") -[node name="GridContainer" type="GridContainer" parent="."] +[node name="MarginContainer" type="MarginContainer" parent="."] layout_mode = 1 -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -11.5 -offset_top = -15.5 -offset_right = 11.5 -offset_bottom = 15.5 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +theme_override_constants/margin_left = 50 +theme_override_constants/margin_top = 50 +theme_override_constants/margin_right = 50 +theme_override_constants/margin_bottom = 50 + +[node name="TabContainer" type="TabContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="play" type="VBoxContainer" parent="MarginContainer/TabContainer"] +layout_mode = 2 -[node name="Button" type="Button" parent="GridContainer"] +[node name="tracks" type="GridContainer" parent="MarginContainer/TabContainer/play"] layout_mode = 2 -text = "test" +theme_override_constants/h_separation = 15 +theme_override_constants/v_separation = 15 +columns = 5 +script = ExtResource("2_po2ce") +tracks = Array[Resource("res://classes/track.gd")]([ExtResource("3_0yjp1"), ExtResource("4_3xqvr")]) +race = ExtResource("5_m5kci") diff --git a/tracks/multilap_test.tres b/tracks/multilap_test.tres index 05ef141..8c7c586 100644 --- a/tracks/multilap_test.tres +++ b/tracks/multilap_test.tres @@ -23,7 +23,7 @@ name = "multilap test" is_loop = true offset = Vector3(0, 1, 0) laps = 3 -checkpoints = PackedFloat32Array(0.2, 0.6) +checkpoints = [0.2, 0.6] checkpoint_scene = ExtResource("1_ehf5p") checkpoint_scale = Vector3(1, 1, 1) checkpoint_needs_collision = true diff --git a/tracks/test.tres b/tracks/test.tres index d19c967..1214bfe 100644 --- a/tracks/test.tres +++ b/tracks/test.tres @@ -22,7 +22,7 @@ name = "test" is_loop = false offset = Vector3(0, 1, 0) laps = 1 -checkpoints = PackedFloat32Array(0.5) +checkpoints = [0.5] checkpoint_scene = ExtResource("1_ra7ed") checkpoint_scale = Vector3(0.4, 0.4, 0.4) checkpoint_needs_collision = true diff --git a/ui/countdown.tscn b/ui/countdown.tscn new file mode 100644 index 0000000..1ac3f00 --- /dev/null +++ b/ui/countdown.tscn @@ -0,0 +1,97 @@ +[gd_scene load_steps=5 format=3 uid="uid://clpo7rt0vkudy"] + +[sub_resource type="GDScript" id="GDScript_4shhd"] +resource_name = "countdown" +script/source = "extends CanvasLayer + +signal finished + +func finished_anim() -> void: + finished.emit() +" + +[sub_resource type="Animation" id="Animation_2si4r"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Counter:text") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [" +"] +} + +[sub_resource type="Animation" id="Animation_uaks0"] +resource_name = "count_in" +length = 3.0 +step = 0.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Counter:text") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 1, 2, 3), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 1, +"values": ["[center][b]3[/b][/center]", "[center][b]2[/b][/center] +", "[center][b]1[/b][/center] +", ""] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Counter:theme_override_colors/default_color") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Color(1, 0.360784, 0.227451, 1), Color(0.980392, 0.737255, 0, 1)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_hplnw"] +_data = { +"RESET": SubResource("Animation_2si4r"), +"count_in": SubResource("Animation_uaks0") +} + +[node name="Countdown" type="CanvasLayer"] +script = SubResource("GDScript_4shhd") + +[node name="CountPlayer" type="AnimationPlayer" parent="."] +autoplay = "count_in" +libraries = { +"": SubResource("AnimationLibrary_hplnw") +} + +[node name="Counter" type="RichTextLabel" parent="."] +custom_minimum_size = Vector2(1400, 0) +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -700.0 +offset_top = -20.0 +offset_right = 700.0 +offset_bottom = 20.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_colors/default_color = Color(1, 0.360784, 0.227451, 1) +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 50 +theme_override_font_sizes/bold_font_size = 800 +bbcode_enabled = true +text = " +" +fit_content = true + +[connection signal="animation_finished" from="CountPlayer" to="." method="finished_anim" unbinds=1] diff --git a/ui/hud.gd b/ui/hud.gd new file mode 100644 index 0000000..3dcdff5 --- /dev/null +++ b/ui/hud.gd @@ -0,0 +1,8 @@ +extends Node +class_name HUD + +signal assigned(car: Car, ghost: GhostCar, timer: GameTimer, track: TrackLoader) +signal next_lap + +@export var splits: Splits +@export var laps: LapCounter
\ No newline at end of file diff --git a/ui/hud.tscn b/ui/hud.tscn new file mode 100644 index 0000000..132a3b4 --- /dev/null +++ b/ui/hud.tscn @@ -0,0 +1,111 @@ +[gd_scene load_steps=13 format=3 uid="uid://vok7fdcyec68"] + +[ext_resource type="Theme" uid="uid://ch2uo5qd8ubx6" path="res://ui/theme.tres" id="1_ie2j2"] +[ext_resource type="Script" path="res://ui/hud.gd" id="1_sfhpc"] +[ext_resource type="Script" path="res://ui/speedometer.gd" id="2_cvi37"] +[ext_resource type="Script" path="res://ui/timer.gd" id="3_poksb"] +[ext_resource type="Texture2D" uid="uid://bfe4ytl0vjosb" path="res://ui/assets/line.png" id="4_o0swd"] +[ext_resource type="Script" path="res://ui/map.gd" id="5_blxcm"] +[ext_resource type="Texture2D" uid="uid://b3nmp7eyu0hjk" path="res://ui/assets/flag.png" id="6_ho2g6"] +[ext_resource type="Texture2D" uid="uid://b6ad1yrgtg6qk" path="res://ui/assets/player_indicator.png" id="7_wv12s"] +[ext_resource type="Texture2D" uid="uid://dkbrx7rpa8dvc" path="res://ui/assets/ghost.png" id="8_yfv7r"] +[ext_resource type="PackedScene" uid="uid://nkh2xi7tnumc" path="res://ui/splits/splits.tscn" id="9_gtkqi"] +[ext_resource type="Script" path="res://ui/laps.gd" id="10_78pxt"] + +[sub_resource type="Gradient" id="Gradient_2kvil"] +offsets = PackedFloat32Array(0, 0.178744, 0.454106, 0.719807, 1) +colors = PackedColorArray(0.85098, 0.85098, 0.85098, 1, 0.942823, 0.942823, 0.942822, 1, 0.868985, 0.868985, 0.868985, 1, 0.838897, 0.838897, 0.838897, 1, 0.85098, 0.85098, 0.85098, 1) + +[node name="HUD" type="Control" node_paths=PackedStringArray("splits", "laps")] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_sfhpc") +splits = NodePath("Splits") +laps = NodePath("Laps") + +[node name="Dashboard" type="HBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -105.0 +grow_horizontal = 2 +grow_vertical = 0 +theme = ExtResource("1_ie2j2") +theme_override_constants/separation = 50 +alignment = 1 + +[node name="Panel" type="PanelContainer" parent="Dashboard"] +layout_mode = 2 + +[node name="Speedometer" type="Label" parent="Dashboard/Panel"] +custom_minimum_size = Vector2(0, 105) +layout_mode = 2 +size_flags_horizontal = 4 +text = "龍 0km/h" +horizontal_alignment = 1 +vertical_alignment = 1 +script = ExtResource("2_cvi37") + +[node name="Panel2" type="PanelContainer" parent="Dashboard"] +layout_mode = 2 + +[node name="Timer" type="Label" parent="Dashboard/Panel2"] +custom_minimum_size = Vector2(0, 105) +layout_mode = 2 +size_flags_horizontal = 4 +text = "祥 0:00:00" +horizontal_alignment = 1 +vertical_alignment = 1 +script = ExtResource("3_poksb") + +[node name="MiniMap" type="Line2D" parent="."] +texture_repeat = 2 +width = 40.0 +default_color = Color(0.854902, 0.854902, 0.854902, 1) +gradient = SubResource("Gradient_2kvil") +texture = ExtResource("4_o0swd") +texture_mode = 1 +antialiased = true +script = ExtResource("5_blxcm") +player_color = Color(1, 0.388235, 0.321569, 1) +finish_indicator = ExtResource("6_ho2g6") +player_indicator = ExtResource("7_wv12s") +ghost_indicator = ExtResource("8_yfv7r") + +[node name="Splits" parent="." instance=ExtResource("9_gtkqi")] +visible = false +layout_mode = 1 +offset_right = 25.0 + +[node name="Laps" type="PanelContainer" parent="." node_paths=PackedStringArray("label")] +layout_mode = 1 +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_left = 10.0 +offset_top = -80.0 +offset_right = 105.0 +grow_vertical = 0 +theme = ExtResource("1_ie2j2") +script = ExtResource("10_78pxt") +label = NodePath("Label") + +[node name="Label" type="Label" parent="Laps"] +layout_mode = 2 +size_flags_horizontal = 4 +theme_override_font_sizes/font_size = 50 +text = " 1/3" +horizontal_alignment = 1 +vertical_alignment = 1 + +[connection signal="assigned" from="." to="MiniMap" method="assigned"] +[connection signal="assigned" from="." to="Laps" method="assigned"] +[connection signal="assigned" from="." to="Dashboard/Panel/Speedometer" method="car_assigned" unbinds=3] +[connection signal="assigned" from="." to="Dashboard/Panel2/Timer" method="assigned" unbinds=1] +[connection signal="next_lap" from="." to="Laps" method="increment"] diff --git a/ui/intro_cam.gd b/ui/intro_cam.gd index 9838855..2e8a8aa 100644 --- a/ui/intro_cam.gd +++ b/ui/intro_cam.gd @@ -1,29 +1,28 @@ extends Camera3D +class_name IntroCam -@export var main_cam: Camera3D -@export var track: TrackLoader -@export var count_player: AnimationPlayer +signal finished -signal race_started +var track: TrackResource +var main_cam: Camera3D -var car: Car +func _init(_track: TrackResource, _main_cam: Camera3D): + track = _track + main_cam = _main_cam func _ready() -> void: + make_current() var box := AABB() - for point in track.track.track.get_baked_points(): - box = box.expand(point) + for i in track.track.point_count: + box = box.expand(track.track.get_point_position(i)) var box_center := box.get_center() - var top_center := Vector3(box_center.x, track.track.overview_height, box_center.z) + var top_center := Vector3(box_center.x, track.overview_height, box_center.z) global_position = top_center + global_rotation_degrees.x = -90 await get_tree().create_timer(2).timeout var tween := get_tree().create_tween().set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) tween.tween_property(self, ^"global_position", main_cam.global_position, 2) tween.tween_property(self, ^"global_rotation", main_cam.global_rotation, 1) await tween.finished - count_player.play(&"count_in", -1, 2) - await count_player.animation_finished - car.ball.freeze = false - race_started.emit() - -func _on_race_created_car(_car: Car) -> void: - car = _car + finished.emit() + main_cam.make_current() @@ -1,14 +1,16 @@ extends PanelContainer +class_name LapCounter -@export var track: TrackLoader +var track: TrackLoader @export var label: Label var lap := 0 -func _ready() -> void: - visible = track.track.laps > 1 - increment() - func increment() -> void: lap += 1 label.text = " %d/%d" % [lap, track.track.laps] + +func assigned(_car, _ghost, _timer, _track: TrackLoader) -> void: + track = _track + visible = track.track.laps > 1 + increment() @@ -2,7 +2,8 @@ extends Line2D class_name MiniMap var path := Path2D.new() -@export var track: TrackLoader +var track: TrackLoader + @export var player_color: Color @export var finish_indicator: Texture @export var player_indicator: Texture @@ -37,10 +38,10 @@ func _process(_delta: float) -> void: if !follower[0].rotates: (follower[1] as Sprite2D).global_rotation = -follower[2].global_rotation.y - PI/2 -func vec(xy: float) -> Vector2: - return Vector2(xy, xy) - func mkfollower(node: Node3D, tex: Texture, mod := Color.WHITE, back := false, rotates := false): + if !is_instance_valid(node): + push_warning("invalid follower") + return var follower := PathFollow2D.new() follower.rotates = rotates path.add_child(follower) @@ -56,8 +57,7 @@ func mkfollower(node: Node3D, tex: Texture, mod := Color.WHITE, back := false, r func flatten(v: Vector3) -> Vector2: return Vector2(v.x, v.z) -func _on_race_created_car(car: Car) -> void: +func assigned(car: Car, ghost: GhostCar, _timer, _track: TrackLoader) -> void: mkfollower(car.car_mesh, player_indicator, player_color) - -func _on_race_created_ghost(ghost: GhostCar) -> void: mkfollower(ghost, ghost_indicator, Color(1,1,1,.5), true) + track = _track diff --git a/ui/speedometer.gd b/ui/speedometer.gd index c7c93da..3e6b953 100644 --- a/ui/speedometer.gd +++ b/ui/speedometer.gd @@ -3,12 +3,8 @@ extends Label @export var f_string = "龍 %dkm/h" var car: Car -func _ready() -> void: - set_process(false) - func _process(_delta: float) -> void: text = f_string % car.kph() -func _on_race_created_car(_car: Car) -> void: +func car_assigned(_car: Car) -> void: car = _car - set_process(true) diff --git a/ui/splits/splits.gd b/ui/splits/splits.gd index a446b37..8a160c6 100644 --- a/ui/splits/splits.gd +++ b/ui/splits/splits.gd @@ -1,4 +1,5 @@ extends VBoxContainer +class_name Splits @export var diff: PanelContainer @export var current: Label diff --git a/ui/timer.gd b/ui/timer.gd index 3215521..a8a5b69 100644 --- a/ui/timer.gd +++ b/ui/timer.gd @@ -1,24 +1,9 @@ extends Label -class_name GameTimer -var elapsed_time: float = 0.0 +var timer: GameTimer -func _ready() -> void: - stop() +func assigned(_car, _ghost, _timer: GameTimer) -> void: + timer = _timer -func start() -> void: - set_process(true) - -func stop() -> void: - set_process(false) - -func now() -> float: - return elapsed_time - -## format a number of seconds into m:s.ms -static func format(time: float) -> String: - return "%01d:%02d.%02d" % [time / 60, fmod(time, 60), fmod(time * 1000, 100)] - -func _process(delta: float) -> void: - elapsed_time += delta - text = "祥 %s" % GameTimer.format(elapsed_time)
\ No newline at end of file +func _process(_delta: float) -> void: + text = "祥 %s" % timer.fmt_now()
\ No newline at end of file diff --git a/ui/tracks.gd b/ui/tracks.gd new file mode 100644 index 0000000..048167a --- /dev/null +++ b/ui/tracks.gd @@ -0,0 +1,17 @@ +extends GridContainer + +@export var tracks: Array[TrackResource] +@export var race: PackedScene + +func _ready() -> void: + for track in tracks: + var button := Button.new() + add_child(button) + button.name = track.name + button.text = track.name + button.pressed.connect(track_selected.bind(track)) + +func track_selected(track: TrackResource) -> void: + print("play %s" % track.name) + Globals.playing = track + get_tree().change_scene_to_packed(race)
\ No newline at end of file |