Godot Version
4.7-rc2.mono
Question
So i created a kart racer, and it’s steering is NOT like arcade steering at all.
And i’m not a heavy professor math teacher math knowledge level so
could anyone fix it? Thank you!
(lfs) lfsuser:~$ extends VehicleBody3D
class_name BaseCar
@export var ARCADE_TURN_SPEED = 2.5
@export var STEER_SPEED = 3.0
@export var STEER_LIMIT = 0.6
var steer_target = 0
@export var engine_force_value = 40
@export var cam: Camera3D
@export var first: AudioStreamPlayer
@export var luigi: AudioStreamPlayer3D
@export var mario: AudioStreamPlayer3D
@export var yshi: AudioStreamPlayer
@export var race_done = false
@export var marker3d: Marker3D
@export var ui: Control
@export var boost: AudioStreamPlayer3D
@export var star: AudioStreamPlayer
@export var starparticle: GPUParticles3D
@export var marker3d2: Marker3D
@export var marker3d3: Marker3D
@export var camera: Camera3D
var gearshift = 3
var gear_multiplicator = 1
var gear_locked = false
var riding = false
var fwd_mps : float
var speed: float
# New steering variables
var turn_input = 0.0
var turn_speed = 4.0
var turn_stop_limit = 0.75
var steering_angle = 45.0
# Checkpoint system
var last_checkpoint: Area3D = null
var start_position: Vector3
var start_rotation: Vector3
var checkpoints_collected: Array = []
var total_checkpoints: int = 0
var lap_count: int = 0
var max_laps: int = 3
var golden_timer_active = false
var star_power = false
func _ready():
start_position = global_position
start_rotation = global_rotation
add_to_group("kart")
total_checkpoints = get_tree().get_nodes_in_group("checkpoints").size()
if Global_self.GodotKartDoubleDash == true:
riding = true
func _physics_process(delta):
speed = linear_velocity.length() * Engine.get_frames_per_second() * delta
fwd_mps = transform.basis.x.x
process_gear_shift()
if Global_self.GodotKartDoubleDash == true:
process_items(delta)
process_camera(delta)
process_accel(delta)
process_steer(delta)
process_brake(delta)
# Reset rotation if car flips over
if abs(rotation.x) > deg_to_rad(150) or abs(rotation.z) > deg_to_rad(150) or abs(rotation.x) >= deg_to_rad(50) or abs(rotation.z) >= deg_to_rad(50):
rotation.x = 0.0
rotation.z = 0.0
%Hud/speed.text = str(round(speed * 3.6)) + " KMPH"
%Hud/lap_label.text = "Lap: " + str(lap_count) + "/" + str(max_laps)
func process_accel(delta):
if riding and not race_done and not Global_self.GodotKartDoubleDash:
if Input.is_action_pressed("player_up"):
if fwd_mps >= -1:
if speed < 30 and speed != 0:
engine_force = clamp(engine_force_value * 10 / speed, 0, 300)
else:
engine_force = engine_force_value
engine_force = engine_force * gear_multiplicator
return
if Input.is_action_pressed("player_dovn"):
if speed < 20 and speed != 0:
engine_force = -clamp(engine_force_value * 3 / speed, 0, 300)
else:
engine_force = -engine_force_value
return
engine_force = 0
if riding and not race_done and Global_self.GodotKartDoubleDash:
if Input.is_action_pressed("player_a_btn"):
if fwd_mps >= -1:
if speed < 30 and speed != 0:
if star_power:
engine_force = clamp(engine_force_value * 10 / speed, 0, 1200)
else:
engine_force = clamp(engine_force_value * 10 / speed, 0, 500)
else:
engine_force = engine_force_value
engine_force = engine_force * gear_multiplicator
return
if Input.is_action_pressed("key_z"):
if speed < 20 and speed != 0:
if star_power:
engine_force = -clamp(engine_force_value * 10 / speed, 0, 1200)
else:
engine_force = -clamp(engine_force_value * 10 / speed, 0, 500)
else:
engine_force = -engine_force_value
return
engine_force = 0
func process_steer(delta):
if not riding:
return
# get smooth input
turn_input = Input.get_axis("player_right", "player_left") * deg_to_rad(steering_angle)
# only steer if moving fast enough
if linear_velocity.length() > turn_stop_limit:
# rotate the entire kart smoothly
var new_basis = global_transform.basis.rotated(global_transform.basis.y, turn_input)
global_transform.basis = global_transform.basis.slerp(new_basis, turn_speed * delta)
global_transform = global_transform.orthonormalized()
# wheel visuals only
steering = turn_input * 0.3
func process_brake(delta):
if riding and not race_done:
if Input.is_action_pressed("player_crouch"):
brake = 1.0
$wheal3.wheel_friction_slip = 2
$wheal2.wheel_friction_slip = 2
else:
brake = 0.0
$wheal3.wheel_friction_slip = 2.9
$wheal2.wheel_friction_slip = 2.9
func collect_itembox():
ui.itemcontrollerui._on_rolling_single()
func collect_itemboxdouble():
ui.itemcontrollerui._on_rolling_double()
func process_camera(delta):
if Global_self.GodotKartDoubleDash:
if Input.is_action_pressed("player_attack"):
camera.position = marker3d2.position
camera.rotation = marker3d2.rotation
if Input.is_action_just_released("player_attack"):
camera.position = marker3d3.position
camera.rotation = marker3d3.rotation
func process_items(delta):
if Input.is_action_just_pressed("player_crouch"):
if golden_timer_active:
shroom_boost(delta)
return
if ui.itemcontrollerui.item == "empty" and ui.itemcontrollerui.item2 == "empty":
return
if ui.itemcontrollerui.item != "empty":
if ui.itemcontrollerui.item == "golden":
activate_golden(delta)
elif ui.itemcontrollerui.item == "shroom":
shroom_boost(delta)
ui.itemcontrollerui.item = "empty"
ui.itemcontrollerui.clearitem()
elif ui.itemcontrollerui.item == "star":
use_star(delta)
ui.itemcontrollerui.item = "empty"
ui.itemcontrollerui.clearitem()
elif ui.itemcontrollerui.item2 != "empty":
if ui.itemcontrollerui.item2 == "golden":
activate_golden(delta)
elif ui.itemcontrollerui.item2 == "shroom":
shroom_boost(delta)
ui.itemcontrollerui.item2 = "empty"
ui.itemcontrollerui.clearitem2()
elif ui.itemcontrollerui.item2 == "star":
use_star(delta)
ui.itemcontrollerui.item2 = "empty"
ui.itemcontrollerui.clearitem2()
func use_golden(delta):
shroom_boost(delta)
var star_infinite = false
var star_checking = false
func use_star(delta):
yshi.stop()
apply_star_color()
boost.play()
starparticle.emitting = true
star.play()
engine_force_value = 760 * 2
star_power = true
star_infinite = false
star_checking = true
for i in range(50000):
if Input.is_action_just_pressed("dpad_dovn"):
star_infinite = true
print("CHAOS! Infinite star activated!")
break
await get_tree().create_timer(0.01).timeout
star_checking = false
if not star_infinite:
await get_tree().create_timer(20.0).timeout
_deactivate_star()
func _deactivate_star():
star_power = false
star_infinite = false
star_checking = false
yshi.play()
remove_star_color()
starparticle.emitting = false
star.stop()
engine_force_value = 40
func apply_star_color():
var star_shader = ShaderMaterial.new()
star_shader.shader = preload("res://stuff/godotKart/godotKartDoubleDash/shaders/star_effect.gdshader")
apply_star_recursive(self, star_shader)
func apply_star_recursive(node, star_mat):
for child in node.get_children():
if child is MeshInstance3D:
child.material_overlay = star_mat
apply_star_recursive(child, star_mat)
func remove_star_color():
remove_star_recursive(self)
func remove_star_recursive(node):
for child in node.get_children():
if child is MeshInstance3D:
child.material_overlay = null
remove_star_recursive(child)
func activate_golden(delta):
golden_timer_active = true
var timer = get_tree().create_timer(5.0)
timer.timeout.connect(_on_golden_timer_timeout)
func _on_golden_timer_timeout():
golden_timer_active = false
print("golden ran out!")
if ui.itemcontrollerui.item == "golden":
ui.itemcontrollerui.item = "empty"
func use_shroom(delta):
shroom_boost(delta)
ui.itemcontrollerui.item = "empty"
func shroom_boost(delta):
linear_velocity += transform.basis.x * 20.0
boost.play()
func process_gear_shift():
if riding and not race_done:
if Input.is_action_pressed("gear"):
if gear_locked == false:
gear_locked = true
gearshift += 1
if gearshift == 6: gearshift = 1
if gearshift == 1: gear_multiplicator = 0.3
elif gearshift == 2: gear_multiplicator = 0.7
elif gearshift == 3: gear_multiplicator = 1
elif gearshift == 4: gear_multiplicator = 1.3
elif gearshift == 5: gear_multiplicator = 1.8
await get_tree().create_timer(1.0).timeout
gear_locked = false
func collect_checkpoint(checkpoint: Area3D):
if Global_self.GodotKartDoubleDash == true:
last_checkpoint = checkpoint
if not checkpoints_collected.has(checkpoint):
checkpoints_collected.append(checkpoint)
print("Checkpoint collected: ", checkpoint.name, " (", checkpoints_collected.size(), "/", total_checkpoints, ")")
if checkpoints_collected.size() >= total_checkpoints:
lap_complete()
func lap_complete():
lap_count += 1
print("LAP ", lap_count, "/", max_laps, " COMPLETE!")
if lap_count >= max_laps:
race_finished()
else:
checkpoints_collected.clear()
for checkpoint in get_tree().get_nodes_in_group("checkpoints"):
if checkpoint.has_method("reset_checkpoint"):
checkpoint.reset_checkpoint()
print("Checkpoints reset for lap ", lap_count + 1)
func race_finished():
print("RACE FINISHED! Final position achieved!")
race_done = true
speed = 0.0
riding = false
$wheal2.use_as_steering = false
$wheal3.use_as_steering = false
fwd_mps = 0.0
steer_target = 0.0
cam.position = marker3d.position
cam.rotation = marker3d.rotation
yshi.stop()
first.play()
luigi.play()
await get_tree().create_timer(1.71).timeout
mario.play()
func respawn_to_checkpoint():
if Global_self.GodotKartDoubleDash == true:
linear_velocity = Vector3.ZERO
angular_velocity = Vector3.ZERO
steering = 0.0
engine_force = 0.0
brake = 0.0
if last_checkpoint:
global_position = last_checkpoint.global_position + Vector3.UP * 1.0
global_rotation = last_checkpoint.global_rotation
else:
global_position = start_position
global_rotation = start_rotation
rotation.x = 0.0
rotation.z = 0.0
func _input(event):
if Global_self.GodotKartDoubleDash == true and riding and not race_done:
if event.is_action_pressed("respawn"):
respawn_to_checkpoint()
if star_infinite and star_power:
if event.is_action_pressed("dpad_dovn"):
print("Infinite star deactivated!")
_deactivate_star()