Rigidbody3D functional prototype

This commit is contained in:
Gary Steven Keough 2025-02-02 20:00:55 -05:00
parent 1550f57f5d
commit 54352990fd
9 changed files with 1550 additions and 74 deletions

1338
core/drone/dro815E.tmp Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
extends CharacterBody3D
extends RigidBody3D
# Local coords to axis
# Yaw = Y
@ -8,61 +8,49 @@ extends CharacterBody3D
@export_category("Parameters")
@export var flight_modes: Array = ["normal", "acro"]
@export var armed: bool = false
@export var can_flip: bool = false
@export var throttle_speed: float = 0.0
@export var rotation_speed: float = 1.0
@export var acceleration: float = 10.0
@export var max_speed: float = 10.0
@export var max_rotation_speed: float = 10.0
@export var rotation_speed: float = 0.05 # Adjust as needed
@export var acceleration: float = 0.5 # Adjust as needed
@export var max_speed: float = 1.0 # Adjust as needed
@export var max_rotation_speed: float = 5.0 # Adjust as needed
@export var camera_tilt_angle: float = 0.0
@export var gravity: float = 9.8
@export_category("Node References")
@export var camera: Camera3D
@export var anim_player: AnimationPlayer
@export var flip_over_detection_ray: RayCast3D
@export var flip_over_timer: Timer
@export var input_suggestion_label: Label
var animation_initalized: bool = false
var using_joy_controller: bool = true
func _ready():
pass
flip_over_timer.timeout.connect(_on_flip_over_timeout)
func handle_throttle(throttle_input: float, delta):
func _process(_delta):
if Input.is_action_just_pressed("arm"):
handle_arming()
func handle_throttle(throttle_input: float):
if using_joy_controller:
if throttle_input > 0:
throttle_speed = throttle_input * 100
var desired_vel = velocity.y + throttle_speed * 0.5
velocity.y = lerp(velocity.y, desired_vel, delta)
else:
pass
apply_central_force(global_transform.basis.y * throttle_speed)
elif throttle_input <= 0.05: # Adjust this value if needed
apply_central_force(global_transform.basis.y * 1) # Minimum thrust
# Speed scale adjusted for animation
anim_player.speed_scale = throttle_input * 4
anim_player.speed_scale = clampf(anim_player.speed_scale, 1.0, 4.0)
velocity.x = clampf(velocity.x, -max_speed, max_speed)
velocity.y = clampf(velocity.y, -100.0, max_speed)
velocity.z = clampf(velocity.z, -max_speed, max_speed)
linear_velocity.x = clampf(linear_velocity.x, -max_speed, max_speed)
linear_velocity.y = clampf(linear_velocity.y, -100.0, max_speed) # Keep vertical clamping
linear_velocity.z = clampf(linear_velocity.z, -max_speed, max_speed)
#print("anim speed: ", anim_player.speed_scale) # DEBUG
#print("throttle speed: ", throttle_speed) # DEBUG
func handle_yaw(yaw_input: float, delta):
#rotate_y(rotation_speed * yaw_input * delta)
#global_rotate(Vector3.UP, yaw_input * rotation_speed * delta)
transform.basis = transform.basis.rotated(Vector3.UP, yaw_input * delta)
func handle_roll(roll_input: float, delta):
if !is_on_floor():
transform.basis = transform.basis.rotated(Vector3.BACK, roll_input * delta)
func handle_pitch(pitch_input: float, delta):
if !is_on_floor():
transform.basis = transform.basis.rotated(Vector3.RIGHT, pitch_input * delta)
func handle_arming():
@ -80,33 +68,60 @@ func handle_arming():
print("Drone disarmed")
func _physics_process(delta):
# Gravity
if !is_on_floor():
velocity.y -= gravity * delta
else:
global_rotation.x = lerpf(global_rotation.x, 0.0, delta * 20)
global_rotation.z = lerpf(global_rotation.z, 0.0, delta * 20)
func _start_flip_over_timer():
if flip_over_timer.time_left > 0:
pass
elif !can_flip:
flip_over_timer.start()
if Input.is_action_just_pressed("arm"):
handle_arming()
if armed:
if Input.is_action_pressed("throttle_down") or Input.is_action_pressed("throttle_up"):
var throttle_input = Input.get_axis("throttle_down", "throttle_up")
handle_throttle(throttle_input, delta)
func _on_flip_over_timeout():
if flip_over_detection_ray.is_colliding() and flip_over_detection_ray.get_collider().is_in_group("Ground"):
can_flip = true
input_suggestion_label.text = "press A to flip drone"
input_suggestion_label.show()
if Input.is_action_pressed("yaw_left") or Input.is_action_pressed("yaw_right"):
var yaw_input = Input.get_axis("yaw_right", "yaw_left")
handle_yaw(yaw_input, delta)
if Input.is_action_pressed("roll_left") or Input.is_action_pressed("roll_right"):
var roll_input = Input.get_axis("roll_left", "roll_right")
handle_roll(roll_input, delta)
func _handle_drone_flipping():
if flip_over_detection_ray.is_colliding() and flip_over_detection_ray.get_collider().is_in_group("Ground"):
global_rotation = Vector3.ZERO
input_suggestion_label.hide()
can_flip = false
if Input.is_action_pressed("pitch_backward") or Input.is_action_pressed("pitch_forward"):
var pitch_input = Input.get_axis("pitch_backward", "pitch_forward")
handle_pitch(pitch_input, delta)
print("velocity: ", velocity)
move_and_slide()
func _physics_process(_delta): # Still needed for other physics
if flip_over_detection_ray.is_colliding() and flip_over_detection_ray.get_collider().is_in_group("Ground"):
_start_flip_over_timer()
if Input.is_action_just_pressed("accept") and can_flip:
_handle_drone_flipping()
func _integrate_forces(state): # Use _integrate_forces for RigidBody3D control
if armed: # Only apply controls when armed
var yaw_input = Input.get_axis("yaw_right", "yaw_left")
var roll_input = Input.get_axis("roll_right", "roll_left")
var pitch_input = Input.get_axis("pitch_backward", "pitch_forward")
var throttle_input = Input.get_axis("throttle_down", "throttle_up")
handle_throttle(throttle_input) # Throttle still handled here
if yaw_input != 0:
rotate_object_local(Vector3.UP, yaw_input * rotation_speed) # Y axis rotation
if roll_input != 0:
rotate_object_local(Vector3.FORWARD, roll_input * rotation_speed) # Z axis rotation
if pitch_input != 0:
rotate_object_local(Vector3.RIGHT, pitch_input * rotation_speed) # X axis rotation
# Damping (Important! Still needed):
if yaw_input == 0:
state.angular_velocity.y = lerp(state.angular_velocity.y, 0.0, 0.05)
if roll_input == 0:
state.angular_velocity.z = lerp(state.angular_velocity.z, 0.0, 0.05)
if pitch_input == 0:
state.angular_velocity.x = lerp(state.angular_velocity.x, 0.0, 0.05)
# Clamp the angular velocity (optional, but good practice):
state.angular_velocity.y = clampf(state.angular_velocity.y, -max_rotation_speed, max_rotation_speed)
state.angular_velocity.z = clampf(state.angular_velocity.z, -max_rotation_speed, max_rotation_speed)
state.angular_velocity.x = clampf(state.angular_velocity.x, -max_rotation_speed, max_rotation_speed)

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=101 format=4 uid="uid://dwvmna8qc0vb4"]
[gd_scene load_steps=103 format=4 uid="uid://dwvmna8qc0vb4"]
[ext_resource type="Script" path="res://core/drone/drone.gd" id="1_de83i"]
[ext_resource type="Material" uid="uid://d0gkxc5fuh354" path="res://core/resources/materials/black_carbon_fiber.tres" id="2_phv8m"]
@ -8,9 +8,13 @@
[ext_resource type="Material" uid="uid://b2okmc5xyxhkm" path="res://core/resources/materials/prop_green_plastic.tres" id="4_ltc6o"]
[ext_resource type="Material" uid="uid://is2nkfruok8v" path="res://core/resources/materials/tan_controller_stack.tres" id="5_h3y6c"]
[ext_resource type="Material" uid="uid://uy2txkh3slat" path="res://core/resources/materials/pink_motor.tres" id="6_3gtkc"]
[ext_resource type="Script" path="res://core/scripts/camera_3d.gd" id="9_8eblv"]
[ext_resource type="Shader" path="res://core/resources/shaders/vhs.gdshader" id="9_66bpw"]
[ext_resource type="Texture2D" uid="uid://bv7klk2tmhya2" path="res://assets/textures/rgba-noise-medium.png" id="10_ylv8e"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_kpx62"]
bounce = 0.1
[sub_resource type="Animation" id="Animation_a4tqt"]
length = 0.001
tracks/0/type = "value"
@ -1065,7 +1069,7 @@ shadow_mesh = SubResource("ArrayMesh_oy56j")
[sub_resource type="ShaderMaterial" id="ShaderMaterial_pkxv0"]
shader = ExtResource("9_66bpw")
shader_parameter/curvature = 0.5
shader_parameter/curvature = 0.0
shader_parameter/skip = 0.05
shader_parameter/image_flicker = 0.06
shader_parameter/vignette_flicker_speed = 0.0
@ -1079,12 +1083,20 @@ shader_parameter/scanline_thickness = 0.5
shader_parameter/scanlines_spacing = 1.0
shader_parameter/noise_texture = ExtResource("10_ylv8e")
[node name="Drone" type="CharacterBody3D" node_paths=PackedStringArray("camera", "anim_player")]
[node name="Drone" type="RigidBody3D" node_paths=PackedStringArray("camera", "anim_player", "flip_over_detection_ray", "flip_over_timer", "input_suggestion_label")]
collision_layer = 2
collision_mask = 7
mass = 0.5
physics_material_override = SubResource("PhysicsMaterial_kpx62")
can_sleep = false
script = ExtResource("1_de83i")
rotation_speed = 0.08
max_speed = 10.0
camera = NodePath("VisualComponets/CameraPivot/Camera3D")
anim_player = NodePath("AnimationPlayer")
flip_over_detection_ray = NodePath("FlipOverDetectionRay")
flip_over_timer = NodePath("FlipOverTimer")
input_suggestion_label = NodePath("VisualComponets/CameraPivot/Camera3D/CanvasLayer/HUD/VBoxContainer/HBoxContainer/MarginContainer/InputSuggestionLabel")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
@ -1099,6 +1111,13 @@ shape = SubResource("BoxShape3D_idv81")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0269745, 0.000103772)
shape = SubResource("BoxShape3D_8y5u4")
[node name="FlipOverDetectionRay" type="RayCast3D" parent="."]
target_position = Vector3(0, 0.35, 0)
[node name="FlipOverTimer" type="Timer" parent="."]
wait_time = 2.0
one_shot = true
[node name="VisualComponets" type="Node3D" parent="."]
transform = Transform3D(0.01, 0, 0, 0, 0.01, 0, 0, 0, 0.01, 0, 0, 0)
@ -1286,7 +1305,7 @@ skeleton = NodePath("")
surface_material_override/0 = ExtResource("4_ltc6o")
[node name="CameraPivot" type="Node3D" parent="VisualComponets"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.87816, 15.4717)
transform = Transform3D(1, 0, 0, 0, 0.965926, 0.258819, 0, -0.258819, 0.965926, 0, 4.87816, 15.4717)
[node name="camera" type="MeshInstance3D" parent="VisualComponets/CameraPivot"]
transform = Transform3D(2.12178, 0, 0, 0, 2.12178, 0, 0, 0, 1.06089, 0, 0, 0)
@ -1296,8 +1315,8 @@ surface_material_override/0 = ExtResource("2_tgwxr")
[node name="Camera3D" type="Camera3D" parent="VisualComponets/CameraPivot"]
transform = Transform3D(-100, 0, 8.74228e-06, 0, 100, 0, -8.74228e-06, 0, -100, 0, 0, 4.40494)
current = true
near = 0.025
script = ExtResource("9_8eblv")
[node name="CanvasLayer" type="CanvasLayer" parent="VisualComponets/CameraPivot/Camera3D"]
@ -1317,3 +1336,33 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HUD" type="Control" parent="VisualComponets/CameraPivot/Camera3D/CanvasLayer"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="VisualComponets/CameraPivot/Camera3D/CanvasLayer/HUD"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
alignment = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VisualComponets/CameraPivot/Camera3D/CanvasLayer/HUD/VBoxContainer"]
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="VisualComponets/CameraPivot/Camera3D/CanvasLayer/HUD/VBoxContainer/HBoxContainer"]
layout_mode = 2
theme_override_constants/margin_left = 50
theme_override_constants/margin_bottom = 40
[node name="InputSuggestionLabel" type="Label" parent="VisualComponets/CameraPivot/Camera3D/CanvasLayer/HUD/VBoxContainer/HBoxContainer/MarginContainer"]
visible = false
layout_mode = 2
text = "press A to flip drone"

View File

@ -14,10 +14,10 @@ size = Vector2(100, 100)
[node name="TestLevel" type="Node3D"]
[node name="StaticBody3D" type="StaticBody3D" parent="."]
[node name="Ground" type="StaticBody3D" parent="." groups=["Ground"]]
[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"]
shape = SubResource("WorldBoundaryShape3D_bpckr")
[node name="MeshInstance3D" type="MeshInstance3D" parent="StaticBody3D"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Ground"]
mesh = SubResource("PlaneMesh_hj83g")

View File

@ -1,7 +1,9 @@
[gd_scene load_steps=6 format=3 uid="uid://deah8x3tnm045"]
[gd_scene load_steps=9 format=3 uid="uid://deah8x3tnm045"]
[ext_resource type="PackedScene" uid="uid://bfhw7682gnh22" path="res://core/levels/test_level.tscn" id="1_ylfl7"]
[ext_resource type="PackedScene" uid="uid://dwvmna8qc0vb4" path="res://core/drone/drone.tscn" id="2_orkyq"]
[ext_resource type="Script" path="res://core/scripts/camera_3d.gd" id="3_sec6q"]
[ext_resource type="Script" path="res://core/scripts/los_view.gd" id="3_supaf"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_rtxf7"]
sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1)
@ -16,6 +18,13 @@ sky = SubResource("Sky_dsv6k")
tonemap_mode = 2
glow_enabled = true
[sub_resource type="Curve" id="Curve_nxnkk"]
min_value = 1.0
max_value = 90.0
bake_resolution = 1
_data = [Vector2(0, 90), 0.0, -220.055, 0, 0, Vector2(0.0753138, 59.5526), -282.238, -282.238, 0, 0, Vector2(0.449093, 7.72959), -32.7953, -32.7953, 0, 0, Vector2(0.994421, 1), -7.74656, 0.0, 0, 0]
point_count = 4
[node name="Main" type="Node3D"]
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
@ -29,3 +38,13 @@ environment = SubResource("Environment_ruppb")
[node name="Drone" parent="." instance=ExtResource("2_orkyq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.017014, 0)
[node name="LOSView" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.23896, 0.638642, -1.134)
script = ExtResource("3_supaf")
zoom_curve = SubResource("Curve_nxnkk")
[node name="LOSCamera3D" type="Camera3D" parent="LOSView"]
near = 0.002
far = 8000.0
script = ExtResource("3_sec6q")

View File

@ -0,0 +1,16 @@
extends Node3D
@export var camera_array: Array[Camera3D] = []
@export var current_camera: int = 0
func _process(delta):
if camera_array.size() != 0 and Input.is_action_just_released("change_camera_view"):
current_camera += 1
if current_camera <= camera_array.size() - 1:
camera_array[current_camera].make_current()
else:
current_camera = 0
camera_array[current_camera].make_current()
print(current_camera)

View File

@ -0,0 +1,5 @@
extends Camera3D
func _ready():
GameManager.camera_array.append(self)

20
core/scripts/los_view.gd Normal file
View File

@ -0,0 +1,20 @@
extends Node3D
@export var zoom_curve: Curve
var child_camera: Camera3D
var drone: RigidBody3D
var dist_to_drone: float = 0.0
func _ready():
child_camera = get_child(0)
drone = get_parent().get_node("Drone")
func _physics_process(delta):
look_at(drone.global_position)
dist_to_drone = global_position.distance_to(drone.global_position)
child_camera.fov = zoom_curve.sample((dist_to_drone-1)/89)

View File

@ -15,6 +15,10 @@ run/main_scene="res://core/main/main.tscn"
config/features=PackedStringArray("4.3", "Forward Plus")
config/icon="res://icon.svg"
[autoload]
GameManager="*res://core/scripts/GameManager.gd"
[input]
arm={
@ -62,6 +66,16 @@ pitch_backward={
"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":1.0,"script":null)
]
}
accept={
"deadzone": 0.5,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null)
]
}
change_camera_view={
"deadzone": 0.5,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":3,"pressure":0.0,"pressed":true,"script":null)
]
}
[layer_names]