small racing game im working on
-rw-r--r--classes/ghost.gd11
-rw-r--r--classes/human_car.gd6
-rw-r--r--classes/trackdata.gd52
-rw-r--r--race.gd35
-rw-r--r--race.tscn4
5 files changed, 81 insertions, 27 deletions
diff --git a/classes/ghost.gd b/classes/ghost.gd
new file mode 100644
index 0000000..bfb13af
--- /dev/null
+++ b/classes/ghost.gd
@@ -0,0 +1,11 @@
+extends Node3D
+class_name GhostCar
+
+@onready var right_wheel := $frontright as MeshInstance3D
+@onready var left_wheel := $frontleft as MeshInstance3D
+
+func update(_origin: Vector3, _rotation: Vector3, steering: float) -> void:
+ right_wheel.rotation.y = steering * .75
+ left_wheel.rotation.y = steering * .75
+ global_rotation = _rotation
+ global_position = _origin
diff --git a/classes/human_car.gd b/classes/human_car.gd
index 989339d..2d0f491 100644
--- a/classes/human_car.gd
+++ b/classes/human_car.gd
@@ -1,6 +1,12 @@
class_name HumanCar
extends Car
+static func attach(to: PackedScene) -> HumanCar:
+ var car := to.instantiate()
+ car.set_script(load("res://classes/human_car.gd"))
+ return car
+
+
func _physics_process(delta: float) -> void:
throttle = 0
throttle -= Input.get_axis("accel", "brake")
diff --git a/classes/trackdata.gd b/classes/trackdata.gd
index d516097..e8a3914 100644
--- a/classes/trackdata.gd
+++ b/classes/trackdata.gd
@@ -6,36 +6,46 @@ const SaveLoad := preload("res://addons/@bendn/remap/private/SaveLoadUtils.gd")
var time: float
var checkpoints: PackedFloat32Array
var positional := {
- origins = PackedVector3Array(),
- rotations = PackedVector3Array()
+ origins = PackedVector3Array(),
+ rotations = PackedVector3Array(),
+ steering = PackedFloat32Array(),
+ snaps = 0,
}
func data() -> Dictionary:
- return ({time = time, checkpoints = checkpoints, positional = positional})
+ return ({time = time, checkpoints = checkpoints, positional = positional})
func _init(num_checkpoints: int) -> void:
- checkpoints.resize(num_checkpoints)
- checkpoints.fill(-1)
+ checkpoints.resize(num_checkpoints)
+ checkpoints.fill(-1)
func collect(cp: int, now: float) -> void:
- if cp == -1: # fin
- time = now
- else:
- checkpoints[cp] = now
+ 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)
+func snapshot(obj: Car) -> void:
+ positional.origins.append(obj.car_mesh.global_position)
+ positional.rotations.append(obj.car_mesh.global_rotation)
+ positional.steering.append(obj._steering)
+ positional.snaps += 1
+
+func loadshot(frame: int) -> Array:
+ return [positional.origins[frame], positional.rotations[frame], positional.steering[frame]]
+
+func snaps() -> int:
+ return positional.snaps
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
+ var obj := TrackSaveableData.new(0)
+ obj.checkpoints = d.get("checkpoints", [])
+ obj.time = d.get("time", -1)
+ obj.positional = d.get("positional", {origins = [], rotations = [], steering = [], snaps = 0})
+ 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)
+ var res := SaveLoad.load_file(path)
+ if res.is_empty():
+ return null
+ return TrackSaveableData.from_d(res)
diff --git a/race.gd b/race.gd
index d7750a2..691cf63 100644
--- a/race.gd
+++ b/race.gd
@@ -1,12 +1,14 @@
extends Node3D
@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())
@onready var best_time_data := TrackSaveableData._load(saves % track.track.name)
-var car: Node3D
+var car: Car
+var ghost: GhostCar
var start_frame: int
const SaveLoad := preload("res://addons/@bendn/remap/private/SaveLoadUtils.gd")
@@ -15,9 +17,20 @@ const saves := "user://%s.trackdata"
signal created_car(car: Car)
signal finished
+func mkghost() -> void:
+ var g: Node3D = ghost_scene.instantiate()
+ g.set_script(load("res://classes/ghost.gd"))
+ ghost = g
+ add_child(ghost)
+ ghost.global_position = best_time_data.loadshot(0)[0]
+ ghost.global_rotation = best_time_data.loadshot(0)[1]
+ print("ghost created")
+
func _ready() -> void:
- car = car_scene.instantiate()
- car.set_script(load("res://classes/human_car.gd"))
+ set_physics_process(false)
+ if best_time_data:
+ mkghost()
+ car = HumanCar.attach(car_scene)
add_child(car)
car.ball.freeze = true
car.visible = false
@@ -27,6 +40,7 @@ func _ready() -> void:
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)
+ print("car created")
for i in len(track.checkpoints):
track.checkpoints[i].collected.connect(collect.bind(i))
@@ -37,14 +51,24 @@ func _ready() -> void:
return
collect(-1)
finished.emit()
+ 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
+ # best_time_data = data # this messes with the ghost, and doesnt matter yet anyways (until i can reset)
data = TrackSaveableData.new(track.checkpoints.size())
)
func _physics_process(_delta: float) -> void:
- data.snapshot(car.car_mesh)
+ data.snapshot(car)
+ if ghost:
+ if best_time_data.snaps() - 1 < Engine.get_physics_frames() - start_frame:
+ print("ran out of snaps, removing ghost")
+ ghost.queue_free()
+ ghost = null
+ return
+ var shot := best_time_data.loadshot(Engine.get_physics_frames() - start_frame)
+ ghost.update(shot[0], shot[1], shot[2])
func collect(cp: int) -> void:
@@ -56,3 +80,4 @@ func collect(cp: int) -> void:
func _on_intro_camera_race_started() -> void:
start_frame = Engine.get_physics_frames()
+ set_physics_process(true)
diff --git a/race.tscn b/race.tscn
index 0839687..58f7783 100644
--- a/race.tscn
+++ b/race.tscn
@@ -1,7 +1,8 @@
-[gd_scene load_steps=21 format=3 uid="uid://dmkcxlevx4c7g"]
+[gd_scene load_steps=22 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"]
+[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"]
@@ -117,6 +118,7 @@ _data = {
[node name="race" type="Node3D" node_paths=PackedStringArray("track", "splits", "timer")]
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")