Compare commits
10
Commits
LAWDev
..
0d3686ed37
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d3686ed37 | ||
|
|
ca898b0d09 | ||
|
|
e013ef7875 | ||
|
|
4256b2001f | ||
|
|
695c8de124 | ||
|
|
0e03ced3c6 | ||
|
|
8feb7bbc47 | ||
|
|
d751b677c3 | ||
|
|
f87278323d | ||
|
|
5893123adb |
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://de2e8sy4x724m"
|
||||
path="res://.godot/imported/jump.ogg-09aff86a6f79a8fce2febb69902962cf.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/jump.ogg"
|
||||
dest_files=["res://.godot/imported/jump.ogg-09aff86a6f79a8fce2febb69902962cf.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=false
|
||||
loop_offset=0
|
||||
bpm=0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://64dplcgx2icb"
|
||||
path="res://.godot/imported/silly-menu-hover-test.ogg-101de051c9810c756b28483653a4c618.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/silly-menu-hover-test.ogg"
|
||||
dest_files=["res://.godot/imported/silly-menu-hover-test.ogg-101de051c9810c756b28483653a4c618.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=false
|
||||
loop_offset=0
|
||||
bpm=0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://txgki0ijeuud"
|
||||
path="res://.godot/imported/silly-test.ogg-4a08df8a26b9ee1e5d13235e013c7cfc.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/silly-test.ogg"
|
||||
dest_files=["res://.godot/imported/silly-test.ogg-4a08df8a26b9ee1e5d13235e013c7cfc.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=false
|
||||
loop_offset=0
|
||||
bpm=0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
@@ -0,0 +1,3 @@
|
||||
[gd_scene format=3 uid="uid://cuyws13lbkmxb"]
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
@@ -0,0 +1,12 @@
|
||||
[gd_resource type="AudioBusLayout" format=3]
|
||||
|
||||
[resource]
|
||||
bus/0/name = "Master"
|
||||
bus/0/volume_db = 0.0
|
||||
bus/0/send = ""
|
||||
bus/1/name = "Music"
|
||||
bus/1/volume_db = 0.0
|
||||
bus/1/send = "Master"
|
||||
bus/2/name = "SFX"
|
||||
bus/2/volume_db = 0.0
|
||||
bus/2/send = "Master"
|
||||
@@ -15,6 +15,15 @@ run/main_scene="uid://b4k81taauef4q"
|
||||
config/features=PackedStringArray("4.5", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[audio]
|
||||
|
||||
bus_layout="res://audio/bus_layout.tres"
|
||||
|
||||
[autoload]
|
||||
|
||||
MenuMusic="*res://scenes/UI/menu_music.tscn"
|
||||
MenuSfx="*res://scenes/UI/menu_sfx.tscn"
|
||||
|
||||
[dotnet]
|
||||
|
||||
project/assembly_name="Promiscuity"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
[gd_scene load_steps=9 format=3 uid="uid://dchj6g2i8ebph"]
|
||||
[gd_scene load_steps=11 format=3 uid="uid://dchj6g2i8ebph"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bpxggc8nr6tf6" path="res://scenes/player.gd" id="2_w7c3h"]
|
||||
[ext_resource type="Script" uid="uid://bpxggc8nr6tf6" path="res://scenes/player.gd" id="1_muv8p"]
|
||||
[ext_resource type="PackedScene" uid="uid://c5of6aaxop1hl" path="res://scenes/block.tscn" id="2_tc7dm"]
|
||||
[ext_resource type="Script" uid="uid://b7fopt7sx74g8" path="res://scenes/Levels/menu.gd" id="3_tc7dm"]
|
||||
|
||||
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_2q6dc"]
|
||||
bounce = 0.5
|
||||
@@ -39,14 +41,14 @@ mesh = SubResource("SphereMesh_w7c3h")
|
||||
|
||||
[node name="Player" type="RigidBody3D" parent="."]
|
||||
physics_material_override = SubResource("PhysicsMaterial_w8frs")
|
||||
gravity_scale = 0.0
|
||||
script = ExtResource("2_w7c3h")
|
||||
script = ExtResource("1_muv8p")
|
||||
camera_path = NodePath("Camera3D")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="Player"]
|
||||
shape = SubResource("SphereShape3D_mx8sn")
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="Player"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.31670225, 0)
|
||||
|
||||
[node name="Ground" type="StaticBody3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0)
|
||||
@@ -60,3 +62,51 @@ mesh = SubResource("BoxMesh_w7c3h")
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.5, 0.8660253, 0, -0.8660253, 0.5, 0, 34, 0)
|
||||
shadow_enabled = true
|
||||
|
||||
[node name="Starter Blocks" type="Node3D" parent="."]
|
||||
|
||||
[node name="Block" parent="Starter Blocks" instance=ExtResource("2_tc7dm")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.298158, -7.0724635)
|
||||
|
||||
[node name="Block2" parent="Starter Blocks" instance=ExtResource("2_tc7dm")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.63255787, 2.596316, -6.980046)
|
||||
|
||||
[node name="Menu" type="CanvasLayer" parent="."]
|
||||
process_mode = 3
|
||||
visible = false
|
||||
script = ExtResource("3_tc7dm")
|
||||
|
||||
[node name="Control" type="Control" parent="Menu"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 4
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Menu/Control"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -39.5
|
||||
offset_top = -33.0
|
||||
offset_right = 39.5
|
||||
offset_bottom = 33.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="ContinueButton" type="Button" parent="Menu/Control/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Continue"
|
||||
|
||||
[node name="QuitButton" type="Button" parent="Menu/Control/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Quit"
|
||||
|
||||
[connection signal="pressed" from="Menu/Control/VBoxContainer/ContinueButton" to="Menu" method="_on_continue_button_pressed"]
|
||||
[connection signal="pressed" from="Menu/Control/VBoxContainer/QuitButton" to="Menu" method="_on_quit_button_pressed"]
|
||||
@@ -0,0 +1,45 @@
|
||||
extends CanvasLayer
|
||||
|
||||
@onready var pause_menu = $Control
|
||||
|
||||
func _ready() -> void:
|
||||
_register_focus_sounds()
|
||||
|
||||
func _input(event):
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
if get_tree().paused:
|
||||
resume_game()
|
||||
else:
|
||||
pause_game()
|
||||
|
||||
func pause_game():
|
||||
get_tree().paused = true
|
||||
visible = true
|
||||
|
||||
func resume_game():
|
||||
get_tree().paused = false
|
||||
visible = false
|
||||
|
||||
func _on_quit_button_pressed():
|
||||
get_tree().quit()
|
||||
|
||||
func _on_continue_button_pressed():
|
||||
resume_game()
|
||||
|
||||
func _register_focus_sounds() -> void:
|
||||
if pause_menu == null:
|
||||
return
|
||||
var vbox := pause_menu.get_node_or_null("VBoxContainer")
|
||||
if vbox == null:
|
||||
return
|
||||
for child in vbox.get_children():
|
||||
if child is BaseButton:
|
||||
var button: BaseButton = child
|
||||
if not button.is_connected("focus_entered", Callable(self, "_on_menu_item_focus")):
|
||||
button.focus_entered.connect(_on_menu_item_focus)
|
||||
if not button.is_connected("mouse_entered", Callable(self, "_on_menu_item_focus")):
|
||||
button.mouse_entered.connect(_on_menu_item_focus)
|
||||
|
||||
func _on_menu_item_focus() -> void:
|
||||
if MenuSfx:
|
||||
MenuSfx.play_hover()
|
||||
@@ -0,0 +1 @@
|
||||
uid://b7fopt7sx74g8
|
||||
@@ -1,5 +0,0 @@
|
||||
extends Node
|
||||
|
||||
func _input(event):
|
||||
if event.is_action_pressed("ui_cancel"): # 'ui_cancel' is a built-in action defined in Project > Project Settings > Input Map
|
||||
get_tree().change_scene_to_file("res://scenes/start_screen.tscn")
|
||||
@@ -1,44 +0,0 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://d3tqrm4ry4l88"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://h1slqbemgwvr" path="res://scenes/Settings.gd" id="1_1dggd"]
|
||||
[ext_resource type="Texture2D" uid="uid://dhuosr0p605gj" path="res://assets/images/pp_start_bg.png" id="1_i47rn"]
|
||||
[ext_resource type="FontFile" uid="uid://m5ceou0rk6j6" path="res://assets/fonts/PlayfairDisplay-VariableFont_wght.ttf" id="2_46duy"]
|
||||
[ext_resource type="Theme" uid="uid://wpxmub0n2dr3" path="res://themes/button_theme.tres" id="3_46duy"]
|
||||
|
||||
[node name="settings_screen" type="Node2D"]
|
||||
script = ExtResource("1_1dggd")
|
||||
metadata/_edit_vertical_guides_ = [1152.0]
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="."]
|
||||
offset_left = -192.0
|
||||
offset_top = -188.0
|
||||
offset_right = 1344.0
|
||||
offset_bottom = 836.0
|
||||
texture = ExtResource("1_i47rn")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 648.0
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("2_46duy")
|
||||
theme_override_font_sizes/font_size = 42
|
||||
text = "Settings"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="TabBar" type="TabBar" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("3_46duy")
|
||||
current_tab = 0
|
||||
tab_count = 4
|
||||
tab_0/title = "Gameplay"
|
||||
tab_1/title = "Video"
|
||||
tab_2/title = "Audio"
|
||||
tab_3/title = "Dev"
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
@@ -0,0 +1,112 @@
|
||||
extends Node2D
|
||||
|
||||
@onready var _tab_bar: TabBar = $MarginContainer/VBoxContainer/TabBar
|
||||
@onready var _tab_container: TabContainer = $MarginContainer/VBoxContainer/TabContainer
|
||||
@onready var _music_volume_slider: HSlider = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup/MusicVolumeSlider
|
||||
@onready var _music_volume_value: Label = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup/MusicVolumeValue
|
||||
@onready var _music_mute_checkbox: CheckBox = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup/MusicMuteCheckBox
|
||||
@onready var _sfx_volume_slider: HSlider = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/SfxVolumeGroup/SfxVolumeSlider
|
||||
@onready var _sfx_volume_value: Label = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/SfxVolumeGroup/SfxVolumeValue
|
||||
@onready var _sfx_mute_checkbox: CheckBox = $MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/SfxVolumeGroup/SfxMuteCheckBox
|
||||
@onready var _menu_music: AudioStreamPlayer = get_tree().get_root().get_node_or_null("MenuMusic")
|
||||
@onready var _menu_sfx: AudioStreamPlayer = get_tree().get_root().get_node_or_null("MenuSfx")
|
||||
|
||||
func _ready() -> void:
|
||||
_tab_bar.tab_changed.connect(_on_tab_bar_tab_changed)
|
||||
_tab_container.tab_changed.connect(_on_tab_container_tab_changed)
|
||||
_tab_container.current_tab = _tab_bar.current_tab
|
||||
_music_volume_slider.value_changed.connect(_on_music_volume_changed)
|
||||
_music_mute_checkbox.toggled.connect(_on_music_mute_toggled)
|
||||
_sfx_volume_slider.value_changed.connect(_on_sfx_volume_changed)
|
||||
_sfx_mute_checkbox.toggled.connect(_on_sfx_mute_toggled)
|
||||
_sync_audio_controls()
|
||||
_register_focus_sounds()
|
||||
|
||||
func _input(event):
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
get_tree().change_scene_to_file("uid://b4k81taauef4q")
|
||||
|
||||
func _on_tab_bar_tab_changed(tab_index: int) -> void:
|
||||
if _tab_container.current_tab != tab_index:
|
||||
_tab_container.current_tab = tab_index
|
||||
|
||||
func _on_tab_container_tab_changed(tab_index: int) -> void:
|
||||
if _tab_bar.current_tab != tab_index:
|
||||
_tab_bar.current_tab = tab_index
|
||||
|
||||
func _sync_audio_controls() -> void:
|
||||
var value: float = 0.7
|
||||
var muted: bool = false
|
||||
if _menu_music:
|
||||
if _menu_music.has_method("get_user_volume"):
|
||||
value = _menu_music.get_user_volume()
|
||||
if _menu_music.has_method("is_user_muted"):
|
||||
muted = _menu_music.is_user_muted()
|
||||
_apply_audio_control_state(_music_volume_slider, _music_mute_checkbox, _music_volume_value, value, muted)
|
||||
|
||||
var sfx_value: float = 0.7
|
||||
var sfx_muted: bool = false
|
||||
if _menu_sfx:
|
||||
if _menu_sfx.has_method("get_user_volume"):
|
||||
sfx_value = _menu_sfx.get_user_volume()
|
||||
if _menu_sfx.has_method("is_user_muted"):
|
||||
sfx_muted = _menu_sfx.is_user_muted()
|
||||
_apply_audio_control_state(_sfx_volume_slider, _sfx_mute_checkbox, _sfx_volume_value, sfx_value, sfx_muted)
|
||||
|
||||
func _on_music_volume_changed(value: float) -> void:
|
||||
if _menu_music and _menu_music.has_method("set_user_volume"):
|
||||
_menu_music.set_user_volume(value)
|
||||
_update_volume_label(_music_volume_value, value, _music_mute_checkbox.button_pressed)
|
||||
|
||||
func _on_music_mute_toggled(pressed: bool) -> void:
|
||||
if _menu_music and _menu_music.has_method("set_user_muted"):
|
||||
_menu_music.set_user_muted(pressed)
|
||||
_music_volume_slider.editable = not pressed
|
||||
_update_volume_label(_music_volume_value, _music_volume_slider.value, pressed)
|
||||
|
||||
func _on_sfx_volume_changed(value: float) -> void:
|
||||
if _menu_sfx and _menu_sfx.has_method("set_user_volume"):
|
||||
_menu_sfx.set_user_volume(value)
|
||||
_update_volume_label(_sfx_volume_value, value, _sfx_mute_checkbox.button_pressed)
|
||||
|
||||
func _on_sfx_mute_toggled(pressed: bool) -> void:
|
||||
if _menu_sfx and _menu_sfx.has_method("set_user_muted"):
|
||||
_menu_sfx.set_user_muted(pressed)
|
||||
_sfx_volume_slider.editable = not pressed
|
||||
_update_volume_label(_sfx_volume_value, _sfx_volume_slider.value, pressed)
|
||||
|
||||
func _apply_audio_control_state(slider: HSlider, checkbox: CheckBox, value_label: Label, value: float, muted: bool) -> void:
|
||||
slider.set_block_signals(true)
|
||||
slider.value = value
|
||||
slider.set_block_signals(false)
|
||||
slider.editable = not muted
|
||||
checkbox.set_block_signals(true)
|
||||
checkbox.button_pressed = muted
|
||||
checkbox.set_block_signals(false)
|
||||
_update_volume_label(value_label, value, muted)
|
||||
|
||||
func _update_volume_label(value_label: Label, value: float, muted: bool) -> void:
|
||||
if muted:
|
||||
value_label.text = "Muted"
|
||||
else:
|
||||
var percent: int = int(round(value * 100.0))
|
||||
value_label.text = str(percent) + "%"
|
||||
|
||||
func _register_focus_sounds() -> void:
|
||||
_connect_focus_recursive(self)
|
||||
|
||||
func _connect_focus_recursive(node: Node) -> void:
|
||||
if node is Control:
|
||||
var control: Control = node
|
||||
if control.focus_mode != Control.FOCUS_NONE:
|
||||
if not control.is_connected("focus_entered", Callable(self, "_on_menu_item_focus")):
|
||||
control.focus_entered.connect(_on_menu_item_focus)
|
||||
if control.has_signal("mouse_entered") and (control is BaseButton or control.focus_mode != Control.FOCUS_NONE):
|
||||
if not control.is_connected("mouse_entered", Callable(self, "_on_menu_item_focus")):
|
||||
control.mouse_entered.connect(_on_menu_item_focus)
|
||||
for child in node.get_children():
|
||||
_connect_focus_recursive(child)
|
||||
|
||||
func _on_menu_item_focus() -> void:
|
||||
if MenuSfx:
|
||||
MenuSfx.play_hover()
|
||||
@@ -0,0 +1,157 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://d3tqrm4ry4l88"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://h1slqbemgwvr" path="res://scenes/UI/Settings.gd" id="1_1dggd"]
|
||||
[ext_resource type="Texture2D" uid="uid://dhuosr0p605gj" path="res://assets/images/pp_start_bg.png" id="1_i47rn"]
|
||||
[ext_resource type="FontFile" uid="uid://m5ceou0rk6j6" path="res://assets/fonts/PlayfairDisplay-VariableFont_wght.ttf" id="2_46duy"]
|
||||
[ext_resource type="Theme" uid="uid://wpxmub0n2dr3" path="res://themes/button_theme.tres" id="3_46duy"]
|
||||
|
||||
|
||||
[node name="settings_screen" type="Node2D"]
|
||||
script = ExtResource("1_1dggd")
|
||||
metadata/_edit_vertical_guides_ = [1152.0]
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="."]
|
||||
offset_left = -192.0
|
||||
offset_top = -188.0
|
||||
offset_right = 1344.0
|
||||
offset_bottom = 836.0
|
||||
texture = ExtResource("1_i47rn")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
offset_right = 1152.0
|
||||
offset_bottom = 648.0
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("2_46duy")
|
||||
theme_override_font_sizes/font_size = 42
|
||||
text = "Settings"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="TabBar" type="TabBar" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme = ExtResource("3_46duy")
|
||||
current_tab = 0
|
||||
tab_count = 4
|
||||
tab_0/title = "Gameplay"
|
||||
tab_1/title = "Video"
|
||||
tab_2/title = "Audio"
|
||||
tab_3/title = "Dev"
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
tabs_visible = false
|
||||
|
||||
[node name="Gameplay" type="Control" parent="MarginContainer/VBoxContainer/TabContainer"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Video" type="Control" parent="MarginContainer/VBoxContainer/TabContainer"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Audio" type="Control" parent="MarginContainer/VBoxContainer/TabContainer"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="AudioVBox" type="VBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Audio"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_constants/separation = 10
|
||||
offset_left = 120.0
|
||||
offset_top = 240.0
|
||||
offset_right = -120.0
|
||||
offset_bottom = -40.0
|
||||
|
||||
[node name="MusicVolumeLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox"]
|
||||
layout_mode = 2
|
||||
text = "Music Volume"
|
||||
horizontal_alignment = 1
|
||||
size_flags_horizontal = 4
|
||||
|
||||
[node name="MusicVolumeGroup" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_constants/separation = 12
|
||||
alignment = 1
|
||||
custom_minimum_size = Vector2(0, 40)
|
||||
|
||||
[node name="MusicVolumeSlider" type="HSlider" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup"]
|
||||
layout_mode = 2
|
||||
min_value = 0.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
size_flags_horizontal = 3
|
||||
custom_minimum_size = Vector2(320, 0)
|
||||
|
||||
[node name="MusicVolumeValue" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup"]
|
||||
layout_mode = 2
|
||||
text = "70%"
|
||||
size_flags_horizontal = 1
|
||||
horizontal_alignment = 1
|
||||
custom_minimum_size = Vector2(60, 0)
|
||||
|
||||
[node name="MusicMuteCheckBox" type="CheckBox" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/MusicVolumeGroup"]
|
||||
layout_mode = 2
|
||||
text = "Mute"
|
||||
size_flags_horizontal = 1
|
||||
|
||||
[node name="SfxVolumeLabel" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox"]
|
||||
layout_mode = 2
|
||||
text = "Menu SFX Volume"
|
||||
horizontal_alignment = 1
|
||||
size_flags_horizontal = 4
|
||||
|
||||
[node name="SfxVolumeGroup" type="HBoxContainer" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_constants/separation = 12
|
||||
alignment = 1
|
||||
custom_minimum_size = Vector2(0, 40)
|
||||
|
||||
[node name="SfxVolumeSlider" type="HSlider" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/SfxVolumeGroup"]
|
||||
layout_mode = 2
|
||||
min_value = 0.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
size_flags_horizontal = 3
|
||||
custom_minimum_size = Vector2(320, 0)
|
||||
|
||||
[node name="SfxVolumeValue" type="Label" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/SfxVolumeGroup"]
|
||||
layout_mode = 2
|
||||
text = "70%"
|
||||
size_flags_horizontal = 1
|
||||
horizontal_alignment = 1
|
||||
custom_minimum_size = Vector2(60, 0)
|
||||
|
||||
[node name="SfxMuteCheckBox" type="CheckBox" parent="MarginContainer/VBoxContainer/TabContainer/Audio/AudioVBox/SfxVolumeGroup"]
|
||||
layout_mode = 2
|
||||
text = "Mute"
|
||||
size_flags_horizontal = 1
|
||||
|
||||
[node name="Dev" type="Control" parent="MarginContainer/VBoxContainer/TabContainer"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
@@ -0,0 +1,106 @@
|
||||
extends AudioStreamPlayer
|
||||
|
||||
const MENU_SCENES: Dictionary = {
|
||||
"res://scenes/UI/start_screen.tscn": true,
|
||||
"res://scenes/UI/Settings.tscn": true,
|
||||
}
|
||||
|
||||
const CONFIG_PATH := "user://settings.cfg"
|
||||
const CONFIG_SECTION := "audio"
|
||||
const CONFIG_KEY_MUSIC_VOLUME := "menu_music_volume"
|
||||
const CONFIG_KEY_MUSIC_MUTED := "menu_music_muted"
|
||||
const DEFAULT_VOLUME := 0.7
|
||||
|
||||
var _last_scene: Node = null
|
||||
var _user_volume_linear: float = DEFAULT_VOLUME
|
||||
var _is_muted: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
set_process(true)
|
||||
_load_settings()
|
||||
_apply_volume()
|
||||
_update_playback(get_tree().current_scene)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
var current := get_tree().current_scene
|
||||
if current != _last_scene:
|
||||
_update_playback(current)
|
||||
elif _should_play_scene(current) and not playing and not _is_muted and _user_volume_linear > 0.0:
|
||||
play()
|
||||
|
||||
func _update_playback(scene: Node) -> void:
|
||||
if scene == null:
|
||||
_last_scene = null
|
||||
return
|
||||
_last_scene = scene
|
||||
if _should_play_scene(scene):
|
||||
if not playing:
|
||||
play()
|
||||
elif playing:
|
||||
stop()
|
||||
|
||||
func _should_play_scene(scene: Node) -> bool:
|
||||
if scene == null:
|
||||
return false
|
||||
var scene_path: String = scene.get_scene_file_path()
|
||||
if scene_path.is_empty():
|
||||
return false
|
||||
return MENU_SCENES.has(scene_path)
|
||||
|
||||
func set_user_volume(value: float) -> void:
|
||||
var clamped_value: float = clamp(value, 0.0, 1.0)
|
||||
if is_equal_approx(_user_volume_linear, clamped_value):
|
||||
return
|
||||
_user_volume_linear = clamped_value
|
||||
_apply_volume()
|
||||
_save_settings()
|
||||
|
||||
func get_user_volume() -> float:
|
||||
return _user_volume_linear
|
||||
|
||||
func set_user_muted(muted: bool) -> void:
|
||||
var new_muted: bool = muted
|
||||
if _is_muted == new_muted:
|
||||
return
|
||||
_is_muted = new_muted
|
||||
_apply_volume()
|
||||
_save_settings()
|
||||
|
||||
func is_user_muted() -> bool:
|
||||
return _is_muted
|
||||
|
||||
func _apply_volume() -> void:
|
||||
if _is_muted or _user_volume_linear <= 0.0:
|
||||
volume_db = -80.0
|
||||
else:
|
||||
volume_db = linear_to_db(_user_volume_linear)
|
||||
|
||||
func _load_settings() -> void:
|
||||
var config: ConfigFile = ConfigFile.new()
|
||||
var err: int = config.load(CONFIG_PATH)
|
||||
if err == OK:
|
||||
var stored_volume: float = float(config.get_value(CONFIG_SECTION, CONFIG_KEY_MUSIC_VOLUME, DEFAULT_VOLUME))
|
||||
_user_volume_linear = clamp(stored_volume, 0.0, 1.0)
|
||||
var stored_muted: bool = bool(config.get_value(CONFIG_SECTION, CONFIG_KEY_MUSIC_MUTED, false))
|
||||
_is_muted = stored_muted
|
||||
elif err == ERR_DOES_NOT_EXIST:
|
||||
_user_volume_linear = DEFAULT_VOLUME
|
||||
_is_muted = false
|
||||
else:
|
||||
push_warning("Failed to load settings.cfg: %s" % err)
|
||||
_user_volume_linear = DEFAULT_VOLUME
|
||||
_is_muted = false
|
||||
|
||||
func _save_settings() -> void:
|
||||
var config: ConfigFile = ConfigFile.new()
|
||||
var err: int = config.load(CONFIG_PATH)
|
||||
if err != OK and err != ERR_DOES_NOT_EXIST:
|
||||
push_warning("Failed to load settings.cfg before saving: %s" % err)
|
||||
config = ConfigFile.new()
|
||||
elif err != OK:
|
||||
config = ConfigFile.new()
|
||||
config.set_value(CONFIG_SECTION, CONFIG_KEY_MUSIC_VOLUME, _user_volume_linear)
|
||||
config.set_value(CONFIG_SECTION, CONFIG_KEY_MUSIC_MUTED, _is_muted)
|
||||
var save_err: int = config.save(CONFIG_PATH)
|
||||
if save_err != OK:
|
||||
push_warning("Failed to save settings.cfg: %s" % save_err)
|
||||
@@ -0,0 +1 @@
|
||||
uid://l0cqi7dvoou3
|
||||
@@ -0,0 +1,13 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dfmq1n507y7d3"]
|
||||
|
||||
[ext_resource type="AudioStream" uid="uid://txgki0ijeuud" path="res://assets/audio/silly-test.ogg" id="1_ek0t3"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/UI/menu_music.gd" id="2_21d4q"]
|
||||
|
||||
[node name="MenuMusic" type="AudioStreamPlayer"]
|
||||
bus = &"Music"
|
||||
stream = ExtResource("1_ek0t3")
|
||||
autoplay = true
|
||||
volume_db = -3.0
|
||||
priority = 10.0
|
||||
script = ExtResource("2_21d4q")
|
||||
@@ -0,0 +1,76 @@
|
||||
extends AudioStreamPlayer
|
||||
|
||||
const CONFIG_PATH := "user://settings.cfg"
|
||||
const CONFIG_SECTION := "audio"
|
||||
const CONFIG_KEY_VOLUME := "menu_sfx_volume"
|
||||
const CONFIG_KEY_MUTED := "menu_sfx_muted"
|
||||
const DEFAULT_VOLUME := 0.7
|
||||
|
||||
var _user_volume_linear: float = DEFAULT_VOLUME
|
||||
var _is_muted: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
_load_settings()
|
||||
_apply_volume()
|
||||
|
||||
func play_hover() -> void:
|
||||
if stream == null or _is_muted or _user_volume_linear <= 0.0:
|
||||
return
|
||||
play(0.0)
|
||||
|
||||
func set_user_volume(value: float) -> void:
|
||||
var clamped_value: float = clamp(value, 0.0, 1.0)
|
||||
if is_equal_approx(_user_volume_linear, clamped_value):
|
||||
return
|
||||
_user_volume_linear = clamped_value
|
||||
_apply_volume()
|
||||
_save_settings()
|
||||
|
||||
func get_user_volume() -> float:
|
||||
return _user_volume_linear
|
||||
|
||||
func set_user_muted(muted: bool) -> void:
|
||||
if _is_muted == muted:
|
||||
return
|
||||
_is_muted = muted
|
||||
_apply_volume()
|
||||
_save_settings()
|
||||
if _is_muted:
|
||||
stop()
|
||||
|
||||
func is_user_muted() -> bool:
|
||||
return _is_muted
|
||||
|
||||
func _apply_volume() -> void:
|
||||
if _is_muted or _user_volume_linear <= 0.0:
|
||||
volume_db = -80.0
|
||||
else:
|
||||
volume_db = linear_to_db(_user_volume_linear)
|
||||
|
||||
func _load_settings() -> void:
|
||||
var config: ConfigFile = ConfigFile.new()
|
||||
var err: int = config.load(CONFIG_PATH)
|
||||
if err == OK:
|
||||
_user_volume_linear = clamp(float(config.get_value(CONFIG_SECTION, CONFIG_KEY_VOLUME, DEFAULT_VOLUME)), 0.0, 1.0)
|
||||
_is_muted = bool(config.get_value(CONFIG_SECTION, CONFIG_KEY_MUTED, false))
|
||||
elif err == ERR_DOES_NOT_EXIST:
|
||||
_user_volume_linear = DEFAULT_VOLUME
|
||||
_is_muted = false
|
||||
else:
|
||||
push_warning("Failed to load settings.cfg: %s" % err)
|
||||
_user_volume_linear = DEFAULT_VOLUME
|
||||
_is_muted = false
|
||||
|
||||
func _save_settings() -> void:
|
||||
var config: ConfigFile = ConfigFile.new()
|
||||
var err: int = config.load(CONFIG_PATH)
|
||||
if err != OK and err != ERR_DOES_NOT_EXIST:
|
||||
push_warning("Failed to load settings.cfg before saving: %s" % err)
|
||||
config = ConfigFile.new()
|
||||
elif err != OK:
|
||||
config = ConfigFile.new()
|
||||
config.set_value(CONFIG_SECTION, CONFIG_KEY_VOLUME, _user_volume_linear)
|
||||
config.set_value(CONFIG_SECTION, CONFIG_KEY_MUTED, _is_muted)
|
||||
var save_err: int = config.save(CONFIG_PATH)
|
||||
if save_err != OK:
|
||||
push_warning("Failed to save settings.cfg: %s" % save_err)
|
||||
@@ -0,0 +1 @@
|
||||
uid://c7ixr4hbh5ad6
|
||||
@@ -0,0 +1,13 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dt785sv7ie7uj"]
|
||||
|
||||
[ext_resource type="AudioStream" uid="uid://64dplcgx2icb" path="res://assets/audio/silly-menu-hover-test.ogg" id="1_a5j5k"]
|
||||
[ext_resource type="Script" path="res://scenes/UI/menu_sfx.gd" id="1_ijvfa"]
|
||||
|
||||
[node name="MenuSfx" type="AudioStreamPlayer"]
|
||||
bus = &"SFX"
|
||||
stream = ExtResource("1_a5j5k")
|
||||
volume_db = -6.0
|
||||
autoplay = false
|
||||
priority = 0.5
|
||||
max_polyphony = 4
|
||||
script = ExtResource("1_ijvfa")
|
||||
@@ -0,0 +1,27 @@
|
||||
extends Control
|
||||
|
||||
func _ready():
|
||||
_register_focus_sounds()
|
||||
|
||||
func _register_focus_sounds() -> void:
|
||||
var button_container := $MarginContainer/MarginContainer/VBoxContainer
|
||||
for child in button_container.get_children():
|
||||
if child is BaseButton:
|
||||
var button: BaseButton = child
|
||||
if not button.is_connected("focus_entered", Callable(self, "_on_menu_item_focus")):
|
||||
button.focus_entered.connect(_on_menu_item_focus)
|
||||
if not button.is_connected("mouse_entered", Callable(self, "_on_menu_item_focus")):
|
||||
button.mouse_entered.connect(_on_menu_item_focus)
|
||||
|
||||
func _on_start_button_pressed():
|
||||
get_tree().change_scene_to_file("uid://dchj6g2i8ebph")
|
||||
|
||||
func _on_settings_button_pressed():
|
||||
get_tree().change_scene_to_file("uid://d3tqrm4ry4l88")
|
||||
|
||||
func _on_quit_button_pressed():
|
||||
get_tree().quit()
|
||||
|
||||
func _on_menu_item_focus() -> void:
|
||||
if MenuSfx:
|
||||
MenuSfx.play_hover()
|
||||
@@ -1,10 +1,9 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://b4k81taauef4q"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cc8lskf7y74kh" path="res://scenes/start_screen.gd" id="1_o7i0r"]
|
||||
[ext_resource type="Script" uid="uid://cc8lskf7y74kh" path="res://scenes/UI/start_screen.gd" id="1_o7i0r"]
|
||||
[ext_resource type="Theme" uid="uid://wpxmub0n2dr3" path="res://themes/button_theme.tres" id="1_tx5wa"]
|
||||
[ext_resource type="Texture2D" uid="uid://dhuosr0p605gj" path="res://assets/images/pp_start_bg.png" id="2_r2jwc"]
|
||||
[ext_resource type="Theme" uid="uid://tn8qndst18d6" path="res://themes/title_font_theme.tres" id="4_hm208"]
|
||||
|
||||
[node name="StartScreen" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
@@ -0,0 +1,21 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://c5of6aaxop1hl"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_4du60"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_alp5v"]
|
||||
albedo_color = Color(0.290196, 0.698039, 0.227451, 1)
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_kryjk"]
|
||||
material = SubResource("StandardMaterial3D_alp5v")
|
||||
|
||||
[node name="Block" type="Node3D"]
|
||||
|
||||
[node name="RigidBody3D" type="RigidBody3D" parent="."]
|
||||
collision_layer = 3
|
||||
collision_mask = 3
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="RigidBody3D"]
|
||||
shape = SubResource("BoxShape3D_4du60")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="RigidBody3D"]
|
||||
mesh = SubResource("BoxMesh_kryjk")
|
||||
+95
-9
@@ -1,16 +1,102 @@
|
||||
extends RigidBody3D
|
||||
|
||||
# Initially I used a CharacterBody3D, however, I wanted the player to bounce off
|
||||
# other objects in the environment and that would have required manual handling
|
||||
# of collisions. So that's why we're using a RigidBody3D instead.
|
||||
|
||||
const ACCELLERATION = 5.0
|
||||
const MOVE_SPEED := 8.0
|
||||
const ACCELLERATION := 30.0
|
||||
const DECELLERATION := 40.0
|
||||
const JUMP_SPEED := 4.0
|
||||
const MAX_NUMBER_OF_JUMPS := 2
|
||||
|
||||
func _integrate_forces(state):
|
||||
var input_dir = Vector3.ZERO
|
||||
input_dir.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
|
||||
input_dir.z = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
|
||||
input_dir = input_dir.normalized()
|
||||
const MIN_FOV := 10
|
||||
const MAX_FOV := 180
|
||||
const ZOOM_FACTOR := 1.1 # Zoom out when >1, in when < 1
|
||||
var mouse_sensitivity := 0.005
|
||||
var rotation_x := 0.0
|
||||
var rotation_y := 0.0
|
||||
var cameraMoveMode := false
|
||||
var current_number_of_jumps := 0
|
||||
|
||||
var jump_sound = preload("res://assets/audio/jump.ogg")
|
||||
var audio_player = AudioStreamPlayer.new()
|
||||
|
||||
@export var camera_path: NodePath
|
||||
@onready var cam: Camera3D = get_node(camera_path) if camera_path != NodePath("") else null
|
||||
|
||||
func _ready() -> void:
|
||||
axis_lock_angular_x = true
|
||||
axis_lock_angular_z = true
|
||||
angular_damp = 6.0
|
||||
contact_monitor = true
|
||||
max_contacts_reported = 4
|
||||
add_child(audio_player)
|
||||
audio_player.stream = jump_sound
|
||||
audio_player.volume_db = -20
|
||||
|
||||
linear_velocity.x += input_dir.x * (ACCELLERATION * state.step)
|
||||
linear_velocity.z += input_dir.z * (ACCELLERATION * state.step)
|
||||
func _integrate_forces(state):
|
||||
# Input as 2D vector
|
||||
var input2v := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
|
||||
|
||||
# Camera based movement
|
||||
var forward := Vector3.FORWARD * -1.0
|
||||
var right := Vector3.RIGHT
|
||||
if cam:
|
||||
forward = cam.global_transform.basis.z
|
||||
right = cam.global_transform.basis.x
|
||||
# project onto ground plane so looking up/down doesn't tilt movement
|
||||
forward.y = 0.0
|
||||
right.y = 0.0
|
||||
if forward.length() > 0.0001:
|
||||
forward = forward.normalized()
|
||||
if right.length() > 0.0001:
|
||||
right = right.normalized()
|
||||
|
||||
var dir := (right * input2v.x + forward * input2v.y).normalized()
|
||||
var target_v := dir * MOVE_SPEED
|
||||
|
||||
var ax := ACCELLERATION if dir != Vector3.ZERO else DECELLERATION
|
||||
linear_velocity.x = move_toward(linear_velocity.x, target_v.x, ax * state.step)
|
||||
linear_velocity.z = move_toward(linear_velocity.z, target_v.z, ax * state.step)
|
||||
|
||||
# Jump Logic
|
||||
var on_floor = false
|
||||
for i in state.get_contact_count():
|
||||
var normal = state.get_contact_local_normal(i)
|
||||
if normal.y > 0.5:
|
||||
on_floor = true
|
||||
break
|
||||
|
||||
if Input.is_action_just_pressed("ui_accept") and (on_floor or current_number_of_jumps == 1):
|
||||
current_number_of_jumps = (current_number_of_jumps + 1) % 2
|
||||
linear_velocity.y = JUMP_SPEED
|
||||
audio_player.play()
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_MIDDLE:
|
||||
if event.pressed:
|
||||
cameraMoveMode = true
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
else:
|
||||
cameraMoveMode = false
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
|
||||
if event is InputEventMouseMotion and cameraMoveMode:
|
||||
rotation_x -= event.relative.y * mouse_sensitivity
|
||||
rotation_y -= event.relative.x * mouse_sensitivity
|
||||
rotation_x = clamp(rotation_x, deg_to_rad(-90), deg_to_rad(90)) # Prevent flipping
|
||||
|
||||
$Camera3D.rotation.x = rotation_x
|
||||
rotation.y = rotation_y
|
||||
|
||||
if event is InputEventMouseButton and event.pressed:
|
||||
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
|
||||
zoom_camera(1.0 / ZOOM_FACTOR) # Zoom in
|
||||
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||
zoom_camera(ZOOM_FACTOR) # Zoom out
|
||||
|
||||
func zoom_camera(factor):
|
||||
var new_fov = cam.fov * factor
|
||||
cam.fov = clamp(new_fov, MIN_FOV, MAX_FOV)
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
extends Control
|
||||
|
||||
|
||||
func _on_start_button_pressed():
|
||||
get_tree().change_scene_to_file("res://scenes/level.tscn")
|
||||
|
||||
func _on_settings_button_pressed():
|
||||
get_tree().change_scene_to_file("res://scenes/Settings.tscn")
|
||||
|
||||
func _on_quit_button_pressed():
|
||||
get_tree().quit()
|
||||
Reference in New Issue
Block a user