feat(audio): drive engine tone from thrust

This commit is contained in:
Josh Creek
2026-09-01 23:22:20 +01:00
parent fcb38b3d57
commit 19ef84c3cb
5 changed files with 53 additions and 2 deletions
+41
View File
@@ -7,6 +7,7 @@ const SAMPLE_RATE := 44100
const MAX_INTENSITY := 1.0
var enabled := true
var _engine_player: AudioStreamPlayer
func bind_tree_buttons(root: Node) -> void:
@@ -47,6 +48,35 @@ func play_goal() -> void:
_play_tone(783.99, 0.30, 0.18)
func set_engine_state(thrust: float, turbo: bool) -> void:
var amount := clamp_intensity(thrust)
if not enabled or amount <= 0.01:
stop_engine()
return
if _engine_player == null or not is_instance_valid(_engine_player):
_engine_player = AudioStreamPlayer.new()
_engine_player.stream = _engine_stream()
add_child(_engine_player)
_engine_player.play()
_engine_player.pitch_scale = engine_pitch(amount, turbo)
_engine_player.volume_db = linear_to_db(engine_volume(amount, turbo))
func stop_engine() -> void:
if _engine_player != null and is_instance_valid(_engine_player):
_engine_player.stop()
static func engine_pitch(thrust: float, turbo: bool) -> float:
var amount := clamp_intensity(thrust)
return 0.75 + amount * 0.55 + (0.30 if turbo and amount > 0.01 else 0.0)
static func engine_volume(thrust: float, turbo: bool) -> float:
var amount := clamp_intensity(thrust)
return clampf(0.015 + amount * 0.045 + (0.025 if turbo and amount > 0.01 else 0.0), 0.0, 0.1)
static func clamp_intensity(value: float) -> float:
if not is_finite(value):
return 0.0
@@ -72,6 +102,17 @@ func _play_tone(frequency: float, duration: float, volume: float) -> void:
player.play()
func _engine_stream() -> AudioStreamWAV:
var stream := AudioStreamWAV.new()
stream.format = AudioStreamWAV.FORMAT_16_BITS
stream.mix_rate = SAMPLE_RATE
stream.stereo = false
stream.loop_mode = AudioStreamWAV.LOOP_FORWARD
stream.data = _tone_data(92.0, 1.0, 0.65)
stream.loop_end = SAMPLE_RATE
return stream
func _tone_data(frequency: float, duration: float, volume: float) -> PackedByteArray:
var frames := maxi(1, int(duration * SAMPLE_RATE))
var data := PackedByteArray()
+3
View File
@@ -100,6 +100,7 @@ func _connect_target() -> void:
func _exit_tree() -> void:
AudioManager.stop_engine()
if is_instance_valid(target) and target.ball_contact.is_connected(_on_target_ball_contact):
target.ball_contact.disconnect(_on_target_ball_contact)
@@ -218,6 +219,8 @@ func _smooth_look_at(point: Vector3, delta: float) -> void:
func _update_speed_feel(delta: float) -> void:
var feel_t := 1.0 - exp(-feel_smoothing * delta)
var turbo_target := 1.0 if target.is_turbo_active() else 0.0
var engine_action := target.get_current_action_copy()
AudioManager.set_engine_state(maxf(engine_action.thrust.z, 0.0), turbo_target > 0.5)
_turbo_blend = lerpf(_turbo_blend, turbo_target, feel_t)
_speed_blend = lerpf(_speed_blend, target.get_speed_ratio(), feel_t)
var target_fov := base_fov + _speed_blend * speed_fov_add + _turbo_blend * turbo_fov_kick