small racing game im working on
| -rw-r--r-- | classes/ghost.gd | 11 | ||||
| -rw-r--r-- | classes/human_car.gd | 6 | ||||
| -rw-r--r-- | classes/trackdata.gd | 52 | ||||
| -rw-r--r-- | race.gd | 35 | ||||
| -rw-r--r-- | race.tscn | 4 |
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) @@ -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) @@ -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") |