mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
076d27a564
Playing with a gamepad did not work: all six move_* actions had no joypad event at all, so a pad could yaw/pitch/roll/turbo but could not translate. Nothing caught it because every action existed and the game booted fine — no assertion checked that an action is reachable on *both* devices. Controller layout, on the 6DOF convention (left stick aims, right stick translates), using all six of the pad's analog axes for the ship's six degrees of freedom: left stick yaw + pitch right stick strafe + vertical LB / RB roll RT / LT forward / back L3 turbo R3 ball camera Input is now read with Input.get_axis instead of is_action_pressed, so triggers and sticks are proportional. Keyboard values are unchanged. Three rotation bugs found by measuring a real Ship rather than reading the code: - apply_torque() is world-space and the torque was never rotated into the hull's frame (unlike thrust, which uses -ship_basis.z). Roll input became pitch after a 90 degree turn and inverted at 180, so the controls were correct flying up-field and backwards flying back. - ship.tscn's inertia is Vector3(7, 1, 7) but a flat torque was applied to every axis, giving yaw 7x the angular acceleration of pitch and roll (172 deg/s vs 52). Torque is now scaled per-axis by inertia, so rotation_acceleration means rad/s^2 and all three axes match. Yaw is unchanged. - pitch_down pitched the nose UP: get_axis's arguments were reversed, so the I/K keys and the stick each did the opposite of their label. Menus were unusable on a pad for a separate reason: Godot 4.7 gives ui_up/down/left/right joypad events by default but leaves ui_accept and ui_cancel with none (verified against a pristine project), so a controller could move the highlight and never press anything. A confirms and B goes back. Gameplay exits on a new leave_gameplay action (Escape / Start) rather than ui_cancel, so carrying B for menus cannot abandon a live match. Bindings for both devices are rebindable in Settings -> Controls, persisted to user://input.cfg — a separate file from settings.cfg because VideoSettings.save() rewrites that file wholesale and would drop any section it does not know about. project.godot stays the source of truth for defaults; overrides are only ever a delta on top of a boot-time snapshot. Verified: 268 unit tests, the ENet integration gate, and a 16-sample before/after comparison of networked prediction residuals showing the physics change does not regress them (median 0.083m -> 0.065m). Note for follow-up: every policy in Game/bots/ was trained against the old sluggish, world-axis rotation and will over-rotate until retrained.
296 lines
12 KiB
Plaintext
296 lines
12 KiB
Plaintext
[gd_scene load_steps=4 format=3]
|
|
|
|
[ext_resource type="Script" path="res://scripts/settings_menu.gd" id="1_settings"]
|
|
[ext_resource type="Theme" path="res://themes/cosmic_clash_theme.tres" id="2_theme"]
|
|
[ext_resource type="Script" path="res://scripts/controls_settings.gd" id="3_controls"]
|
|
|
|
[node name="SettingsMenu" type="Control"]
|
|
layout_mode = 3
|
|
anchors_preset = 15
|
|
anchor_right = 1.0
|
|
anchor_bottom = 1.0
|
|
grow_horizontal = 2
|
|
grow_vertical = 2
|
|
script = ExtResource("1_settings")
|
|
theme = ExtResource("2_theme")
|
|
|
|
[node name="MarginContainer" type="MarginContainer" parent="."]
|
|
layout_mode = 1
|
|
anchors_preset = 15
|
|
anchor_right = 1.0
|
|
anchor_bottom = 1.0
|
|
grow_horizontal = 2
|
|
grow_vertical = 2
|
|
theme_override_constants/margin_left = 24
|
|
theme_override_constants/margin_top = 24
|
|
theme_override_constants/margin_right = 24
|
|
theme_override_constants/margin_bottom = 24
|
|
|
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="TitleLabel" type="Label" parent="MarginContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_font_sizes/font_size = 36
|
|
text = "Settings"
|
|
horizontal_alignment = 1
|
|
|
|
[node name="TabContainer" type="TabContainer" parent="MarginContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
size_flags_vertical = 3
|
|
tab_alignment = 1
|
|
|
|
[node name="Video" type="ScrollContainer" parent="MarginContainer/VBoxContainer/TabContainer"]
|
|
layout_mode = 2
|
|
follow_focus = true
|
|
horizontal_scroll_mode = 0
|
|
|
|
[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video"]
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
size_flags_vertical = 3
|
|
|
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer"]
|
|
custom_minimum_size = Vector2(420, 0)
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="PresetRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="PresetLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/PresetRow"]
|
|
custom_minimum_size = Vector2(110, 0)
|
|
layout_mode = 2
|
|
text = "Graphics preset"
|
|
|
|
[node name="PresetDropdown" type="OptionButton" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/PresetRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 40)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
|
|
[node name="AARow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="AALabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/AARow"]
|
|
custom_minimum_size = Vector2(110, 0)
|
|
layout_mode = 2
|
|
text = "Anti-aliasing"
|
|
|
|
[node name="AADropdown" type="OptionButton" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/AARow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 40)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
|
|
[node name="ResolutionRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="ResolutionLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/ResolutionRow"]
|
|
custom_minimum_size = Vector2(110, 0)
|
|
layout_mode = 2
|
|
text = "Resolution scale"
|
|
|
|
[node name="ResolutionSlider" type="HSlider" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/ResolutionRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 24)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
size_flags_vertical = 4
|
|
min_value = 0.5
|
|
max_value = 1.0
|
|
step = 0.05
|
|
value = 1.0
|
|
|
|
[node name="ResolutionValueLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/ResolutionRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(48, 0)
|
|
layout_mode = 2
|
|
text = "100%"
|
|
horizontal_alignment = 2
|
|
|
|
[node name="GlowRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="GlowLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/GlowRow"]
|
|
custom_minimum_size = Vector2(110, 0)
|
|
layout_mode = 2
|
|
text = "Glow intensity"
|
|
|
|
[node name="GlowSlider" type="HSlider" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/GlowRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 24)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
size_flags_vertical = 4
|
|
min_value = 0.0
|
|
max_value = 1.5
|
|
step = 0.05
|
|
value = 1.0
|
|
|
|
[node name="GlowValueLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/GlowRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(48, 0)
|
|
layout_mode = 2
|
|
text = "100%"
|
|
horizontal_alignment = 2
|
|
|
|
[node name="BrightnessRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="BrightnessLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/BrightnessRow"]
|
|
custom_minimum_size = Vector2(110, 0)
|
|
layout_mode = 2
|
|
text = "Brightness"
|
|
|
|
[node name="BrightnessSlider" type="HSlider" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/BrightnessRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 24)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
size_flags_vertical = 4
|
|
min_value = 0.7
|
|
max_value = 1.3
|
|
step = 0.02
|
|
value = 1.0
|
|
|
|
[node name="BrightnessValueLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/BrightnessRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(48, 0)
|
|
layout_mode = 2
|
|
text = "100%"
|
|
horizontal_alignment = 2
|
|
|
|
[node name="VsyncRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="VsyncLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/VsyncRow"]
|
|
custom_minimum_size = Vector2(110, 0)
|
|
layout_mode = 2
|
|
text = "VSync"
|
|
|
|
[node name="VsyncDropdown" type="OptionButton" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/VsyncRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 40)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
|
|
[node name="FpsCapRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="FpsCapLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/FpsCapRow"]
|
|
custom_minimum_size = Vector2(110, 0)
|
|
layout_mode = 2
|
|
text = "FPS cap"
|
|
|
|
[node name="FpsCapDropdown" type="OptionButton" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/FpsCapRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 40)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
|
|
[node name="FpsReadoutRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="FpsReadoutTitleLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/FpsReadoutRow"]
|
|
custom_minimum_size = Vector2(110, 0)
|
|
layout_mode = 2
|
|
text = "Current"
|
|
|
|
[node name="FpsReadoutLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/FpsReadoutRow"]
|
|
unique_name_in_owner = true
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
text = "0 fps"
|
|
|
|
[node name="Controls" type="ScrollContainer" parent="MarginContainer/VBoxContainer/TabContainer"]
|
|
visible = false
|
|
layout_mode = 2
|
|
follow_focus = true
|
|
horizontal_scroll_mode = 0
|
|
script = ExtResource("3_controls")
|
|
|
|
[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/VBoxContainer/TabContainer/Controls"]
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
size_flags_vertical = 3
|
|
|
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer"]
|
|
custom_minimum_size = Vector2(520, 0)
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="DeviceRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer/VBoxContainer"]
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 10
|
|
|
|
[node name="DeviceLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer/VBoxContainer/DeviceRow"]
|
|
custom_minimum_size = Vector2(160, 0)
|
|
layout_mode = 2
|
|
text = "Device"
|
|
|
|
[node name="KeyboardButton" type="Button" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer/VBoxContainer/DeviceRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 40)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
toggle_mode = true
|
|
button_pressed = true
|
|
text = "Keyboard"
|
|
|
|
[node name="ControllerButton" type="Button" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer/VBoxContainer/DeviceRow"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 40)
|
|
layout_mode = 2
|
|
size_flags_horizontal = 3
|
|
toggle_mode = true
|
|
text = "Controller"
|
|
|
|
[node name="StatusLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer/VBoxContainer"]
|
|
unique_name_in_owner = true
|
|
modulate = Color(1, 0.85, 0.5, 1)
|
|
layout_mode = 2
|
|
theme_override_font_sizes/font_size = 13
|
|
text = ""
|
|
autowrap_mode = 2
|
|
|
|
[node name="BindingList" type="VBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer/VBoxContainer"]
|
|
unique_name_in_owner = true
|
|
layout_mode = 2
|
|
theme_override_constants/separation = 6
|
|
|
|
[node name="InvertPitchCheck" type="CheckBox" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer/VBoxContainer"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 40)
|
|
layout_mode = 2
|
|
text = "Invert pitch"
|
|
|
|
[node name="ResetButton" type="Button" parent="MarginContainer/VBoxContainer/TabContainer/Controls/CenterContainer/VBoxContainer"]
|
|
unique_name_in_owner = true
|
|
custom_minimum_size = Vector2(0, 44)
|
|
layout_mode = 2
|
|
text = "Reset all bindings to defaults"
|
|
|
|
[node name="BackButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
|
custom_minimum_size = Vector2(0, 56)
|
|
layout_mode = 2
|
|
text = "Back"
|
|
|
|
[connection signal="item_selected" from="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/PresetRow/PresetDropdown" to="." method="_on_preset_dropdown_item_selected"]
|
|
[connection signal="item_selected" from="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/AARow/AADropdown" to="." method="_on_aa_dropdown_item_selected"]
|
|
[connection signal="value_changed" from="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/ResolutionRow/ResolutionSlider" to="." method="_on_resolution_slider_value_changed"]
|
|
[connection signal="value_changed" from="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/GlowRow/GlowSlider" to="." method="_on_glow_slider_value_changed"]
|
|
[connection signal="value_changed" from="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/BrightnessRow/BrightnessSlider" to="." method="_on_brightness_slider_value_changed"]
|
|
[connection signal="item_selected" from="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/VsyncRow/VsyncDropdown" to="." method="_on_vsync_dropdown_item_selected"]
|
|
[connection signal="item_selected" from="MarginContainer/VBoxContainer/TabContainer/Video/CenterContainer/VBoxContainer/FpsCapRow/FpsCapDropdown" to="." method="_on_fps_cap_dropdown_item_selected"]
|
|
[connection signal="pressed" from="MarginContainer/VBoxContainer/BackButton" to="." method="_on_back_pressed"]
|