diff --git a/.gitignore b/.gitignore index 50335d9..7a2dacc 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ export_credentials.cfg .mono/ data_*/ mono_crash.*.json + +export diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..28c5eeb --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,67 @@ +[preset.0] + +name="Windows Desktop" +platform="Windows Desktop" +runnable=true +advanced_options=false +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="export/Windows/Scrap Frontier.exe" +patches=PackedStringArray() +encryption_include_filters="" +encryption_exclude_filters="" +seed=0 +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_wrapper=1 +binary_format/embed_pck=true +texture_format/s3tc_bptc=true +texture_format/etc2_astc=false +shader_baker/enabled=false +binary_format/architecture="x86_64" +codesign/enable=false +codesign/timestamp=true +codesign/timestamp_server_url="" +codesign/digest_algorithm=1 +codesign/description="" +codesign/custom_options=PackedStringArray() +application/modify_resources=true +application/icon="" +application/console_wrapper_icon="" +application/icon_interpolation=4 +application/file_version="" +application/product_version="" +application/company_name="" +application/product_name="" +application/file_description="" +application/copyright="" +application/trademarks="" +application/export_angle=0 +application/export_d3d12=0 +application/d3d12_agility_sdk_multiarch=true +ssh_remote_deploy/enabled=false +ssh_remote_deploy/host="user@host_ip" +ssh_remote_deploy/port="22" +ssh_remote_deploy/extra_args_ssh="" +ssh_remote_deploy/extra_args_scp="" +ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}' +$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}' +$trigger = New-ScheduledTaskTrigger -Once -At 00:00 +$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries +$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings +Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true +Start-ScheduledTask -TaskName godot_remote_debug +while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 } +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue" +ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue +Remove-Item -Recurse -Force '{temp_dir}'" diff --git a/game.gd b/game.gd new file mode 100644 index 0000000..7808723 --- /dev/null +++ b/game.gd @@ -0,0 +1,31 @@ +extends Node + +var _current_scene: Node + + +func _ready() -> void: + _show_main_menu() + + +func _show_main_menu() -> void: + if _current_scene != null: + _current_scene.queue_free() + + var scene : Node = load("res://title_screen.tscn").instantiate() + add_child(scene) + scene.continue_game.connect(_continue_game) + scene.new_game.connect(_new_game) + scene.quit_game.connect(_quit) + _current_scene = scene + + +func _continue_game() -> void: + print("continue_game") + + +func _new_game() -> void: + print("new_game") + + +func _quit() -> void: + get_tree().quit() diff --git a/game.gd.uid b/game.gd.uid new file mode 100644 index 0000000..ab9a2eb --- /dev/null +++ b/game.gd.uid @@ -0,0 +1 @@ +uid://1aescybuf6gu diff --git a/game.tscn b/game.tscn new file mode 100644 index 0000000..7cd434f --- /dev/null +++ b/game.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://3slnk7fd7xm5"] + +[ext_resource type="Script" uid="uid://1aescybuf6gu" path="res://game.gd" id="1_80nbo"] + +[node name="Game" type="Node"] +script = ExtResource("1_80nbo") diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..23dccda --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ttk12r3i056y" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/menu/credits.gd b/menu/credits.gd new file mode 100644 index 0000000..0fdddf5 --- /dev/null +++ b/menu/credits.gd @@ -0,0 +1,7 @@ +extends Node + +signal show_main_menu + + +func _on_main_menu_button_pressed() -> void: + show_main_menu.emit() diff --git a/menu/credits.gd.uid b/menu/credits.gd.uid new file mode 100644 index 0000000..3027767 --- /dev/null +++ b/menu/credits.gd.uid @@ -0,0 +1 @@ +uid://dclkpithyykju diff --git a/menu/credits.tscn b/menu/credits.tscn new file mode 100644 index 0000000..1abbcc1 --- /dev/null +++ b/menu/credits.tscn @@ -0,0 +1,42 @@ +[gd_scene load_steps=2 format=3 uid="uid://c3q3g2647qc27"] + +[ext_resource type="Script" uid="uid://dclkpithyykju" path="res://menu/credits.gd" id="1_wp78b"] + +[node name="Credits" type="Node"] +script = ExtResource("1_wp78b") + +[node name="Control" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_left = 100.0 +offset_top = 100.0 +offset_right = 140.0 +offset_bottom = 140.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="Control"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="GridContainer" type="GridContainer" parent="Control/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="ProgrammingLabel" type="Label" parent="Control/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Programming:" +horizontal_alignment = 2 + +[node name="ProgrammersLabel" type="Label" parent="Control/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Ruslan Ignatov" + +[node name="HBoxContainer" type="HBoxContainer" parent="Control/VBoxContainer"] +layout_mode = 2 +alignment = 2 + +[node name="MainMenuButton" type="Button" parent="Control/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Main Menu" + +[connection signal="pressed" from="Control/VBoxContainer/HBoxContainer/MainMenuButton" to="." method="_on_main_menu_button_pressed"] diff --git a/menu/main_menu.gd b/menu/main_menu.gd new file mode 100644 index 0000000..3b1101c --- /dev/null +++ b/menu/main_menu.gd @@ -0,0 +1,22 @@ +extends Node + +signal continue_game +signal new_game +signal quit_game +signal show_options + + +func _on_continue_button_pressed() -> void: + continue_game.emit() + + +func _on_start_button_pressed() -> void: + new_game.emit() + + +func _on_options_button_pressed() -> void: + show_options.emit() + + +func _on_quit_button_pressed() -> void: + quit_game.emit() diff --git a/menu/main_menu.gd.uid b/menu/main_menu.gd.uid new file mode 100644 index 0000000..e0d1f1d --- /dev/null +++ b/menu/main_menu.gd.uid @@ -0,0 +1 @@ +uid://dixdfabe2vfsj diff --git a/menu/main_menu.tscn b/menu/main_menu.tscn new file mode 100644 index 0000000..0b19214 --- /dev/null +++ b/menu/main_menu.tscn @@ -0,0 +1,41 @@ +[gd_scene load_steps=2 format=3 uid="uid://bxlccevt52y70"] + +[ext_resource type="Script" uid="uid://dixdfabe2vfsj" path="res://menu/main_menu.gd" id="1_chmv6"] + +[node name="MainMenu" type="Node"] +script = ExtResource("1_chmv6") + +[node name="Control" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="Control"] +layout_mode = 0 +offset_left = 100.0 +offset_top = 100.0 +offset_right = 179.0 +offset_bottom = 236.0 + +[node name="ContinueButton" type="Button" parent="Control/VBoxContainer"] +layout_mode = 2 +disabled = true +text = "Continue" + +[node name="StartButton" type="Button" parent="Control/VBoxContainer"] +layout_mode = 2 +text = "Start" + +[node name="OptionsButton" type="Button" parent="Control/VBoxContainer"] +layout_mode = 2 +text = "Options" + +[node name="QuitButton" type="Button" parent="Control/VBoxContainer"] +layout_mode = 2 +text = "Quit" + +[connection signal="pressed" from="Control/VBoxContainer/ContinueButton" to="." method="_on_continue_button_pressed"] +[connection signal="pressed" from="Control/VBoxContainer/StartButton" to="." method="_on_start_button_pressed"] +[connection signal="pressed" from="Control/VBoxContainer/OptionsButton" to="." method="_on_options_button_pressed"] +[connection signal="pressed" from="Control/VBoxContainer/QuitButton" to="." method="_on_quit_button_pressed"] diff --git a/menu/options.gd b/menu/options.gd new file mode 100644 index 0000000..be5d461 --- /dev/null +++ b/menu/options.gd @@ -0,0 +1,39 @@ +extends Node + +signal show_credits +signal show_main_menu + +@onready var fullscreen_check := $Control/VBoxContainer/OptionsGridContainer/FullscreenCheckButton +@onready var window_factor := $Control/VBoxContainer/OptionsGridContainer/WindowFactorOptionButton + + +func _ready() -> void: + _load_current_settings() + + +func _load_current_settings() -> void: + fullscreen_check.button_pressed = SettingsManager.fullscreen() + window_factor.selected = SettingsManager.window_factor() + _update_window_factor_disabled() + + +func _update_window_factor_disabled() -> void: + window_factor.disabled = SettingsManager.fullscreen() + + +func _on_fullscreen_check_button_toggled(toggled: bool) -> void: + SettingsManager.set_fullscreen(toggled) + _update_window_factor_disabled() + + +func _on_window_factor_option_button_item_selected(index: int) -> void: + if !SettingsManager.fullscreen(): + SettingsManager.set_window_factor(index) + + +func _on_credits_button_pressed() -> void: + show_credits.emit() + + +func _on_back_button_pressed() -> void: + show_main_menu.emit() diff --git a/menu/options.gd.uid b/menu/options.gd.uid new file mode 100644 index 0000000..7c189bc --- /dev/null +++ b/menu/options.gd.uid @@ -0,0 +1 @@ +uid://ceng1u112aqg0 diff --git a/menu/options.tscn b/menu/options.tscn new file mode 100644 index 0000000..1114e5d --- /dev/null +++ b/menu/options.tscn @@ -0,0 +1,69 @@ +[gd_scene load_steps=2 format=3 uid="uid://btr60idiit4y7"] + +[ext_resource type="Script" uid="uid://ceng1u112aqg0" path="res://menu/options.gd" id="1_61pji"] + +[node name="Options" type="Node"] +script = ExtResource("1_61pji") + +[node name="Control" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 0 +offset_left = 100.0 +offset_top = 100.0 +offset_right = 140.0 +offset_bottom = 140.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="Control"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 +alignment = 1 + +[node name="OptionsGridContainer" type="GridContainer" parent="Control/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="FullscreenLabel" type="Label" parent="Control/VBoxContainer/OptionsGridContainer"] +layout_mode = 2 +text = "Fullscreen" + +[node name="FullscreenCheckButton" type="CheckButton" parent="Control/VBoxContainer/OptionsGridContainer"] +layout_mode = 2 + +[node name="WindowFactorLabel" type="Label" parent="Control/VBoxContainer/OptionsGridContainer"] +layout_mode = 2 +text = "Window Factor" + +[node name="WindowFactorOptionButton" type="OptionButton" parent="Control/VBoxContainer/OptionsGridContainer"] +layout_mode = 2 +selected = 0 +item_count = 6 +popup/item_0/text = "×1" +popup/item_0/id = 0 +popup/item_1/text = "×2" +popup/item_1/id = 1 +popup/item_2/text = "×3" +popup/item_2/id = 2 +popup/item_3/text = "×4" +popup/item_3/id = 3 +popup/item_4/text = "×5" +popup/item_4/id = 4 +popup/item_5/text = "×6" +popup/item_5/id = 5 + +[node name="HBoxContainer" type="HBoxContainer" parent="Control/VBoxContainer"] +layout_mode = 2 +alignment = 2 + +[node name="CreditsButton" type="Button" parent="Control/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Credits" + +[node name="BackButton" type="Button" parent="Control/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Back" + +[connection signal="toggled" from="Control/VBoxContainer/OptionsGridContainer/FullscreenCheckButton" to="." method="_on_fullscreen_check_button_toggled"] +[connection signal="item_selected" from="Control/VBoxContainer/OptionsGridContainer/WindowFactorOptionButton" to="." method="_on_window_factor_option_button_item_selected"] +[connection signal="pressed" from="Control/VBoxContainer/HBoxContainer/CreditsButton" to="." method="_on_credits_button_pressed"] +[connection signal="pressed" from="Control/VBoxContainer/HBoxContainer/BackButton" to="." method="_on_back_button_pressed"] diff --git a/project.godot b/project.godot index 765cb1d..73b8549 100644 --- a/project.godot +++ b/project.godot @@ -11,10 +11,32 @@ config_version=5 [application] config/name="Scrap Frontier" +config/description="Scroll Shooter" +config/tags=PackedStringArray("2d") +run/main_scene="uid://3slnk7fd7xm5" config/features=PackedStringArray("4.5", "GL Compatibility") config/icon="res://icon.svg" +[autoload] + +SettingsManager="*res://settings_manager.gd" + +[debug] + +gdscript/warnings/untyped_declaration=1 + +[display] + +window/size/viewport_width=640 +window/size/viewport_height=360 +window/size/resizable=false +window/stretch/mode="viewport" +window/stretch/scale=1.02 +window/stretch/scale_mode="integer" + [rendering] +textures/canvas_textures/default_texture_filter=0 renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" +2d/snap/snap_2d_transforms_to_pixel=true diff --git a/settings_manager.gd b/settings_manager.gd new file mode 100644 index 0000000..3293004 --- /dev/null +++ b/settings_manager.gd @@ -0,0 +1,108 @@ +extends Node + +const CONFIG_FILE = "user://settings.cfg" +const BASE_SIZE = Vector2i(640, 360) + +const CATEGORY_VIDEO = "video" +const SETTING_FULLSCREEN = "fullscreen" +const SETTING_WINDOW_FACTOR = "window_factor" + +var _config: ConfigFile + +var _fullscreen := false +var _window_factor := 0 + + +func _ready() -> void: + _load_settings() + _apply_all_settings() + + +func _load_settings() -> void: + _config = ConfigFile.new() + + if _config.load(CONFIG_FILE) == OK: + _fullscreen = _config.get_value(CATEGORY_VIDEO, SETTING_FULLSCREEN, false) + _window_factor = _config.get_value(CATEGORY_VIDEO, SETTING_WINDOW_FACTOR, 0) + + _save_settings() + + +func _save_settings() -> void: + if _config == null: + _config = ConfigFile.new() + + _config.set_value(CATEGORY_VIDEO, SETTING_FULLSCREEN, _fullscreen) + _config.set_value(CATEGORY_VIDEO, SETTING_WINDOW_FACTOR, _window_factor) + + _config.save(CONFIG_FILE) + + +func _apply_all_settings() -> void: + _apply_video_settings() + + +func _apply_video_settings() -> void: + if _fullscreen: + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) + else: + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) + _apply_window_scale() + + +func _apply_window_scale() -> void: + if _fullscreen: return + + var factors := [1, 2, 3, 4, 5, 6] + + var factor_index := _window_factor + if factor_index >= factors.size(): + factor_index = 0 + + var scale : int = factors[factor_index] + var new_size := BASE_SIZE * scale + + var current_position := DisplayServer.window_get_position() + var current_size := DisplayServer.window_get_size() + + var current_center := current_position + current_size / 2 + var new_position := current_center - new_size / 2 + + DisplayServer.window_set_size(new_size) + DisplayServer.window_set_position(new_position) + + _ensure_window_on_screen() + + +func _ensure_window_on_screen() -> void: + if _fullscreen: return + + var window_position := DisplayServer.window_get_position() + var window_size := DisplayServer.window_get_size() + var screen_size := DisplayServer.screen_get_size() + + var new_x : int = clamp(window_position.x, 0, screen_size.x - window_size.x) + var new_y : int = clamp(window_position.y, 0, screen_size.y - window_size.y) + + if new_x != window_position.x or new_y != window_position.y: + DisplayServer.window_set_position(Vector2i(new_x, new_y)) + + +func set_fullscreen(value: bool) -> void: + _fullscreen = value + _apply_video_settings() + _save_settings() + + +func fullscreen() -> bool: + return _fullscreen + + +func set_window_factor(value: int) -> void: + _window_factor = value + _apply_window_scale() + _save_settings() + + +func window_factor() -> int: + return _window_factor diff --git a/settings_manager.gd.uid b/settings_manager.gd.uid new file mode 100644 index 0000000..2510ef5 --- /dev/null +++ b/settings_manager.gd.uid @@ -0,0 +1 @@ +uid://d2k5y0xd4hl22 diff --git a/title_screen.gd b/title_screen.gd new file mode 100644 index 0000000..ec8dc92 --- /dev/null +++ b/title_screen.gd @@ -0,0 +1,58 @@ +extends Node + +signal continue_game +signal new_game +signal quit_game + +var _current_scene: Node + + +func _ready() -> void: + _show_main_menu() + + +func _show_main_menu() -> void: + if _current_scene != null: + _current_scene.queue_free() + + var scene : Node = load("res://menu/main_menu.tscn").instantiate() + add_child(scene) + scene.continue_game.connect(_continue_game) + scene.new_game.connect(_new_game) + scene.show_options.connect(_show_options) + scene.quit_game.connect(_quit_game) + _current_scene = scene + + +func _continue_game() -> void: + continue_game.emit() + + +func _new_game() -> void: + new_game.emit() + + +func _quit_game() -> void: + quit_game.emit() + + +func _show_options() -> void: + if _current_scene != null: + _current_scene.queue_free() + + var scene : Node = load("res://menu/options.tscn").instantiate() + add_child(scene) + scene.show_main_menu.connect(_show_main_menu) + scene.show_credits.connect(_show_credits) + _current_scene = scene + + +func _show_credits() -> void: + if _current_scene != null: + _current_scene.queue_free() + + var scene : Node = load("res://menu/credits.tscn").instantiate() + add_child(scene) + scene.show_main_menu.connect(_show_main_menu) + _current_scene = scene + diff --git a/title_screen.gd.uid b/title_screen.gd.uid new file mode 100644 index 0000000..7066456 --- /dev/null +++ b/title_screen.gd.uid @@ -0,0 +1 @@ +uid://b0etxb4if8lay diff --git a/title_screen.tscn b/title_screen.tscn new file mode 100644 index 0000000..9b7b3e9 --- /dev/null +++ b/title_screen.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://cdw82732vgub8"] + +[ext_resource type="Script" uid="uid://b0etxb4if8lay" path="res://title_screen.gd" id="1_v6p8y"] + +[node name="TitleScreen" type="Node"] +script = ExtResource("1_v6p8y")