small racing game im working on
-rw-r--r--assets/cars/kenney_sedan/sedan.tscn6
-rw-r--r--cam.gd33
-rw-r--r--classes/car.gd15
-rw-r--r--classes/checkpoint.gd7
-rw-r--r--classes/finish.gd11
-rw-r--r--race.gd29
-rw-r--r--race.tscn174
-rw-r--r--scenes/ring_checkpoint.gd6
-rw-r--r--scenes/ring_checkpoint.tscn14
-rw-r--r--scenes/ring_finish.gd4
-rw-r--r--scenes/ring_finish.tscn11
-rw-r--r--scenes/ring_start.tscn4
-rw-r--r--scenes/track-base.gd29
-rw-r--r--scenes/track.tscn4
-rw-r--r--tracks/test.tres18
-rw-r--r--ui/intro_cam.gd27
-rw-r--r--ui/map.gd13
-rw-r--r--ui/speedometer.gd11
18 files changed, 309 insertions, 107 deletions
diff --git a/assets/cars/kenney_sedan/sedan.tscn b/assets/cars/kenney_sedan/sedan.tscn
index f7d01c9..e3643e1 100644
--- a/assets/cars/kenney_sedan/sedan.tscn
+++ b/assets/cars/kenney_sedan/sedan.tscn
@@ -1,6 +1,5 @@
-[gd_scene load_steps=21 format=3 uid="uid://ccn1nk1a0b0sa"]
+[gd_scene load_steps=20 format=3 uid="uid://ccn1nk1a0b0sa"]
-[ext_resource type="Script" path="res://classes/human_car.gd" id="1_2rc1g"]
[ext_resource type="PackedScene" uid="uid://bbj2agqv581cd" path="res://assets/cars/kenney_sedan/sedan.blend" id="1_a083g"]
[ext_resource type="Material" uid="uid://b0t01t5nxdfdp" path="res://assets/cars/skid.tres" id="3_abyal"]
[ext_resource type="SphereMesh" uid="uid://cd2plk55q0xr7" path="res://assets/cars/sphere.tres" id="4_nipof"]
@@ -295,7 +294,6 @@ radial_segments = 16
rings = 12
[node name="Sedan" type="Node3D"]
-script = ExtResource("1_2rc1g")
[node name="CarMesh" parent="." instance=ExtResource("1_a083g")]
@@ -340,10 +338,8 @@ draw_pass_1 = ExtResource("4_nipof")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
[node name="Ball" type="RigidBody3D" parent="."]
-transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0.5)
collision_layer = 2
collision_mask = 3
-axis_lock_angular_y = true
physics_material_override = SubResource("PhysicsMaterial_grep7")
linear_damp = 0.1
angular_damp = 5.0
diff --git a/cam.gd b/cam.gd
index b53ad19..88ffdb9 100644
--- a/cam.gd
+++ b/cam.gd
@@ -1,20 +1,18 @@
extends Camera3D
-@export var follow_this: Node3D
+var follow_this: Node3D
@export var target_distance = 3.0
@export var target_height = 2.0
var last_lookat
func _ready():
- last_lookat = follow_this.global_transform.origin
- if follow_this is Car:
- await follow_this.ready
- follow_this = follow_this.car_mesh
+ set_physics_process(false)
-func _physics_process(delta):
- var delta_v = global_transform.origin - follow_this.global_transform.origin
- var target_pos = global_transform.origin
+
+func target() -> Vector3:
+ var delta_v := global_position - follow_this.global_position
+ var target_pos := global_position
# ignore y
delta_v.y = 0.0
@@ -22,12 +20,21 @@ func _physics_process(delta):
if (delta_v.length() > target_distance):
delta_v = delta_v.normalized() * target_distance
delta_v.y = target_height
- target_pos = follow_this.global_transform.origin + delta_v
+ target_pos = follow_this.global_position + delta_v
else:
- target_pos.y = follow_this.global_transform.origin.y + target_height
-
- global_transform.origin = global_transform.origin.lerp(target_pos, delta * 20.0)
+ target_pos.y = follow_this.global_position.y + target_height
+ return target_pos
- last_lookat = last_lookat.lerp(follow_this.global_transform.origin, delta * 20.0)
+func _physics_process(delta):
+ global_position = global_position.lerp(target(), delta * 20.0)
+ last_lookat = last_lookat.lerp(follow_this.global_position, delta * 20.0)
look_at(last_lookat, Vector3(0.0, 1.0, 0.0))
+
+
+func _on_race_created_car(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 87fbab7..133abff 100644
--- a/classes/car.gd
+++ b/classes/car.gd
@@ -13,7 +13,7 @@ class_name Car
@export var show_debug := false
var acceleration := 35.0 # ai must change this for randomness
-const sphere_offset := Vector3(0, -2, .5)
+const sphere_offset := Vector3(0, -2.3, 0)
const max_steering_range := deg_to_rad(40.0)
const turn_speed := 2.0
const wheel_turn_speed := 0.2
@@ -37,10 +37,11 @@ func steer(to: float) -> void:
func move_mesh(delta: float) -> void:
# just lerp the y due to trimesh bouncing
- car_mesh.transform.origin.x = ball.transform.origin.x + sphere_offset.x
- car_mesh.transform.origin.z = ball.transform.origin.z + sphere_offset.z
- car_mesh.transform.origin.y = lerp(car_mesh.transform.origin.y, ball.transform.origin.y + sphere_offset.y, 1 * delta)
- ball.apply_central_force(-car_mesh.global_transform.basis.z * throttle)
+ car_mesh.global_position.x = ball.global_position.x + sphere_offset.x
+ car_mesh.global_position.z = ball.global_position.z + sphere_offset.z
+ car_mesh.global_position.y = lerp(car_mesh.global_position.y, ball.global_position.y + sphere_offset.y, 10 * delta)
+ if !ball.freeze:
+ ball.apply_central_force(-car_mesh.global_transform.basis.z * throttle)
func turn(delta: float) -> void:
if ball.linear_velocity.length() > turn_stop_limit:
@@ -50,8 +51,8 @@ func turn(delta: float) -> void:
# tilt body for effect
body_mesh.rotation.z = lerp(body_mesh.rotation.z, clampf((-_steering * .2) * ball.linear_velocity.length_squared() / body_tilt, -.4, .4), 10 * delta)
-func floor_mesh(delta: float) -> void:
- var n = ground_ray.get_collision_normal()
+func floor_mesh(delta: float) -> void:
+ var n := ground_ray.get_collision_normal()
var xform := align_with_y(car_mesh.global_transform, n.normalized())
car_mesh.global_transform = car_mesh.global_transform.interpolate_with(xform, 10 * delta)
diff --git a/classes/checkpoint.gd b/classes/checkpoint.gd
index 47844c4..c0d7fc4 100644
--- a/classes/checkpoint.gd
+++ b/classes/checkpoint.gd
@@ -1,6 +1,11 @@
extends PathFollow3D
class_name CheckPoint
-signal player_entered
+signal collected
+
+var id: int # checkpoint id
@export var needs_collision := true
+
+func enter() -> void:
+ collected.emit() \ No newline at end of file
diff --git a/classes/finish.gd b/classes/finish.gd
index a936380..d7c9eb9 100644
--- a/classes/finish.gd
+++ b/classes/finish.gd
@@ -1,2 +1,9 @@
-extends CheckPoint
-class_name Finish \ No newline at end of file
+extends PathFollow3D
+class_name Finish
+
+signal collected
+
+@export var needs_collision := true
+
+func enter() -> void:
+ collected.emit() \ No newline at end of file
diff --git a/race.gd b/race.gd
index 5c33a91..4a86e88 100644
--- a/race.gd
+++ b/race.gd
@@ -1,9 +1,28 @@
extends Node3D
-@export var car: Car
+@export var car: PackedScene
+@export var track: TrackLoader
-func _on_track_place_car(at: Vector3, rot: Vector3) -> void:
- # await car.ready
- car.ball.global_position = at + (Vector3.UP * 2)
- car.ball.global_rotation = rot
+signal created_car(car: Car)
+func _ready() -> void:
+ var c: Node3D = car.instantiate()
+ c.set_script(load("res://classes/human_car.gd"))
+ c.show_debug = true
+ add_child(c)
+ c.ball.freeze = true
+ c.visible = false
+ c.global_position = track.start_pos + Vector3.UP * 3.5
+ c.set_deferred(&"rotation", track.start_rot + Vector3.UP * PI)
+ await get_tree().process_frame
+ c.global_position = c.global_position - (c.ball.global_transform.basis.z * 2) # bump forward a teensy bit
+ c.visible = true
+ created_car.emit(c)
+ for cp in track.checkpoints:
+ cp.collected.connect(collect.bind(cp.id))
+
+func collect(cp: int) -> void:
+ print("collected cp %d" % cp)
+ collected_checkpoints.append(cp)
+
+var collected_checkpoints: PackedInt32Array = []
diff --git a/race.tscn b/race.tscn
index a536cc1..2bac7f6 100644
--- a/race.tscn
+++ b/race.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=16 format=3 uid="uid://dmkcxlevx4c7g"]
+[gd_scene load_steps=20 format=3 uid="uid://dmkcxlevx4c7g"]
[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"]
@@ -13,6 +13,7 @@
[ext_resource type="PackedScene" uid="uid://clw61td2wh84w" path="res://scenes/track.tscn" id="11_6q53c"]
[ext_resource type="Curve3D" uid="uid://cuonflkcdybj0" path="res://tracks/test_curve.tres" id="12_8yl7p"]
[ext_resource type="Resource" uid="uid://de46bcu1ivmtq" path="res://tracks/test.tres" id="13_sh6e8"]
+[ext_resource type="Script" path="res://ui/intro_cam.gd" id="14_yajvg"]
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_tkhh8"]
@@ -20,9 +21,114 @@
material = ExtResource("4_i1mlf")
size = Vector2(5000, 5000)
-[node name="race" type="Node3D" node_paths=PackedStringArray("car")]
+[sub_resource type="Animation" id="Animation_uaks0"]
+resource_name = "count_in"
+length = 1.5
+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, 0.5, 1, 1.5),
+"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, 1.5),
+"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(1.5),
+"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(1.5),
+"transitions": PackedFloat32Array(1),
+"values": [{
+"args": [],
+"method": &"make_current"
+}]
+}
+
+[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="AnimationLibrary" id="AnimationLibrary_hplnw"]
+_data = {
+"RESET": SubResource("Animation_2si4r"),
+"count_in": SubResource("Animation_uaks0")
+}
+
+[node name="race" type="Node3D" node_paths=PackedStringArray("track")]
script = ExtResource("1_ckbwd")
-car = NodePath("Sedan")
+car = ExtResource("6_nu32e")
+track = NodePath("Track")
+
+[node name="Track" parent="." instance=ExtResource("11_6q53c")]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
+curve = ExtResource("12_8yl7p")
+track = ExtResource("13_sh6e8")
+
+[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
[node name="Env" type="WorldEnvironment" parent="."]
environment = ExtResource("2_pnp7e")
@@ -38,16 +144,6 @@ shape = SubResource("WorldBoundaryShape3D_tkhh8")
[node name="MeshInstance" type="MeshInstance3D" parent="Ground"]
mesh = SubResource("PlaneMesh_ta0cd")
-[node name="Camera3D" type="Camera3D" parent="." node_paths=PackedStringArray("follow_this")]
-far = 500.0
-script = ExtResource("5_nb035")
-follow_this = NodePath("../Sedan")
-target_distance = 9.0
-target_height = 5.0
-
-[node name="Sedan" parent="." instance=ExtResource("6_nu32e")]
-transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 2, 100)
-
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer"]
@@ -65,7 +161,7 @@ alignment = 1
[node name="Panel" type="PanelContainer" parent="CanvasLayer/HBoxContainer"]
layout_mode = 2
-[node name="Speedometer" type="Label" parent="CanvasLayer/HBoxContainer/Panel" node_paths=PackedStringArray("car")]
+[node name="Speedometer" type="Label" parent="CanvasLayer/HBoxContainer/Panel"]
custom_minimum_size = Vector2(0, 105)
layout_mode = 2
size_flags_horizontal = 4
@@ -73,7 +169,6 @@ text = "龍 0km/h"
horizontal_alignment = 1
vertical_alignment = 1
script = ExtResource("8_awr5n")
-car = NodePath("../../../../Sedan")
[node name="Panel2" type="PanelContainer" parent="CanvasLayer/HBoxContainer"]
layout_mode = 2
@@ -87,19 +182,52 @@ horizontal_alignment = 1
vertical_alignment = 1
script = ExtResource("9_dn61b")
-[node name="MiniMap" type="Line2D" parent="CanvasLayer" node_paths=PackedStringArray("track", "car")]
+[node name="MiniMap" type="Line2D" parent="CanvasLayer" node_paths=PackedStringArray("track")]
position = Vector2(300, 145)
default_color = Color(0.588235, 0.588235, 0.588235, 0.537255)
joint_mode = 2
antialiased = true
script = ExtResource("10_58kgt")
track = NodePath("../../Track")
-car = NodePath("../../Sedan")
player_color = Color(1, 0.388235, 0.321569, 0.803922)
-[node name="Track" parent="." instance=ExtResource("11_6q53c")]
-transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
-curve = ExtResource("12_8yl7p")
-track = ExtResource("13_sh6e8")
-
-[connection signal="place_car" from="Track" to="." method="_on_track_place_car"]
+[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"]
diff --git a/scenes/ring_checkpoint.gd b/scenes/ring_checkpoint.gd
index 07443f4..7f67fc9 100644
--- a/scenes/ring_checkpoint.gd
+++ b/scenes/ring_checkpoint.gd
@@ -2,8 +2,4 @@ extends CheckPoint
func _ready() -> void:
if not needs_collision:
- $Ring/Collision.queue_free()
-
-func _on_player_entered(_body: Node3D) -> void:
- print("player entered!")
- player_entered.emit()
+ $Ring/Collision.queue_free() \ No newline at end of file
diff --git a/scenes/ring_checkpoint.tscn b/scenes/ring_checkpoint.tscn
index 315c8d7..eae51f3 100644
--- a/scenes/ring_checkpoint.tscn
+++ b/scenes/ring_checkpoint.tscn
@@ -1,20 +1,20 @@
[gd_scene load_steps=5 format=3 uid="uid://d4a3e1w62m3ck"]
-[ext_resource type="Script" path="res://classes/checkpoint.gd" id="1_kak2a"]
+[ext_resource type="Script" path="res://scenes/ring_checkpoint.gd" id="1_cmmpp"]
[ext_resource type="TorusMesh" uid="uid://dlbpusye3e33p" path="res://assets/meshes/checkpoint.tres" id="2_xys6y"]
-[sub_resource type="TorusMesh" id="TorusMesh_nyq70"]
+[sub_resource type="TorusMesh" id="TorusMesh_wt6vi"]
inner_radius = 25.0
outer_radius = 40.0
rings = 10
ring_segments = 4
-[sub_resource type="BoxShape3D" id="BoxShape3D_0mg7y"]
+[sub_resource type="BoxShape3D" id="BoxShape3D_2btqs"]
size = Vector3(52, 52, 3)
[node name="Checkpoint" type="PathFollow3D"]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0, 0)
-script = ExtResource("1_kak2a")
+script = ExtResource("1_cmmpp")
[node name="Ring" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0)
@@ -24,7 +24,7 @@ mesh = ExtResource("2_xys6y")
transform = Transform3D(1, 0, 0, 0, 1, -8.35187e-23, 0, -8.35187e-23, 1, 0, 0, 0)
visible = false
use_collision = true
-mesh = SubResource("TorusMesh_nyq70")
+mesh = SubResource("TorusMesh_wt6vi")
[node name="PlayerDetector" type="Area3D" parent="."]
collision_layer = 0
@@ -32,6 +32,6 @@ collision_mask = 2
monitorable = false
[node name="Area" type="CollisionShape3D" parent="PlayerDetector"]
-shape = SubResource("BoxShape3D_0mg7y")
+shape = SubResource("BoxShape3D_2btqs")
-[connection signal="body_entered" from="PlayerDetector" to="." method="_on_player_entered"]
+[connection signal="body_entered" from="PlayerDetector" to="." method="enter" flags=6 unbinds=1]
diff --git a/scenes/ring_finish.gd b/scenes/ring_finish.gd
index ce7501e..05e36aa 100644
--- a/scenes/ring_finish.gd
+++ b/scenes/ring_finish.gd
@@ -3,7 +3,3 @@ extends Finish
func _ready() -> void:
if not needs_collision:
$Ring/Collision.queue_free()
-
-func _on_player_entered(_body: Node3D) -> void:
- print("player finished!")
- player_entered.emit()
diff --git a/scenes/ring_finish.tscn b/scenes/ring_finish.tscn
index 7e9f7d0..1c3a86e 100644
--- a/scenes/ring_finish.tscn
+++ b/scenes/ring_finish.tscn
@@ -3,13 +3,13 @@
[ext_resource type="Script" path="res://scenes/ring_finish.gd" id="1_oj823"]
[ext_resource type="TorusMesh" uid="uid://bc8hyk8kfo4q1" path="res://assets/meshes/ring_finish.tres" id="2_hvrqd"]
-[sub_resource type="TorusMesh" id="TorusMesh_oms0g"]
+[sub_resource type="TorusMesh" id="TorusMesh_c1qmt"]
inner_radius = 25.0
outer_radius = 40.0
rings = 10
ring_segments = 4
-[sub_resource type="BoxShape3D" id="BoxShape3D_ue5ee"]
+[sub_resource type="BoxShape3D" id="BoxShape3D_431ml"]
size = Vector3(52, 52, 3)
[node name="RingFinish" type="PathFollow3D"]
@@ -23,12 +23,15 @@ mesh = ExtResource("2_hvrqd")
transform = Transform3D(1, 0, 0, 0, 1, -8.35187e-23, 0, -8.35187e-23, 1, 0, 0, 0)
visible = false
use_collision = true
-mesh = SubResource("TorusMesh_oms0g")
+mesh = SubResource("TorusMesh_c1qmt")
[node name="PlayerDetector" type="Area3D" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.34943, 1.90735e-06, 0.0562134)
collision_layer = 0
collision_mask = 2
monitorable = false
[node name="Area" type="CollisionShape3D" parent="PlayerDetector"]
-shape = SubResource("BoxShape3D_ue5ee")
+shape = SubResource("BoxShape3D_431ml")
+
+[connection signal="body_entered" from="PlayerDetector" to="." method="enter" flags=6 unbinds=1]
diff --git a/scenes/ring_start.tscn b/scenes/ring_start.tscn
index 0135c28..6320c32 100644
--- a/scenes/ring_start.tscn
+++ b/scenes/ring_start.tscn
@@ -3,7 +3,7 @@
[ext_resource type="TorusMesh" uid="uid://cwiqggu3nwbyh" path="res://assets/meshes/ring_start.tres" id="1_ksild"]
[ext_resource type="Script" path="res://scenes/ring_start.gd" id="1_kvj6d"]
-[sub_resource type="TorusMesh" id="TorusMesh_24cjh"]
+[sub_resource type="TorusMesh" id="TorusMesh_e4fn4"]
inner_radius = 25.0
outer_radius = 40.0
rings = 10
@@ -20,4 +20,4 @@ mesh = ExtResource("1_ksild")
transform = Transform3D(1, 0, 0, 0, 1, -8.35187e-23, 0, -8.35187e-23, 1, 0, 0, 0)
visible = false
use_collision = true
-mesh = SubResource("TorusMesh_24cjh")
+mesh = SubResource("TorusMesh_e4fn4")
diff --git a/scenes/track-base.gd b/scenes/track-base.gd
index ab034e8..ea2f40d 100644
--- a/scenes/track-base.gd
+++ b/scenes/track-base.gd
@@ -23,13 +23,14 @@ class_name TrackLoader
@onready var collision := $CollisionShape as CSGPolygon3D
@onready var sun := $Sun as DirectionalLight3D
-signal place_car(at: Vector3, rot: Vector3)
+var checkpoints: Array[CheckPoint]
+var start_rot: Vector3
+var start_pos: Vector3
var is_dirty := true
func vec(x := 0.0, y := 0.0) -> Vector2:
return Vector2(x, y)
-
func _update():
if !is_dirty or !track or !track.track:
# curve = null # editor freezes with this, idk why
@@ -100,18 +101,20 @@ func _update():
if child is PathFollow3D:
child.queue_free()
- for cp in track.checkpoints:
- var _c: CheckPoint = make_follower(track.checkpoint_scene, cp, track.checkpoint_scale, track.checkpoint_needs_collision)
+ for i in len(track.checkpoints):
+ var c: CheckPoint = make_follower(track.checkpoint_scene, track.checkpoints[i], track.checkpoint_scale, track.checkpoint_needs_collision)
+ checkpoints.append(c)
+ if not Engine.is_editor_hint(): # godot tools are wierd
+ c.id = i
var f: Finish = make_follower(track.finish_scene, track.finish_location, track.finish_scale, track.finish_needs_collision)
- var start_position := f.global_position
- var start_rot := f.global_rotation
+ start_pos = f.global_position
+ start_rot = f.rotation
if track.laps == 0:
var s: Start = make_follower(track.start_scene, track.start_location, track.start_scale, track.start_needs_collision)
- start_position = s.global_position
- start_rot = s.global_rotation
- if not Engine.is_editor_hint():
- place_car.emit(start_position, start_rot)
+ start_pos = s.global_position
+ start_rot = s.rotation
+ start_rot = start_rot.snapped(Vector3(PI/2, PI/2, PI/2))
# loopage
rail_l.path_joined = track.is_loop
@@ -123,16 +126,16 @@ func _update():
is_dirty = false
func _ready():
- call_deferred("_update")
+ _update()
func _on_curve_changed() -> void:
is_dirty = true
call_deferred("_update")
-func make_follower(scene: PackedScene, ratio: float, scl: Vector3, collision: bool) -> PathFollow3D:
+func make_follower(scene: PackedScene, ratio: float, scl: Vector3, collide: bool) -> PathFollow3D:
var follower: PathFollow3D = scene.instantiate()
+ follower.needs_collision = collide
add_child(follower)
follower.scale = scl
- follower.needs_collision = collision
follower.progress_ratio = ratio # ratio set must be after add_child()
return follower \ No newline at end of file
diff --git a/scenes/track.tscn b/scenes/track.tscn
index 5f5ace8..074ce0b 100644
--- a/scenes/track.tscn
+++ b/scenes/track.tscn
@@ -32,7 +32,7 @@ mode = 2
path_node = NodePath("..")
path_interval_type = 0
path_interval = 1.0
-path_simplify_angle = 10.0
+path_simplify_angle = 3.0
path_rotation = 2
path_local = false
path_continuous_u = true
@@ -72,7 +72,7 @@ mode = 2
path_node = NodePath("..")
path_interval_type = 0
path_interval = 1.0
-path_simplify_angle = 5.0
+path_simplify_angle = 3.0
path_rotation = 2
path_local = false
path_continuous_u = true
diff --git a/tracks/test.tres b/tracks/test.tres
index f4ca576..2f1ff99 100644
--- a/tracks/test.tres
+++ b/tracks/test.tres
@@ -8,10 +8,10 @@
[resource]
script = ExtResource("3_o0ql2")
-track_width = 17.0
+track_width = 15.0
rail_distance = 3.0
-lower_support_width = 15.0
-support_height = 8.0
+lower_support_width = 23.0
+support_height = 12.0
track = ExtResource("5_35ahq")
left_barrier = true
right_barrier = true
@@ -22,13 +22,13 @@ offset = Vector3(0, 1, 0)
laps = 0
checkpoints = PackedFloat32Array(0.5)
checkpoint_scene = ExtResource("1_ra7ed")
-checkpoint_scale = Vector3(0.3, 0.3, 0.3)
-checkpoint_needs_collision = false
+checkpoint_scale = Vector3(0.4, 0.4, 0.4)
+checkpoint_needs_collision = true
finish_location = 1.0
finish_scene = ExtResource("2_e22em")
-finish_scale = Vector3(0.3, 0.3, 0.3)
-finish_needs_collision = false
+finish_scale = Vector3(0.4, 0.4, 0.4)
+finish_needs_collision = true
start_location = 0.0
start_scene = ExtResource("4_8biam")
-start_scale = Vector3(0.3, 0.3, 0.3)
-start_needs_collision = false
+start_scale = Vector3(0.4, 0.4, 0.4)
+start_needs_collision = true
diff --git a/ui/intro_cam.gd b/ui/intro_cam.gd
new file mode 100644
index 0000000..00c2afe
--- /dev/null
+++ b/ui/intro_cam.gd
@@ -0,0 +1,27 @@
+extends Camera3D
+
+@export var main_cam: Camera3D
+@export var track: TrackLoader
+@export var count_player: AnimationPlayer
+
+var car: Car
+
+func _ready() -> void:
+ var box := AABB()
+ for point in track.track.track.get_baked_points():
+ box = box.expand(point)
+ box = box.grow(200)
+ var box_center := box.get_center()
+ var top_center := Vector3(box_center.x, -box.position.y, box_center.z)
+ global_position = top_center
+ 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")
+ await count_player.animation_finished
+ car.ball.freeze = false
+
+func _on_race_created_car(_car: Car) -> void:
+ car = _car
diff --git a/ui/map.gd b/ui/map.gd
index 0469d14..9ff8a79 100644
--- a/ui/map.gd
+++ b/ui/map.gd
@@ -1,10 +1,12 @@
extends Line2D
+class_name MiniMap
+var car: Node3D
@export var track: TrackLoader
-@export var car: Node3D
@export var player_color: Color
func _ready() -> void:
+ set_process(false)
clear_points()
width = track.track.track_width
if !track.track.is_loop:
@@ -14,13 +16,18 @@ func _ready() -> void:
var p := flatten(point_3d)
add_point(p)
-
func _process(_delta: float) -> void:
queue_redraw()
func _draw() -> void:
- var point := flatten(track.curve.get_closest_point(car.ball.global_position))
+ if !car: return
+ var point := flatten(track.curve.get_closest_point(car.global_position))
draw_circle(point, width / 2, player_color)
func flatten(vec: Vector3) -> Vector2:
return Vector2(vec.x, vec.z)
+
+func _on_race_created_car(_car) -> void:
+ car = _car.ball
+ set_process(true)
+
diff --git a/ui/speedometer.gd b/ui/speedometer.gd
index 39ec8ca..c9eb0c9 100644
--- a/ui/speedometer.gd
+++ b/ui/speedometer.gd
@@ -1,7 +1,14 @@
extends Label
@export var f_string = "龍 %dkm/h"
-@export var car: Node3D
+var car: Node3D
+
+func _ready() -> void:
+ set_process(false)
func _process(_delta: float) -> void:
- text = f_string % (car.ball.linear_velocity.length_squared() / 12)
+ text = f_string % (car.linear_velocity.length_squared() / 12)
+
+func _on_race_created_car(_car: Car) -> void:
+ car = _car.ball
+ set_process(true)