diff --git a/.gitignore b/.gitignore index 40ec496..7b7ea92 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,6 @@ export_credentials.cfg # Mono-specific ignores .mono/ data_*/ -mono_crash.*.json \ No newline at end of file +mono_crash.*.json + +.vscode/ diff --git a/audio/impact.ogg b/audio/impact.ogg new file mode 100644 index 0000000..38e9fee Binary files /dev/null and b/audio/impact.ogg differ diff --git a/audio/impact.ogg.import b/audio/impact.ogg.import new file mode 100644 index 0000000..b3f04d0 --- /dev/null +++ b/audio/impact.ogg.import @@ -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 diff --git a/scenes/main.tscn b/scenes/main.tscn index 561fe55..ddf6e04 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -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"] @@ -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 @@ -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 @@ -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"] diff --git a/scripts/vehicle.gd b/scripts/vehicle.gd index bdb7c82..b6f54b4 100644 --- a/scripts/vehicle.gd +++ b/scripts/vehicle.gd @@ -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 @@ -34,41 +35,44 @@ 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: @@ -76,16 +80,21 @@ func _physics_process(delta): 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) @@ -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()