Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ export_credentials.cfg
# Mono-specific ignores
.mono/
data_*/
mono_crash.*.json
mono_crash.*.json

.vscode/
Binary file added audio/impact.ogg
Binary file not shown.
19 changes: 19 additions & 0 deletions audio/impact.ogg.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[remap]

importer="oggvorbisstr"
type="AudioStreamOggVorbis"
uid="uid://io4pmr3lo1dy"
path="res://.godot/imported/impact.ogg-269c0252b110415bc0e0bddca8c04785.oggvorbisstr"

[deps]

source_file="res://audio/impact.ogg"
dest_files=["res://.godot/imported/impact.ogg-269c0252b110415bc0e0bddca8c04785.oggvorbisstr"]

[params]

loop=false
loop_offset=0
bpm=0
beat_count=0
bar_beats=4
8 changes: 7 additions & 1 deletion scenes/main.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
[ext_resource type="Script" uid="uid://b24bstassw26s" path="res://scripts/view.gd" id="5_0lrhn"]
[ext_resource type="AudioStream" uid="uid://2in1jtv5bh0y" path="res://audio/skid.ogg" id="5_choun"]
[ext_resource type="AudioStream" uid="uid://j6x2is8pyt8y" path="res://audio/engine.ogg" id="6_choun"]
[ext_resource type="AudioStream" uid="uid://io4pmr3lo1dy" path="res://audio/impact.ogg" id="7_eb6dy"]
[ext_resource type="MeshLibrary" uid="uid://b6myd2b7l2o2j" path="res://models/Library/mesh-library.tres" id="8_eg7gk"]
[ext_resource type="PackedScene" uid="uid://c44tfiddyjjm1" path="res://models/vehicle-truck-green.glb" id="9_cmq2j"]
[ext_resource type="PackedScene" uid="uid://c5e64mpylh1ge" path="res://models/vehicle-truck-purple.glb" id="10_p3c1o"]
Expand Down Expand Up @@ -113,6 +114,9 @@ autoplay = true
stream = ExtResource("6_choun")
autoplay = true

[node name="ImpactSound" type="AudioStreamPlayer3D" parent="Vehicle/Container"]
stream = ExtResource("7_eb6dy")

[node name="Sphere" type="RigidBody3D" parent="Vehicle"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
collision_layer = 8
Expand All @@ -121,7 +125,7 @@ physics_material_override = SubResource("PhysicsMaterial_eyo0u")
gravity_scale = 1.5
continuous_cd = true
contact_monitor = true
max_contacts_reported = 1
max_contacts_reported = 2
linear_damp = 0.1
angular_damp_mode = 1
angular_damp = 4.0
Expand Down Expand Up @@ -175,3 +179,5 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -23.7772, -0.143123, -13.5596

[node name="vehicle-truck-red" parent="." instance=ExtResource("11_wocnk")]
transform = Transform3D(-0.913034, 0, 0.407884, 0, 1, 0, -0.407884, 0, -0.913034, -1.36138, -0.148564, -23.8)

[connection signal="body_entered" from="Vehicle/Sphere" to="Vehicle" method="_on_sphere_body_entered"]
89 changes: 53 additions & 36 deletions scripts/vehicle.gd
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ extends Node3D

@onready var screech_sound: AudioStreamPlayer3D = $Container/ScreechSound
@onready var engine_sound: AudioStreamPlayer3D = $Container/EngineSound
@onready var impact_sound: AudioStreamPlayer3D = $Container/ImpactSound

var input: Vector3
var normal: Vector3
Expand All @@ -34,58 +35,66 @@ var linear_speed: float

var colliding: bool

var linear_velocity: Vector3
var prev_position: Vector3

# Functions

func _physics_process(delta):

handle_input(delta)

var direction = sign(linear_speed)
if direction == 0: direction = sign(input.z) if abs(input.z) > 0.1 else 1

var steering_grip = clamp(abs(linear_speed), 0.2, 1.0)

var target_angular = -input.x * steering_grip * 4 * direction
angular_speed = lerp(angular_speed, target_angular, delta * 4)

vehicle_model.rotate_y(angular_speed * delta)

# Ground alignment

if raycast.is_colliding():
if !colliding:
vehicle_body.position = Vector3(0, 0.1, 0) # Bounce
input.z = 0

normal = raycast.get_collision_normal()

# Orient model to colliding normal

if normal.dot(vehicle_model.global_basis.y) > 0.5:
var xform = align_with_y(vehicle_model.global_transform, normal)
vehicle_model.global_transform = vehicle_model.global_transform.interpolate_with(xform, 0.2).orthonormalized()

colliding = raycast.is_colliding()

var target_speed = input.z

if (target_speed < 0 and linear_speed > 0.01):
linear_speed = lerp(linear_speed, 0.0, delta * 8)
else:
if (target_speed < 0):
linear_speed = lerp(linear_speed, target_speed / 2, delta * 2)
else:
linear_speed = lerp(linear_speed, target_speed, delta * 6)

acceleration = lerpf(acceleration, linear_speed + (abs(sphere.angular_velocity.length() * linear_speed) / 100), delta * 1)

# Match vehicle model to physics sphere

vehicle_model.position = sphere.position - Vector3(0, 0.65, 0)
raycast.position = sphere.position


# Calculate vehicle model linear velocity

linear_velocity = (vehicle_model.position - prev_position) / delta
prev_position = vehicle_model.position

# Visual and audio effects

effect_engine(delta)
effect_body(delta)
effect_wheels(delta)
Expand All @@ -94,72 +103,80 @@ func _physics_process(delta):
# Handle input when vehicle is colliding with ground

func handle_input(delta):

if raycast.is_colliding():
input.x = Input.get_axis("left", "right")
input.z = Input.get_axis("back", "forward")

sphere.angular_velocity += vehicle_model.get_global_transform().basis.x * (linear_speed * 100) * delta

func effect_body(delta):

# Slightly tilt body based on acceleration and steering

vehicle_body.rotation.x = lerp_angle(vehicle_body.rotation.x, -(linear_speed - acceleration) / 6, delta * 10)
vehicle_body.rotation.z = lerp_angle(vehicle_body.rotation.z, -input.x / 5 * linear_speed, delta * 5)

# Change the body position so wheels don't clip through the body when tilting

vehicle_body.position = vehicle_body.position.lerp(Vector3(0, 0.2, 0), delta * 5)

func effect_wheels(delta):

# Rotate wheels based on acceleration

for wheel in [wheel_fl, wheel_fr, wheel_bl, wheel_br]:
wheel.rotation.x += acceleration

# Rotate front wheels based on steering direction

wheel_fl.rotation.y = lerp_angle(wheel_fl.rotation.y, -input.x / 1.5, delta * 10)
wheel_fr.rotation.y = lerp_angle(wheel_fr.rotation.y, -input.x / 1.5, delta * 10)

# Engine sounds

func effect_engine(delta):

var speed_factor = clamp(abs(linear_speed), 0.0, 1.0)
var throttle_factor = clamp(abs(input.z), 0.0, 1.0)

var target_volume = remap(speed_factor + (throttle_factor * 0.5), 0.0, 1.5, -15.0, -5.0)
engine_sound.volume_db = lerp(engine_sound.volume_db, target_volume, delta * 5.0)

var target_pitch = remap(speed_factor, 0.0, 1.0, 0.5, 3)
if throttle_factor > 0.1: target_pitch += 0.2

engine_sound.pitch_scale = lerp(engine_sound.pitch_scale, target_pitch, delta * 2.0)

# Show trails (and play skid sound)

func effect_trails():

var drift_intensity = abs(linear_speed - acceleration) + (abs(vehicle_body.rotation.z) * 2.0)
var should_emit = drift_intensity > 0.25

trail_left.emitting = should_emit
trail_right.emitting = should_emit

var target_volume = -80.0
if should_emit: target_volume = remap(clamp(drift_intensity, 0.25, 2.0), 0.25, 2.0, -10.0, 0.0)

screech_sound.pitch_scale = lerp(screech_sound.pitch_scale, clamp(abs(linear_speed), 1.0, 3.0), 0.1)
screech_sound.volume_db = lerp(screech_sound.volume_db, target_volume, 10.0 * get_physics_process_delta_time())

# Align vehicle with normal

func align_with_y(xform, new_y):

xform.basis.y = new_y
xform.basis.x = -xform.basis.z.cross(new_y)
xform.basis = xform.basis.orthonormalized()
return xform

# Detect collisions and play impact sound

func _on_sphere_body_entered(_body: Node) -> void:
if not impact_sound.playing:
var impact_velocity := absf(linear_velocity.dot(vehicle_body.global_basis.z))
impact_sound.volume_db = clampf(remap(impact_velocity, 0.0, 6.0, -20.0, 0.0), -20.0, 0.0)
impact_sound.play()