first save
This commit is contained in:
parent
814e50a862
commit
ad95711535
14 changed files with 434 additions and 41 deletions
|
@ -1,14 +0,0 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://cjk3phtyyiyty"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bdw7xdf1lc3ud" path="res://entities/do_spline.gd" id="1_c4y0q"]
|
||||
|
||||
[sub_resource type="Curve3D" id="Curve3D_p7e7j"]
|
||||
_data = {
|
||||
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6.24595, 0, 10),
|
||||
"tilts": PackedFloat32Array(0, 0)
|
||||
}
|
||||
point_count = 2
|
||||
|
||||
[node name="Track" type="Path3D"]
|
||||
curve = SubResource("Curve3D_p7e7j")
|
||||
script = ExtResource("1_c4y0q")
|
121
entities/car/car.gd
Normal file
121
entities/car/car.gd
Normal file
|
@ -0,0 +1,121 @@
|
|||
extends RigidBody3D
|
||||
class_name Car
|
||||
|
||||
@export var forward_force: float = 100.0
|
||||
@export var backward_force: float = 50.0
|
||||
@export var steer_speed: float = 2.0
|
||||
|
||||
@export var base_lateral_friction: float = 5.0
|
||||
@export var lateral_velocity_start_drift_threshold: float = 10.0
|
||||
@export var lateral_velocity_total_drift_threshold: float = 15.0
|
||||
|
||||
@onready var forward_left: RayCast3D = $Raycasts/ForwardLeft
|
||||
@onready var forward_right: RayCast3D = $Raycasts/ForwardRight
|
||||
@onready var backward_right: RayCast3D = $Raycasts/BackwardRight
|
||||
@onready var backward_left: RayCast3D = $Raycasts/BackwardLeft
|
||||
|
||||
@onready var forward_left_respawn: RayCast3D = $RaycastsRespawn/ForwardLeftRespawn
|
||||
@onready var forward_right_respawn: RayCast3D = $RaycastsRespawn/ForwardRightRespawn
|
||||
@onready var backward_right_respawn: RayCast3D = $RaycastsRespawn/BackwardRightRespawn
|
||||
@onready var backward_left_respawn: RayCast3D = $RaycastsRespawn/BackwardLeftRespawn
|
||||
|
||||
|
||||
|
||||
var base_steer_speed: float
|
||||
var current_steer_speed = base_steer_speed
|
||||
var last_steer_input := 0.0
|
||||
var rotation_angle := 0.0
|
||||
|
||||
var respawn_pos : Vector3
|
||||
|
||||
var thread: Thread = Thread.new()
|
||||
var steer_input = 0.0
|
||||
|
||||
var cheat := false
|
||||
var air_time := 0.0
|
||||
|
||||
|
||||
func return_to_road():
|
||||
position = respawn_pos + 3*Vector3.UP
|
||||
rotation.z = 0
|
||||
rotation.x = 0
|
||||
|
||||
linear_velocity = Vector3.ZERO
|
||||
angular_velocity = Vector3.ZERO
|
||||
|
||||
air_time = 0.0
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
|
||||
if Input.is_action_just_pressed("restart"):
|
||||
return_to_road()
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
var move_input := Input.get_axis("back", "forward")
|
||||
var steer_input_brut := Input.get_axis("right", "left")
|
||||
steer_input = lerpf(steer_input, steer_input_brut, 0.1)
|
||||
var is_on_floor := backward_left_respawn.is_colliding() || backward_right_respawn.is_colliding() || forward_left_respawn.is_colliding() || forward_right_respawn.is_colliding()
|
||||
var is_all_wheel_on_floor := backward_left_respawn.is_colliding() && backward_right_respawn.is_colliding() && forward_left_respawn.is_colliding() && forward_right_respawn.is_colliding()
|
||||
var is_flat : bool = transform.basis.y.dot(Vector3.UP) > 0.9
|
||||
|
||||
if is_all_wheel_on_floor && is_flat:
|
||||
respawn_pos = position
|
||||
|
||||
if !is_on_floor && !cheat:
|
||||
#$DriftParticles.emitting = false
|
||||
#$DriftParticles2.emitting = false
|
||||
#AudioServer.set_bus_volume_db(5, -80)
|
||||
air_time += delta
|
||||
if air_time > 1.5:
|
||||
return_to_road()
|
||||
return
|
||||
air_time = 0.0
|
||||
if cheat && Input.is_key_pressed(KEY_SPACE):
|
||||
linear_velocity.y += 20*delta
|
||||
if cheat:
|
||||
forward_force = 500
|
||||
|
||||
# Movement
|
||||
if move_input > 0.0:
|
||||
apply_central_force(global_transform.basis.z * forward_force)
|
||||
elif move_input < 0.0:
|
||||
var break_or_backward = 2*backward_force if global_transform.basis.z.dot(linear_velocity) > 0 else backward_force
|
||||
apply_central_force(global_transform.basis.z * -break_or_backward)
|
||||
|
||||
# Rotation
|
||||
rotation_angle = steer_input * delta
|
||||
#angular_velocity = steer_input * delta * global_transform.basis.y * 30.0
|
||||
rotate(global_transform.basis.y, rotation_angle)
|
||||
|
||||
# Drift Simulation
|
||||
var velocity = linear_velocity
|
||||
var forward_dir = global_transform.basis.z
|
||||
if forward_dir.length_squared() == 0.0:
|
||||
return # skip drift this frame if something is invalid
|
||||
forward_dir = forward_dir.normalized()
|
||||
|
||||
var forward_velocity = forward_dir * velocity.dot(forward_dir)
|
||||
var lateral_velocity = velocity - forward_velocity
|
||||
|
||||
var drift_factor = inverse_lerp(
|
||||
lateral_velocity_total_drift_threshold,
|
||||
lateral_velocity_start_drift_threshold,
|
||||
lateral_velocity.length()
|
||||
)
|
||||
drift_factor = clamp(drift_factor, 0, 1)
|
||||
|
||||
#$DriftParticles.emitting = drift_factor < 1 && is_on_floor
|
||||
#$DriftParticles2.emitting = drift_factor < 1 && is_on_floor
|
||||
#if drift_factor < 1 && is_on_floor:
|
||||
#AudioServer.set_bus_volume_db(5, lerp(-15, -30, drift_factor))
|
||||
#else:
|
||||
#AudioServer.set_bus_volume_db(5, -80)
|
||||
|
||||
steer_speed = lerp(steer_speed * 2.0, base_steer_speed, drift_factor)
|
||||
|
||||
var lateral_friction_force = -lateral_velocity * base_lateral_friction * drift_factor
|
||||
apply_central_force(lateral_friction_force)
|
||||
|
||||
|
||||
|
||||
|
1
entities/car/car.gd.uid
Normal file
1
entities/car/car.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://ctjy0e806j0vk
|
47
entities/car/car.tscn
Normal file
47
entities/car/car.tscn
Normal file
|
@ -0,0 +1,47 @@
|
|||
[gd_scene load_steps=4 format=3 uid="uid://dgs0fqojgcmu3"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://ctjy0e806j0vk" path="res://entities/car/car.gd" id="1_nh45c"]
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_kkl2f"]
|
||||
size = Vector3(1, 1, 2)
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_76tdi"]
|
||||
size = Vector3(1, 1, 2)
|
||||
|
||||
[node name="Car" type="RigidBody3D"]
|
||||
script = ExtResource("1_nh45c")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
|
||||
mesh = SubResource("BoxMesh_kkl2f")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.00250244)
|
||||
shape = SubResource("BoxShape3D_76tdi")
|
||||
|
||||
[node name="Raycasts" type="Node3D" parent="."]
|
||||
|
||||
[node name="ForwardLeft" type="RayCast3D" parent="Raycasts"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0, -1)
|
||||
|
||||
[node name="ForwardRight" type="RayCast3D" parent="Raycasts"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0, -1)
|
||||
|
||||
[node name="BackwardRight" type="RayCast3D" parent="Raycasts"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0, 1)
|
||||
|
||||
[node name="BackwardLeft" type="RayCast3D" parent="Raycasts"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0, 1)
|
||||
|
||||
[node name="RaycastsRespawn" type="Node3D" parent="."]
|
||||
|
||||
[node name="ForwardLeftRespawn" type="RayCast3D" parent="RaycastsRespawn"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0, -1)
|
||||
|
||||
[node name="ForwardRightRespawn" type="RayCast3D" parent="RaycastsRespawn"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0, -1)
|
||||
|
||||
[node name="BackwardRightRespawn" type="RayCast3D" parent="RaycastsRespawn"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0, 1)
|
||||
|
||||
[node name="BackwardLeftRespawn" type="RayCast3D" parent="RaycastsRespawn"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0, 1)
|
4
entities/car/car_physic_mat.tres
Normal file
4
entities/car/car_physic_mat.tres
Normal file
|
@ -0,0 +1,4 @@
|
|||
[gd_resource type="PhysicsMaterial" format=3 uid="uid://doaljsb6138cp"]
|
||||
|
||||
[resource]
|
||||
friction = 0.1
|
|
@ -1,26 +0,0 @@
|
|||
@tool
|
||||
extends Path3D
|
||||
class_name RoadPath
|
||||
@export_tool_button("update_control_points") var action = update_control_points
|
||||
|
||||
func update_control_points():
|
||||
if curve.point_count < 2:
|
||||
return
|
||||
|
||||
|
||||
# Start point: out control based on next point
|
||||
var dir = (curve.get_point_position(1) - curve.get_point_position(0)).normalized()
|
||||
var tangent_length = dir.length() / 3
|
||||
|
||||
curve.set_point_out(0, dir * tangent_length)
|
||||
|
||||
# Intermediate points: in and out controls based on adjacent points
|
||||
for i in range(1, curve.point_count - 1):
|
||||
var prev_dir = (curve.get_point_position(i) - curve.get_point_position(i - 1)).normalized()
|
||||
var next_dir = (curve.get_point_position(i + 1) - curve.get_point_position(i)).normalized()
|
||||
tangent_length = next_dir.length() / 3
|
||||
var tangent = (prev_dir + next_dir)
|
||||
tangent.y = 0
|
||||
tangent = tangent.normalized()
|
||||
curve.set_point_in(i, -tangent * tangent_length)
|
||||
curve.set_point_out(i, tangent * tangent_length)
|
32
entities/road/do_spline.gd
Normal file
32
entities/road/do_spline.gd
Normal file
|
@ -0,0 +1,32 @@
|
|||
@tool
|
||||
extends Path3D
|
||||
class_name RoadPath
|
||||
@export_tool_button("update_control_points") var action = update_control_points
|
||||
|
||||
func modulo_get_point_position(i):
|
||||
return curve.get_point_position(posmod(i, curve.point_count))
|
||||
|
||||
func update_control_points():
|
||||
if curve.point_count < 2:
|
||||
return
|
||||
|
||||
#
|
||||
## Start point: out control based on next point
|
||||
#var dir = (curve.get_point_position(1) - curve.get_point_position(0)).normalized()
|
||||
#var tangent_length = dir.length() / 3
|
||||
#
|
||||
#curve.set_point_out(0, dir * tangent_length)
|
||||
|
||||
# Intermediate points: in and out controls based on adjacent points
|
||||
for i in range(0, curve.point_count):
|
||||
var prev = modulo_get_point_position(i) - modulo_get_point_position(i - 1)
|
||||
var next = modulo_get_point_position(i + 1) - modulo_get_point_position(i)
|
||||
var prev_dir = prev.normalized()
|
||||
var next_dir = next.normalized()
|
||||
var tangent_length = next.length() / 3
|
||||
var tangent = (prev_dir + next_dir)
|
||||
|
||||
tangent.y = 0
|
||||
tangent = tangent.normalized()
|
||||
curve.set_point_in(i, -tangent * tangent_length)
|
||||
curve.set_point_out(i, tangent * tangent_length)
|
118
entities/road/road.gd
Normal file
118
entities/road/road.gd
Normal file
|
@ -0,0 +1,118 @@
|
|||
@tool
|
||||
extends StaticBody3D
|
||||
class_name Road
|
||||
|
||||
@export_tool_button("create_mesh") var action_generate = generate_mesh
|
||||
@export_tool_button("clear_all") var action_clear = clear_all
|
||||
|
||||
@export var track : RoadPath
|
||||
@export var road_mesh_instance : MeshInstance3D
|
||||
@export var road_shape : CollisionShape3D
|
||||
@export var road_material : BaseMaterial3D
|
||||
@export var segment_length := 0.1
|
||||
@export var road_width : float = 1.5
|
||||
@export var road_thickness : float = 0.5
|
||||
|
||||
var st_road = SurfaceTool.new()
|
||||
|
||||
func clear_all():
|
||||
st_road = SurfaceTool.new()
|
||||
st_road.clear()
|
||||
road_mesh_instance.mesh = null
|
||||
if road_shape and road_shape.shape:
|
||||
road_shape.shape = null
|
||||
|
||||
func generate_mesh():
|
||||
clear_all()
|
||||
st_road.begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
if road_material:
|
||||
st_road.set_material(road_material)
|
||||
|
||||
var curve := track.curve
|
||||
var race_length = curve.get_baked_length()
|
||||
var nb_of_point : int = race_length / segment_length
|
||||
|
||||
for i in range(nb_of_point):
|
||||
var dist1 = float(i) * segment_length
|
||||
var dist2 = float(i + 1) * segment_length
|
||||
|
||||
var t1 := curve.sample_baked_with_rotation(dist1, true)
|
||||
var t2 := curve.sample_baked_with_rotation(dist2, true)
|
||||
|
||||
var fwd1 = t1.basis.z.normalized()
|
||||
var fwd2 = t2.basis.z.normalized()
|
||||
|
||||
var right1 = t1.basis.x.normalized()
|
||||
var right2 = t2.basis.x.normalized()
|
||||
|
||||
var left1 = -right1
|
||||
var left2 = -right2
|
||||
|
||||
var up1 = t1.basis.y.normalized()
|
||||
var up2 = t2.basis.y.normalized()
|
||||
|
||||
var p1 := t1.origin
|
||||
if i == 0:
|
||||
p1 += fwd1 * 0.05
|
||||
var p2 := t2.origin
|
||||
|
||||
# Top vertices
|
||||
var p1_right = p1 + right1 * road_width * 0.5
|
||||
var p1_left = p1 - right1 * road_width * 0.5
|
||||
var p2_right = p2 + right2 * road_width * 0.5
|
||||
var p2_left = p2 - right2 * road_width * 0.5
|
||||
|
||||
# Bottom vertices
|
||||
var p1_right_bottom = p1_right - up1 * road_thickness
|
||||
var p1_left_bottom = p1_left - up1 * road_thickness
|
||||
var p2_right_bottom = p2_right - up2 * road_thickness
|
||||
var p2_left_bottom = p2_left - up2 * road_thickness
|
||||
|
||||
# Top face
|
||||
create_rectangle(p1_right, p1_left, p2_left, p2_right, up1, up2, Vector2(0, dist1 / road_width), Vector2(1, dist2 / road_width))
|
||||
|
||||
# Bottom face (inverted normal)
|
||||
create_rectangle(p1_left_bottom, p1_right_bottom, p2_right_bottom, p2_left_bottom, up1, up2, Vector2(1, dist1 / road_width), Vector2(0, dist2 / road_width))
|
||||
|
||||
# Right side face
|
||||
create_rectangle(p1_right_bottom, p1_right, p2_right, p2_right_bottom, right1, right2, Vector2(dist1 / road_thickness, 0), Vector2(dist2 / road_thickness, 1))
|
||||
|
||||
# Left side face
|
||||
create_rectangle(p1_left, p1_left_bottom, p2_left_bottom, p2_left, left1, left2, Vector2(dist1 / road_thickness, 0), Vector2(dist2 / road_thickness, 1))
|
||||
|
||||
var final_mesh = st_road.commit()
|
||||
road_mesh_instance.mesh = final_mesh
|
||||
|
||||
var shape = final_mesh.create_trimesh_shape()
|
||||
road_shape.shape = shape
|
||||
|
||||
func create_rectangle(
|
||||
v1: Vector3, v2: Vector3, v3: Vector3, v4: Vector3,
|
||||
normal1: Vector3, normal2: Vector3,
|
||||
uv1: Vector2, uv2: Vector2
|
||||
):
|
||||
# Triangle 1
|
||||
st_road.set_uv(uv1)
|
||||
st_road.set_normal(normal1)
|
||||
st_road.add_vertex(v1)
|
||||
|
||||
st_road.set_uv(Vector2(uv1.x, uv2.y))
|
||||
st_road.set_normal(normal1)
|
||||
st_road.add_vertex(v2)
|
||||
|
||||
st_road.set_uv(uv2)
|
||||
st_road.set_normal(normal2)
|
||||
st_road.add_vertex(v3)
|
||||
|
||||
# Triangle 2
|
||||
st_road.set_uv(uv2)
|
||||
st_road.set_normal(normal2)
|
||||
st_road.add_vertex(v3)
|
||||
|
||||
st_road.set_uv(Vector2(uv2.x, uv1.y))
|
||||
st_road.set_normal(normal1)
|
||||
st_road.add_vertex(v4)
|
||||
|
||||
st_road.set_uv(uv1)
|
||||
st_road.set_normal(normal1)
|
||||
st_road.add_vertex(v1)
|
1
entities/road/road.gd.uid
Normal file
1
entities/road/road.gd.uid
Normal file
|
@ -0,0 +1 @@
|
|||
uid://bgt66573ipmub
|
33
entities/road/road.tscn
Normal file
33
entities/road/road.tscn
Normal file
File diff suppressed because one or more lines are too long
16
entities/road/road_path.tscn
Normal file
16
entities/road/road_path.tscn
Normal file
|
@ -0,0 +1,16 @@
|
|||
[gd_scene load_steps=3 format=3 uid="uid://cjk3phtyyiyty"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bdw7xdf1lc3ud" path="res://entities/road/do_spline.gd" id="1_c4y0q"]
|
||||
|
||||
[sub_resource type="Curve3D" id="Curve3D_p7e7j"]
|
||||
closed = true
|
||||
_data = {
|
||||
"points": PackedVector3Array(0.246495, 0, 4.21189, -0.246495, 0, -4.21189, 0, 0, 0, -4.24042, 0, 0.00829778, 4.24042, 0, -0.00829778, 10, 0, -7.75931, -4.21783, 0, -0.014848, 4.21783, 0, 0.014848, 20, 1.27448, 0, -4.24638, 0, 0.0109491, 4.24638, 0, -0.0109491, 30, 0, -7.64779, -2.44782, 0, -6.85357, 2.44782, 0, 6.85357, 40, 1.9489, 0, 12.6025, 0, -5.29505, -12.6025, 0, 5.29505, 35.1108, 0, 21.1888),
|
||||
"tilts": PackedFloat32Array(0, 0, 0, 0, 0, 0)
|
||||
}
|
||||
point_count = 6
|
||||
|
||||
[node name="Track" type="Path3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00397015, 0, 0)
|
||||
curve = SubResource("Curve3D_p7e7j")
|
||||
script = ExtResource("1_c4y0q")
|
Loading…
Add table
Add a link
Reference in a new issue