small racing game im working on
saved trackdata
found out non deterministic physics, panicing sort of
bendn 2023-01-29
parent c21aeb0 · commit 76f709b
-rw-r--r--.gitignore1
-rw-r--r--classes/track.gd2
-rw-r--r--classes/trackdata.gd41
-rw-r--r--godot.lock7
-rw-r--r--godot.package2
-rw-r--r--race.gd56
-rw-r--r--race.tscn3
-rw-r--r--tracks/test.tres1
-rw-r--r--ui/intro_cam.gd3
-rw-r--r--ui/splits/difference.gd4
-rw-r--r--ui/timer.gd3
11 files changed, 105 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index 67f574c..d59960c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.godot/
movie.*
*.blend1
+addons/
diff --git a/classes/track.gd b/classes/track.gd
index 956fe39..c07ae6d 100644
--- a/classes/track.gd
+++ b/classes/track.gd
@@ -22,6 +22,8 @@ class_name TrackResource
## Sun y rotation ( its a game, the sun rotates around us )
@export_range(-360, 360) var sun_y := 0
@export_group("", "")
+## The name of this track
+@export var name: String = ""
## Does the track loop around?
@export var is_loop := true
## Offset the entire track
diff --git a/classes/trackdata.gd b/classes/trackdata.gd
new file mode 100644
index 0000000..d516097
--- /dev/null
+++ b/classes/trackdata.gd
@@ -0,0 +1,41 @@
+class_name TrackSaveableData
+extends RefCounted
+
+const SaveLoad := preload("res://addons/@bendn/remap/private/SaveLoadUtils.gd")
+
+var time: float
+var checkpoints: PackedFloat32Array
+var positional := {
+ origins = PackedVector3Array(),
+ rotations = PackedVector3Array()
+}
+
+func data() -> Dictionary:
+ return ({time = time, checkpoints = checkpoints, positional = positional})
+
+func _init(num_checkpoints: int) -> void:
+ checkpoints.resize(num_checkpoints)
+ checkpoints.fill(-1)
+
+func collect(cp: int, now: float) -> void:
+ if cp == -1: # fin
+ time = now
+ else:
+ checkpoints[cp] = now
+
+func snapshot(obj: Node3D) -> void:
+ positional.origins.append(obj.global_position)
+ positional.rotations.append(obj.global_rotation)
+
+static func from_d(d: Dictionary) -> TrackSaveableData:
+ var obj := TrackSaveableData.new(0)
+ obj.checkpoints = d.get("checkpoints", [])
+ obj.time = d.get("time", -1)
+ obj.positional = d.get("positional", {origins = null, rotations = null})
+ return obj
+
+static func _load(path: String) -> TrackSaveableData:
+ var res := SaveLoad.load_file(path)
+ if res.is_empty():
+ return null
+ return TrackSaveableData.from_d(res)
diff --git a/godot.lock b/godot.lock
new file mode 100644
index 0000000..dbc3f12
--- /dev/null
+++ b/godot.lock
@@ -0,0 +1,7 @@
+[
+ {
+ "name": "@bendn/remap",
+ "version": "5.0.6",
+ "integrity": "sha512-lfB0Vx/fmXhnrTttiG+sr33EFAlAEopDq9lX2bn3z+pp3dzSuMtTaRwbkUN8ndbuwfPa8Dm+NghUX2s3wHQFLQ=="
+ }
+] \ No newline at end of file
diff --git a/godot.package b/godot.package
new file mode 100644
index 0000000..c9a13a2
--- /dev/null
+++ b/godot.package
@@ -0,0 +1,2 @@
+[packages]
+"@bendn/remap" = '5.0.6'
diff --git a/race.gd b/race.gd
index bae0000..d7750a2 100644
--- a/race.gd
+++ b/race.gd
@@ -1,36 +1,58 @@
extends Node3D
-@export var car: PackedScene
+@export var car_scene: PackedScene
@export var track: TrackLoader
@export var splits: Control
@export var timer: Control
+@onready var data := TrackSaveableData.new(track.checkpoints.size())
+@onready var best_time_data := TrackSaveableData._load(saves % track.track.name)
+var car: Node3D
+var start_frame: int
+
+const SaveLoad := preload("res://addons/@bendn/remap/private/SaveLoadUtils.gd")
+const saves := "user://%s.trackdata"
signal created_car(car: Car)
+signal finished
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)
+ car = car_scene.instantiate()
+ car.set_script(load("res://classes/human_car.gd"))
+ 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
- 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)
+ car.global_position = car.global_position - (car.ball.global_transform.basis.z * 2) # bump forward a teensy bit
+ car.visible = true
+ created_car.emit(car)
for i in len(track.checkpoints):
track.checkpoints[i].collected.connect(collect.bind(i))
track.finish.collected.connect(
func passed_finish() -> void:
- if track.checkpoints.size() == len(collected_checkpoints):
- collect(-1)
+ for t in data.checkpoints: # no any() function on packedfloat32
+ if t < 0:
+ return
+ collect(-1)
+ finished.emit()
+ if not best_time_data or data.time < best_time_data.time:
+ SaveLoad.save(saves % track.track.name, data.data())
+ best_time_data = data
+ data = TrackSaveableData.new(track.checkpoints.size())
)
+func _physics_process(_delta: float) -> void:
+ data.snapshot(car.car_mesh)
+
+
func collect(cp: int) -> void:
- splits.update(timer.elapsed_time, 10)
- collected_checkpoints.append(cp)
+ var time := best_time_data.checkpoints[cp] if best_time_data else -1.0
+ time = best_time_data.time if cp == -1 and time != -1.0 else time
+ splits.update(timer.now(), time)
+ data.collect(cp, timer.now())
+
-var collected_checkpoints: PackedInt32Array = []
+func _on_intro_camera_race_started() -> void:
+ start_frame = Engine.get_physics_frames()
diff --git a/race.tscn b/race.tscn
index 6fb7f56..0839687 100644
--- a/race.tscn
+++ b/race.tscn
@@ -116,7 +116,7 @@ _data = {
[node name="race" type="Node3D" node_paths=PackedStringArray("track", "splits", "timer")]
script = ExtResource("1_ckbwd")
-car = ExtResource("6_nu32e")
+car_scene = ExtResource("6_nu32e")
track = NodePath("Track")
splits = NodePath("CanvasLayer/Splits")
timer = NodePath("CanvasLayer/HBoxContainer/Panel2/Timer")
@@ -237,3 +237,4 @@ libraries = {
[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="race_started" from="IntroCamera" to="." method="_on_intro_camera_race_started"]
diff --git a/tracks/test.tres b/tracks/test.tres
index 2f1ff99..504ef4b 100644
--- a/tracks/test.tres
+++ b/tracks/test.tres
@@ -17,6 +17,7 @@ left_barrier = true
right_barrier = true
sun_x = -90
sun_y = 0
+name = "test"
is_loop = false
offset = Vector3(0, 1, 0)
laps = 0
diff --git a/ui/intro_cam.gd b/ui/intro_cam.gd
index e1c3e60..26088d6 100644
--- a/ui/intro_cam.gd
+++ b/ui/intro_cam.gd
@@ -4,6 +4,8 @@ extends Camera3D
@export var track: TrackLoader
@export var count_player: AnimationPlayer
+signal race_started
+
var car: Car
func _ready() -> void:
@@ -22,6 +24,7 @@ func _ready() -> void:
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
diff --git a/ui/splits/difference.gd b/ui/splits/difference.gd
index 8d81ff3..ee5c910 100644
--- a/ui/splits/difference.gd
+++ b/ui/splits/difference.gd
@@ -8,6 +8,10 @@ extends PanelContainer
enum Change { GAIN, LOSS, EQUAL }
func update(time: float, prev_time: float) -> void:
+ if prev_time < 0: # no time set
+ hide()
+ else:
+ show() # shouldnt be needed but just to be carefull
var change := diff(time, prev_time)
style(change)
match change:
diff --git a/ui/timer.gd b/ui/timer.gd
index 0895ecc..3215521 100644
--- a/ui/timer.gd
+++ b/ui/timer.gd
@@ -12,6 +12,9 @@ func start() -> void:
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)]