small racing game im working on
Diffstat (limited to 'classes/car.gd')
-rw-r--r--classes/car.gd80
1 files changed, 80 insertions, 0 deletions
diff --git a/classes/car.gd b/classes/car.gd
new file mode 100644
index 0000000..87fbab7
--- /dev/null
+++ b/classes/car.gd
@@ -0,0 +1,80 @@
+extends Node3D
+class_name Car
+
+@onready var ball := $Ball as RigidBody3D
+@onready var car_mesh := $CarMesh as Node3D
+@onready var ground_ray := $CarMesh/GroundRay as RayCast3D
+# mesh references
+@onready var right_wheel := $CarMesh/frontright as MeshInstance3D
+@onready var left_wheel := $CarMesh/frontleft as MeshInstance3D
+@onready var skid_l = $CarMesh/SkidL as GPUParticles3D
+@onready var skid_r = $CarMesh/SkidR as GPUParticles3D
+@onready var body_mesh := $CarMesh/body as MeshInstance3D
+@export var show_debug := false
+
+var acceleration := 35.0 # ai must change this for randomness
+const sphere_offset := Vector3(0, -2, .5)
+const max_steering_range := deg_to_rad(40.0)
+const turn_speed := 2.0
+const wheel_turn_speed := 0.2
+const turn_stop_limit := 0.75
+const body_tilt := 685.0
+
+var throttle := 0.0
+var _steering := 0.0
+
+func _ready():
+ $Ball/DebugMesh.visible = show_debug
+ ground_ray.add_exception(ball)
+
+func steer(to: float) -> void:
+ _steering = clamp(lerpf(_steering, -to, wheel_turn_speed), -max_steering_range, max_steering_range)
+ if is_zero_approx(_steering) or (_steering < .05 && _steering > -.05):
+ _steering = 0
+ # rotate wheels for effect
+ right_wheel.rotation.y = _steering * .75
+ left_wheel.rotation.y = _steering * .75
+
+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)
+
+func turn(delta: float) -> void:
+ if ball.linear_velocity.length() > turn_stop_limit:
+ var new_basis := car_mesh.global_transform.basis.rotated(car_mesh.global_transform.basis.y, _steering)
+ car_mesh.global_transform.basis = car_mesh.global_transform.basis.slerp(new_basis, turn_speed * delta)
+ car_mesh.global_transform = car_mesh.global_transform.orthonormalized()
+ # 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()
+ var xform := align_with_y(car_mesh.global_transform, n.normalized())
+ car_mesh.global_transform = car_mesh.global_transform.interpolate_with(xform, 10 * delta)
+
+func _physics_process(delta: float) -> void:
+ move_mesh(delta)
+
+ # if not ground_ray.is_colliding():
+ # return
+
+ # print(ball.linear_velocity.normalized().dot(-car_mesh.transform.basis.y))
+ # if throttle < 0 && :
+ # steering = -steering
+
+ # drift particles
+ var drift: bool = ball.linear_velocity.length() > 25 and abs(ball.linear_velocity.normalized().dot(-car_mesh.transform.basis.z)) > .5
+ skid_l.emitting = drift
+ skid_r.emitting = drift
+
+ turn(delta)
+ floor_mesh(delta)
+
+func align_with_y(xform: Transform3D, new_y: Vector3) -> Transform3D:
+ xform.basis.y = new_y
+ xform.basis.x = -xform.basis.z.cross(new_y)
+ xform.basis = xform.basis.orthonormalized()
+ return xform