diff --git a/project.godot b/project.godot index 93ad76d..2e40708 100644 --- a/project.godot +++ b/project.godot @@ -13,6 +13,63 @@ config_version=4 config/name="bugged-racing" config/icon="res://icon.png" +[input] + +throttle={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":7,"axis_value":1.0,"script":null) + ] +} +brake={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":6,"axis_value":1.0,"script":null) + ] +} +clutch={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":67,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":3,"axis_value":-1.0,"script":null) + ] +} +handbrake={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":3,"axis_value":1.0,"script":null) + ] +} +steer_left={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null) + ] +} +steer_right={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null) + ] +} +gear_up={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777237,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":69,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":5,"pressure":0.0,"pressed":false,"script":null) + ] +} +gear_down={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777238,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":81,"physical_scancode":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":4,"pressure":0.0,"pressed":false,"script":null) + ] +} + [physics] common/enable_pause_aware_picking=true diff --git a/scenes/test_level.tscn b/scenes/test_level.tscn index 4a00997..18854bb 100644 --- a/scenes/test_level.tscn +++ b/scenes/test_level.tscn @@ -35,7 +35,6 @@ shape = SubResource( 3 ) [node name="buggy" parent="." instance=ExtResource( 1 )] transform = Transform( 1.00456, 0, 0, 0, 1.00456, 0, 0, 0, 1.00456, -38.0928, 1.38435, -0.0872202 ) mass = 250.0 -engine_force_value = 10000 [node name="camera" type="Camera" parent="."] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5.88022, 23.0639 ) diff --git a/vehicles/buggy.gd b/vehicles/buggy.gd index f3704e7..47c7901 100644 --- a/vehicles/buggy.gd +++ b/vehicles/buggy.gd @@ -5,35 +5,108 @@ const STEER_LIMIT = 0.4 var steer_target = 0 -export var engine_force_value = 40 +export (float) var MAX_ENGINE_FORCE = 100.0 +export (float) var MAX_BRAKE_FORCE = 50.0 +export (float) var THROTTLE_POWER = 10000.0 +export (float) var MAX_RPM_LOSS_PS = 3000.0 -func _physics_process(delta): - var fwd_mps = transform.basis.xform_inv(linear_velocity).x +export (Array) var gear_ratios = [ 6, 5, 4, 3, 2, 1.0 ] +export (float) var reverse_ratio = -6.0 +export (float) var final_drive = 3.38 +export (float) var max_rpm = 7000 +export (float) var min_rpm = 900 +export (float) var gear_switch_time = 0.2 +export (Curve) var power_curve - steer_target = Input.get_action_strength("ui_left") - Input.get_action_strength("ui_right") +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 + +var traction_wheels: Array + +func _ready(): + for wheel in [frwheel, flwheel, rrwheel, rlwheel]: + if wheel.use_as_traction: + traction_wheels.append(wheel) + +func _get_gear_ratio(): + if gear == 0: + return 0 + elif gear == -1: + return reverse_ratio + else: + return gear_ratios[gear - 1] + +func _handle_gear_switch(delta: float): + if gear_timer > 0: + gear_timer = max(0, gear_timer - delta) + elif clutch_position > 0.8: + if Input.is_action_just_pressed("gear_up"): + if gear + 1 <= gear_ratios.size(): + gear += 1 + gear_timer = gear_switch_time * (2 - clutch_position) + if Input.is_action_just_pressed("gear_down"): + if gear - 1 >= -1: + gear -= 1 + gear_timer = gear_switch_time * (2 - clutch_position) + +func _has_traction(): + for wheel in traction_wheels: + if wheel.is_in_contact(): + return true + return false + +func _lerp_rpm(from, to, delta, factor): + var new_val = lerp(from, to, factor) + if abs(from - new_val) > MAX_RPM_LOSS_PS * delta: + var new_factor = inverse_lerp(from, to, from - sign(from - new_val) * MAX_RPM_LOSS_PS * delta) + new_val = lerp(from, to, new_factor) + return new_val + +func _physics_process(delta: float): + clutch_position = Input.get_action_strength("clutch") + _handle_gear_switch(delta) + var throttle = Input.get_action_strength("throttle") + + 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: + rpm = lerp(rpm, transmission_rpm, delta * (1 - clutch_position)) + rpm = _lerp_rpm(rpm, min_rpm, delta, delta * clutch_position * 3) + else: + rpm = _lerp_rpm(rpm, min_rpm, delta, delta * 3) + if _has_traction(): + rpm += throttle * delta * clutch_position * THROTTLE_POWER + else: + 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) + + # 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") + rrwheel.brake = handbrake * MAX_BRAKE_FORCE / 2 + rlwheel.brake = handbrake * MAX_BRAKE_FORCE / 2 + + $Info.text = "Gear: %d, RPM: %.0f, TRPM: %.0f, Engine force: %.0f" % [ gear, rpm, transmission_rpm, engine_force ] + + steer_target = Input.get_action_strength("steer_left") - Input.get_action_strength("steer_right") steer_target *= STEER_LIMIT - if Input.is_action_pressed("ui_up"): - # Increase engine force at low speeds to make the initial acceleration faster. - var speed = linear_velocity.length() - if speed < 5 and speed != 0: - engine_force = clamp(engine_force_value * 5 / speed, 0, 100) - else: - engine_force = engine_force_value - else: - engine_force = 0 - - if Input.is_action_pressed("ui_down"): - # Increase engine force at low speeds to make the initial acceleration faster. - if fwd_mps >= -1: - var speed = linear_velocity.length() - if speed < 5 and speed != 0: - engine_force = -clamp(engine_force_value * 5 / speed, 0, 100) - else: - engine_force = -engine_force_value - else: - brake = 1 - else: - brake = 0.0 - steering = move_toward(steering, steer_target, STEER_SPEED * delta) diff --git a/vehicles/buggy.tscn b/vehicles/buggy.tscn index 2bda980..00eb45e 100644 --- a/vehicles/buggy.tscn +++ b/vehicles/buggy.tscn @@ -1,13 +1,17 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://assets/basic_buggy.glb" type="PackedScene" id=1] [ext_resource path="res://vehicles/buggy.gd" type="Script" id=3] +[sub_resource type="Curve" id=2] +_data = [ Vector2( 0, 0 ), 0.0, 0.0, 0, 0, Vector2( 0.910377, 0.990909 ), 0.0, 0.0, 0, 0, Vector2( 1, 0 ), 0.0, 0.0, 0, 0 ] + [sub_resource type="BoxShape" id=1] extents = Vector3( 0.521885, 0.334919, 1.78849 ) [node name="buggy" instance=ExtResource( 1 )] script = ExtResource( 3 ) +power_curve = SubResource( 2 ) [node name="chassis" parent="." index="0"] transform = Transform( -1, 0, -3.25841e-07, 0, 1, 0, 3.25841e-07, 0, -1, 0, 0.446435, 0 ) @@ -45,3 +49,10 @@ wheel_radius = 0.6 wheel_rest_length = 0.4 suspension_travel = 1.0 suspension_max_force = 10000.0 + +[node name="Info" type="Label" parent="." index="7"] +margin_right = 40.0 +margin_bottom = 14.0 +__meta__ = { +"_edit_use_anchors_": false +}