2021-11-18 23:08:21 +00:00
|
|
|
class_name BuggedVehicle
|
2021-11-05 22:11:26 +00:00
|
|
|
extends VehicleBody
|
|
|
|
|
2021-11-14 22:07:54 +00:00
|
|
|
signal speed_updated(speed_kph, speed_percent)
|
|
|
|
signal rpm_updated(rpm, rpm_percent)
|
2021-11-13 22:55:18 +00:00
|
|
|
signal gear_updated(gear)
|
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
export(float) var MAX_STEER_ANGLE = 25
|
|
|
|
export(float) var SPEED_STEER_ANGLE = 10
|
|
|
|
export(float) var MAX_STEER_SPEED = 100.0
|
|
|
|
export(float) var MAX_STEER_INPUT = 80.0
|
2021-11-05 22:11:26 +00:00
|
|
|
|
2021-11-07 00:47:56 +00:00
|
|
|
onready var max_steer_angle_rad: float = deg2rad(MAX_STEER_ANGLE)
|
|
|
|
onready var speed_steer_angle_rad: float = deg2rad(SPEED_STEER_ANGLE)
|
|
|
|
onready var max_steer_input_rad: float = deg2rad(MAX_STEER_INPUT)
|
2021-11-18 23:08:21 +00:00
|
|
|
export(Curve) var steer_curve = null
|
|
|
|
|
|
|
|
export(float) var MAX_ENGINE_FORCE = 85.0
|
|
|
|
export(float) var MAX_BRAKE_FORCE = 50.0
|
|
|
|
export(float) var THROTTLE_POWER = 6000.0
|
|
|
|
export(float) var MAX_RPM_LOSS_PS = 3000.0
|
|
|
|
export(float) var BASE_ENGINE_PITCH = 0.5
|
|
|
|
export(float) var EXPECTED_MAX_SPEED = 200
|
|
|
|
|
|
|
|
export(Array) var gear_ratios = [3.4, 2.5, 2.0, 1.5, 1.25]
|
|
|
|
export(float) var reverse_ratio = -3
|
|
|
|
export(float) var final_drive = 3.45
|
|
|
|
export(float) var max_rpm = 3500
|
|
|
|
export(float) var min_rpm = 900
|
|
|
|
export(float) var gear_switch_time = 0.2
|
|
|
|
export(Curve) var power_curve = null
|
|
|
|
export(Curve) var sound_curve = null
|
2021-11-05 22:11:26 +00:00
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
var clutch_position: float = 0.0
|
|
|
|
var rpm = 0
|
|
|
|
var gear = 1
|
|
|
|
|
|
|
|
var gear_timer = 0
|
|
|
|
|
|
|
|
onready var frwheel: VehicleWheel = $front_right
|
|
|
|
onready var flwheel: VehicleWheel = $front_left
|
|
|
|
onready var rrwheel: VehicleWheel = $rear_right
|
|
|
|
onready var rlwheel: VehicleWheel = $rear_left
|
2021-11-13 21:22:07 +00:00
|
|
|
onready var frsmoke: TireSmoke = $fr_tire_smoke
|
|
|
|
onready var flsmoke: TireSmoke = $fl_tire_smoke
|
|
|
|
onready var rrsmoke: TireSmoke = $rr_tire_smoke
|
|
|
|
onready var rlsmoke: TireSmoke = $rl_tire_smoke
|
2021-11-07 00:33:24 +00:00
|
|
|
|
2021-11-08 18:53:23 +00:00
|
|
|
onready var engine_sound_player: AudioStreamPlayer3D = $engine_sound_player
|
|
|
|
onready var engine_sound_playback: AudioStreamPlayback = $engine_sound_player.get_stream_playback()
|
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
var traction_wheels: Array
|
2021-11-18 23:08:21 +00:00
|
|
|
var reset_transform: Transform = Transform.IDENTITY
|
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
|
|
|
|
func _ready():
|
|
|
|
for wheel in [frwheel, flwheel, rrwheel, rlwheel]:
|
|
|
|
if wheel.use_as_traction:
|
|
|
|
traction_wheels.append(wheel)
|
2021-11-05 22:11:26 +00:00
|
|
|
|
2021-11-08 18:53:23 +00:00
|
|
|
_generate_engine_sound(0)
|
|
|
|
engine_sound_player.play()
|
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
func _integrate_forces(state: PhysicsDirectBodyState) -> void:
|
|
|
|
if reset_transform != Transform.IDENTITY:
|
|
|
|
state.set_transform(reset_transform)
|
|
|
|
reset_transform = Transform.IDENTITY
|
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
func _get_gear_ratio():
|
|
|
|
if gear == 0:
|
|
|
|
return 0
|
|
|
|
elif gear == -1:
|
|
|
|
return reverse_ratio
|
2021-11-05 22:11:26 +00:00
|
|
|
else:
|
2021-11-07 00:33:24 +00:00
|
|
|
return gear_ratios[gear - 1]
|
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
func _handle_gear_switch(delta: float):
|
|
|
|
if gear_timer > 0:
|
|
|
|
gear_timer = max(0, gear_timer - delta)
|
2021-11-18 19:46:16 +00:00
|
|
|
if clutch_position > 0.8:
|
2021-11-07 00:33:24 +00:00
|
|
|
if Input.is_action_just_pressed("gear_up"):
|
|
|
|
if gear + 1 <= gear_ratios.size():
|
|
|
|
gear += 1
|
|
|
|
gear_timer = gear_switch_time * (2 - clutch_position)
|
2021-11-13 22:55:18 +00:00
|
|
|
emit_signal("gear_updated", gear)
|
2021-11-07 00:33:24 +00:00
|
|
|
if Input.is_action_just_pressed("gear_down"):
|
|
|
|
if gear - 1 >= -1:
|
|
|
|
gear -= 1
|
|
|
|
gear_timer = gear_switch_time * (2 - clutch_position)
|
2021-11-13 22:55:18 +00:00
|
|
|
emit_signal("gear_updated", gear)
|
2021-11-07 00:33:24 +00:00
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
func _has_traction():
|
|
|
|
for wheel in traction_wheels:
|
|
|
|
if wheel.is_in_contact():
|
|
|
|
return true
|
|
|
|
return false
|
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
|
2021-11-13 21:22:07 +00:00
|
|
|
func _update_wheels_smoke():
|
2021-11-18 23:08:21 +00:00
|
|
|
for wheelnsmoke in [
|
|
|
|
[frwheel, frsmoke], [flwheel, flsmoke], [rrwheel, rrsmoke], [rlwheel, rlsmoke]
|
|
|
|
]:
|
2021-11-13 21:22:07 +00:00
|
|
|
wheelnsmoke[1].update(wheelnsmoke[0].get_skidinfo())
|
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
func _lerp_rpm(from, to, delta, factor):
|
|
|
|
var new_val = lerp(from, to, factor)
|
|
|
|
if abs(from - new_val) > MAX_RPM_LOSS_PS * delta:
|
2021-11-18 23:08:21 +00:00
|
|
|
var new_factor = inverse_lerp(
|
|
|
|
from, to, from - sign(from - new_val) * MAX_RPM_LOSS_PS * delta
|
|
|
|
)
|
2021-11-07 00:33:24 +00:00
|
|
|
new_val = lerp(from, to, new_factor)
|
|
|
|
return new_val
|
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
func _physics_process(delta: float):
|
2021-11-13 21:22:07 +00:00
|
|
|
_update_wheels_smoke()
|
2021-11-07 00:33:24 +00:00
|
|
|
clutch_position = Input.get_action_strength("clutch")
|
|
|
|
_handle_gear_switch(delta)
|
|
|
|
var throttle = Input.get_action_strength("throttle")
|
2021-11-13 20:17:52 +00:00
|
|
|
if gear_timer > 0:
|
|
|
|
clutch_position = 1
|
|
|
|
throttle = 0
|
2021-11-07 00:33:24 +00:00
|
|
|
|
|
|
|
var wheel_rpm = traction_wheels[0].get_rpm()
|
|
|
|
var final_rpm = abs(wheel_rpm) * final_drive
|
|
|
|
var transmission_rpm = final_rpm * abs(_get_gear_ratio())
|
|
|
|
|
|
|
|
if gear != 0:
|
2021-11-13 11:53:59 +00:00
|
|
|
rpm = lerp(rpm, transmission_rpm, delta * 10 * (1 - clutch_position))
|
2021-11-08 18:53:23 +00:00
|
|
|
rpm = _lerp_rpm(rpm, min_rpm, delta, delta * clutch_position)
|
2021-11-07 00:33:24 +00:00
|
|
|
else:
|
2021-11-08 18:53:23 +00:00
|
|
|
rpm = _lerp_rpm(rpm, min_rpm, delta, delta)
|
2021-11-07 00:33:24 +00:00
|
|
|
if _has_traction():
|
2021-11-13 11:44:07 +00:00
|
|
|
rpm += throttle * delta * (max(clutch_position, 1 if gear == 0 else 0)) * THROTTLE_POWER
|
2021-11-05 22:11:26 +00:00
|
|
|
else:
|
2021-11-07 00:33:24 +00:00
|
|
|
rpm += throttle * delta * THROTTLE_POWER
|
|
|
|
rpm = clamp(rpm, 0, max_rpm)
|
|
|
|
var rpm_factor = clamp(rpm / max_rpm, 0.0, 1.0)
|
|
|
|
var power_factor = power_curve.interpolate_baked(rpm_factor)
|
|
|
|
|
2021-11-08 18:53:23 +00:00
|
|
|
_generate_engine_sound(rpm_factor)
|
|
|
|
|
2021-11-07 00:33:24 +00:00
|
|
|
# Transfer to transmission
|
|
|
|
var transmission_input = power_factor * (1 - clutch_position) * _get_gear_ratio()
|
|
|
|
|
|
|
|
var final_input = transmission_input * final_drive
|
|
|
|
|
|
|
|
brake = Input.get_action_strength("brake") * MAX_BRAKE_FORCE
|
|
|
|
engine_force = throttle * final_input * MAX_ENGINE_FORCE
|
|
|
|
|
|
|
|
var handbrake = Input.get_action_strength("handbrake")
|
2021-11-16 17:48:41 +00:00
|
|
|
rrwheel.brake = handbrake * MAX_BRAKE_FORCE
|
|
|
|
rlwheel.brake = handbrake * MAX_BRAKE_FORCE
|
2021-11-07 00:33:24 +00:00
|
|
|
|
2021-11-07 00:47:56 +00:00
|
|
|
var speed = wheel_rpm * 2.0 * PI * rrwheel.wheel_radius / 60.0 * 3600.0 / 1000.0
|
2021-11-14 22:07:54 +00:00
|
|
|
emit_signal("speed_updated", speed, speed / EXPECTED_MAX_SPEED)
|
|
|
|
emit_signal("rpm_updated", rpm, rpm_factor)
|
2021-11-07 00:47:56 +00:00
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
var steering_input = (
|
|
|
|
Input.get_action_strength("steer_left")
|
|
|
|
- Input.get_action_strength("steer_right")
|
|
|
|
)
|
2021-11-07 00:47:56 +00:00
|
|
|
if abs(steering_input) < 0.05:
|
|
|
|
steering_input = 0.0
|
|
|
|
elif steer_curve:
|
|
|
|
if steering_input < 0.0:
|
|
|
|
steering_input = -steer_curve.interpolate_baked(-steering_input)
|
|
|
|
else:
|
|
|
|
steering_input = steer_curve.interpolate_baked(steering_input)
|
2021-11-07 00:33:24 +00:00
|
|
|
|
2021-11-07 00:47:56 +00:00
|
|
|
var steer_speed_factor = clamp(speed / MAX_STEER_SPEED, 0.0, 1.0)
|
2021-11-05 22:11:26 +00:00
|
|
|
|
2021-11-11 22:54:34 +00:00
|
|
|
steering = steering_input * lerp(max_steer_angle_rad, speed_steer_angle_rad, steer_speed_factor)
|
2021-11-08 18:53:23 +00:00
|
|
|
|
2021-11-18 23:08:21 +00:00
|
|
|
|
2021-11-08 18:53:23 +00:00
|
|
|
func _generate_engine_sound(rpm_factor):
|
2021-11-13 21:48:15 +00:00
|
|
|
engine_sound_player.pitch_scale = BASE_ENGINE_PITCH + 2 * rpm_factor
|
2021-11-08 18:53:23 +00:00
|
|
|
var to_fill = engine_sound_playback.get_frames_available()
|
|
|
|
var factor = rpm_factor
|
2021-11-13 11:44:07 +00:00
|
|
|
if to_fill <= 0:
|
|
|
|
return
|
|
|
|
var fill_segment = 1.0 / to_fill
|
|
|
|
var fill_percent = 0.0
|
2021-11-08 18:53:23 +00:00
|
|
|
while to_fill > 0:
|
|
|
|
engine_sound_playback.push_frame(Vector2(1.0, 1.0) * factor)
|
2021-11-18 23:08:21 +00:00
|
|
|
factor += (
|
|
|
|
cos(factor)
|
|
|
|
* sin(factor)
|
|
|
|
* (1 + to_fill % 2)
|
|
|
|
* ((sound_curve.interpolate_baked(fill_percent) - 0.5) * 2)
|
|
|
|
)
|
2021-11-08 18:53:23 +00:00
|
|
|
to_fill -= 1
|
2021-11-13 11:44:07 +00:00
|
|
|
fill_percent += fill_segment
|