diff --git a/default_bus_layout.tres b/default_bus_layout.tres new file mode 100644 index 0000000..715ca52 --- /dev/null +++ b/default_bus_layout.tres @@ -0,0 +1,9 @@ +[gd_resource type="AudioBusLayout" format=3 uid="uid://bgs4iykhuoux0"] + +[resource] +bus/1/name = &"Sounds" +bus/1/solo = false +bus/1/mute = false +bus/1/bypass_fx = false +bus/1/volume_db = 0.00282288 +bus/1/send = &"Master" diff --git a/elements/player.tscn b/elements/player.tscn index c08d971..74c84c6 100644 --- a/elements/player.tscn +++ b/elements/player.tscn @@ -1,43 +1,80 @@ -[gd_scene load_steps=4 format=3 uid="uid://cnnvwotv33u1b"] - -[ext_resource type="PackedScene" uid="uid://dw0xl8644x166" path="res://elements/gravity.tscn" id="1_h0h2o"] -[ext_resource type="PackedScene" uid="uid://df5m716pd6mej" path="res://elements/sphere.tscn" id="2_ophnk"] +[gd_scene load_steps=11 format=3 uid="uid://cnnvwotv33u1b"] [sub_resource type="GDScript" id="GDScript_bnqcw"] -script/source = "extends Node3D +script/source = "class_name Player +extends Node3D -func _process(_delta: float) -> void: +signal velocity_change +var velocity := 0.0: + get: return velocity + set(value): + if value != velocity: + velocity_change.emit(value) + velocity = value +@onready var ball_position: Vector3 = $Sphere.position + +func _physics_process(_delta: float) -> void: + ball_position = $Sphere.position $SpotLightMain.position = $Sphere.position + Vector3(0, 5, 0) $SpotLightTop.position = $Sphere.position $SpotLightLeft.position = $Sphere.position $SpotLightRight.position = $Sphere.position $SpotLightBottom.position = $Sphere.position - ## Keep the ball at the center of the camera, at a distance + # Keep the ball at the center of the camera, at a distance $Camera.position = $Sphere.position + Vector3(0, 0, 15) - ## Angle of the camera, so the player can see where the ball is going - var velocity: Vector3 = $Sphere.linear_velocity - var desired_x = max(min(velocity.y, 35), -35) - var desired_y = max(min(-velocity.x, 50), -50) + # Angle of the camera, so the player can see where the ball is going + velocity = abs($Sphere.linear_velocity.x) + abs($Sphere.linear_velocity.y) + var desired_x = max(min($Sphere.linear_velocity.y, 35), -35) + var desired_y = max(min(-$Sphere.linear_velocity.x, 50), -50) var difference_x = $Camera.rotation_degrees.x - desired_x var difference_y = $Camera.rotation_degrees.y - desired_y $Camera.rotation_degrees.x -= max(min(difference_x / 2, 3), -3) $Camera.rotation_degrees.y -= max(min(difference_y / 2, 3), -3) - ## FOV of the camera, so it unzooms more at higher velocities + # FOV of the camera, so it unzooms more at higher velocities const default_fov = 75 - var total_velocity = abs(velocity.x) + abs(velocity.y) - $Camera.fov = default_fov + (total_velocity / 12) + $Camera.fov = default_fov + (velocity / 12) " +[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_vumbr"] +bounce = 0.2 + +[sub_resource type="SphereShape3D" id="SphereShape3D_xfgrm"] + +[sub_resource type="Gradient" id="Gradient_bgp4x"] +colors = PackedColorArray(0.942957, 7.89344e-06, 0.597148, 1, 0, 0.9912, 0.9912, 1) + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_5d6uk"] +gradient = SubResource("Gradient_bgp4x") +fill_from = Vector2(0.504951, 0.00495049) +fill_to = Vector2(0.549505, 1) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qcgmu"] +albedo_texture = SubResource("GradientTexture2D_5d6uk") + +[sub_resource type="SphereMesh" id="SphereMesh_bor8g"] +material = SubResource("StandardMaterial3D_qcgmu") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_4tofj"] +direction = Vector3(0, 0, 0) +gravity = Vector3(0, 0, 0) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2ybet"] +vertex_color_use_as_albedo = true +albedo_color = Color(0, 0.734117, 0.734117, 1) + +[sub_resource type="SphereMesh" id="SphereMesh_1m3ut"] +material = SubResource("StandardMaterial3D_2ybet") +radius = 0.2 +height = 0.4 +radial_segments = 8 +rings = 4 + [node name="Player" type="Node3D"] script = SubResource("GDScript_bnqcw") -[node name="Gravity" parent="." instance=ExtResource("1_h0h2o")] - -[node name="Sphere" parent="." instance=ExtResource("2_ophnk")] - [node name="Camera" type="Camera3D" parent="."] current = true @@ -61,3 +98,21 @@ spot_range = 50.0 [node name="SpotLightBottom" type="SpotLight3D" parent="."] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) spot_range = 50.0 + +[node name="Sphere" type="RigidBody3D" parent="."] +collision_priority = 100.0 +axis_lock_linear_z = true +physics_material_override = SubResource("PhysicsMaterial_vumbr") +can_sleep = false +contact_monitor = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Sphere"] +shape = SubResource("SphereShape3D_xfgrm") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Sphere"] +mesh = SubResource("SphereMesh_bor8g") + +[node name="GPUParticles3D" type="GPUParticles3D" parent="Sphere"] +amount = 16 +process_material = SubResource("ParticleProcessMaterial_4tofj") +draw_pass_1 = SubResource("SphereMesh_1m3ut") diff --git a/elements/ring.gd b/elements/ring.gd new file mode 100644 index 0000000..07924c7 --- /dev/null +++ b/elements/ring.gd @@ -0,0 +1,14 @@ +class_name Ring +extends CSGTorus3D + +var happy_material = preload("res://graphics/happy_material.tres") + +var collected = false +signal collect_signal + +func _on_area_3d_body_entered(body: Node3D) -> void: + if collected == false and body.name == "Sphere": + self.material = happy_material + collected = true + $AudioStreamPlayer.play() + collect_signal.emit() diff --git a/elements/ring.gd.uid b/elements/ring.gd.uid new file mode 100644 index 0000000..e2befce --- /dev/null +++ b/elements/ring.gd.uid @@ -0,0 +1 @@ +uid://d1tdcd6b2bp05 diff --git a/elements/ring.tscn b/elements/ring.tscn index 898bee7..7e5786d 100644 --- a/elements/ring.tscn +++ b/elements/ring.tscn @@ -2,24 +2,9 @@ [ext_resource type="Material" uid="uid://brwwlwb1rpro7" path="res://graphics/unhappy_material.tres" id="1_48h5f"] [ext_resource type="AudioStream" uid="uid://b0cl5v6q1ocbv" path="res://sounds/ring1.ogg" id="2_2so43"] +[ext_resource type="Script" uid="uid://d1tdcd6b2bp05" path="res://elements/ring.gd" id="2_288uq"] [ext_resource type="AudioStream" uid="uid://cvvs74ep5d4wt" path="res://sounds/ring2.ogg" id="3_lkqw0"] -[sub_resource type="GDScript" id="GDScript_86vhg"] -script/source = "extends CSGTorus3D - -var happy_material = preload(\"res://graphics/happy_material.tres\") - -var collected = false -signal collect_signal - -func _on_area_3d_body_entered(body: Node3D) -> void: - if collected == false and body.name == \"Sphere\": - self.material = happy_material - collected = true - $AudioStreamPlayer.play() - collect_signal.emit() -" - [sub_resource type="CylinderShape3D" id="CylinderShape3D_tgirv"] radius = 4.0 @@ -33,10 +18,11 @@ stream_1/stream = ExtResource("3_lkqw0") use_collision = true inner_radius = 4.0 outer_radius = 8.0 -sides = 16 -ring_sides = 8 +sides = 32 +ring_sides = 16 material = ExtResource("1_48h5f") -script = SubResource("GDScript_86vhg") +script = ExtResource("2_288uq") +metadata/_custom_type_script = "uid://d1tdcd6b2bp05" [node name="Area3D" type="Area3D" parent="."] @@ -45,5 +31,6 @@ shape = SubResource("CylinderShape3D_tgirv") [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] stream = SubResource("AudioStreamRandomizer_251sn") +bus = &"Sounds" [connection signal="body_entered" from="Area3D" to="." method="_on_area_3d_body_entered"] diff --git a/elements/sign.tscn b/elements/sign.tscn index e93e18e..d91f0ad 100644 --- a/elements/sign.tscn +++ b/elements/sign.tscn @@ -4,7 +4,7 @@ [node name="Text" type="Label3D" parent="."] text = "Sample text" -font_size = 1024 +font_size = 64 [node name="CSGBox3D" type="CSGBox3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -5.1) diff --git a/elements/sphere.tscn b/elements/sphere.tscn deleted file mode 100644 index 77e697e..0000000 --- a/elements/sphere.tscn +++ /dev/null @@ -1,52 +0,0 @@ -[gd_scene load_steps=10 format=3 uid="uid://df5m716pd6mej"] - -[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_vumbr"] -bounce = 0.2 - -[sub_resource type="SphereShape3D" id="SphereShape3D_xfgrm"] - -[sub_resource type="Gradient" id="Gradient_bgp4x"] -colors = PackedColorArray(0.942957, 7.89344e-06, 0.597148, 1, 0, 0.9912, 0.9912, 1) - -[sub_resource type="GradientTexture2D" id="GradientTexture2D_5d6uk"] -gradient = SubResource("Gradient_bgp4x") -fill_from = Vector2(0.504951, 0.00495049) -fill_to = Vector2(0.549505, 1) - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_qcgmu"] -albedo_texture = SubResource("GradientTexture2D_5d6uk") - -[sub_resource type="SphereMesh" id="SphereMesh_bor8g"] -material = SubResource("StandardMaterial3D_qcgmu") - -[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_4tofj"] -direction = Vector3(0, 0, 0) -gravity = Vector3(0, 0, 0) - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2ybet"] -vertex_color_use_as_albedo = true -albedo_color = Color(0, 0.734117, 0.734117, 1) - -[sub_resource type="SphereMesh" id="SphereMesh_1m3ut"] -material = SubResource("StandardMaterial3D_2ybet") -radius = 0.2 -height = 0.4 -radial_segments = 8 -rings = 4 - -[node name="Sphere" type="RigidBody3D"] -collision_priority = 100.0 -axis_lock_linear_z = true -physics_material_override = SubResource("PhysicsMaterial_vumbr") -contact_monitor = true - -[node name="CollisionShape3D" type="CollisionShape3D" parent="."] -shape = SubResource("SphereShape3D_xfgrm") - -[node name="MeshInstance3D" type="MeshInstance3D" parent="."] -mesh = SubResource("SphereMesh_bor8g") - -[node name="GPUParticles3D" type="GPUParticles3D" parent="."] -amount = 16 -process_material = SubResource("ParticleProcessMaterial_4tofj") -draw_pass_1 = SubResource("SphereMesh_1m3ut") diff --git a/elements/tree.tscn b/elements/tree.tscn index 8d9690a..771ea82 100644 --- a/elements/tree.tscn +++ b/elements/tree.tscn @@ -29,6 +29,7 @@ vertex_color_use_as_albedo = true albedo_color = Color(0.212217, 0.468618, 0, 1) [node name="Tree" type="Node3D"] +physics_interpolation_mode = 2 script = SubResource("GDScript_tbkod") [node name="Dirt" type="CSGBox3D" parent="."] diff --git a/export_presets.cfg b/export_presets.cfg index 4833fd5..81b9e74 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -9,9 +9,11 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="exports/*" -export_path="exports/AlakajamEntry.x86_64" +export_path="exports/DreamBall.x86_64" +patches=PackedStringArray() encryption_include_filters="" encryption_exclude_filters="" +seed=0 encrypt_pck=false encrypt_directory=false script_export_mode=2 @@ -49,9 +51,11 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="exports/*" -export_path="exports/AlakajamEntry.exe" +export_path="exports/DreamBall.exe" +patches=PackedStringArray() encryption_include_filters="" encryption_exclude_filters="" +seed=0 encrypt_pck=false encrypt_directory=false script_export_mode=2 @@ -114,9 +118,11 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="exports/*" -export_path="exports/web/AlakajamEntry.html" +export_path="exports/web/DreamBall.html" +patches=PackedStringArray() encryption_include_filters="" encryption_exclude_filters="" +seed=0 encrypt_pck=false encrypt_directory=false script_export_mode=2 diff --git a/fonts/Knewave/Knewave-Regular.ttf b/fonts/Knewave/Knewave-Regular.ttf new file mode 100644 index 0000000..a98f750 Binary files /dev/null and b/fonts/Knewave/Knewave-Regular.ttf differ diff --git a/fonts/Knewave/Knewave-Regular.ttf.import b/fonts/Knewave/Knewave-Regular.ttf.import new file mode 100644 index 0000000..b563747 --- /dev/null +++ b/fonts/Knewave/Knewave-Regular.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://c3fsj6knyiuhl" +path="res://.godot/imported/Knewave-Regular.ttf-621ce63e5403426c07f1520fe86b0560.fontdata" + +[deps] + +source_file="res://fonts/Knewave/Knewave-Regular.ttf" +dest_files=["res://.godot/imported/Knewave-Regular.ttf-621ce63e5403426c07f1520fe86b0560.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=4 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/fonts/Knewave/OFL.txt b/fonts/Knewave/OFL.txt new file mode 100644 index 0000000..34f48fe --- /dev/null +++ b/fonts/Knewave/OFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2010, Tyler Finck , with Reserved Font Name: "Knewave". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/graphics/happy_material.tres b/graphics/happy_material.tres index 4cdfa67..8d285ac 100644 --- a/graphics/happy_material.tres +++ b/graphics/happy_material.tres @@ -1,5 +1,5 @@ [gd_resource type="StandardMaterial3D" format=3 uid="uid://df0n6u78ylb4h"] [resource] -albedo_color = Color(1, 0, 1, 1) -metallic_specular = 0.0 +albedo_color = Color(6.73831e-07, 0.700198, 0.789641, 1) +metallic_specular = 1.0 diff --git a/graphics/unhappy_material.tres b/graphics/unhappy_material.tres index e5d0a3d..c5bb7a3 100644 --- a/graphics/unhappy_material.tres +++ b/graphics/unhappy_material.tres @@ -1,4 +1,6 @@ [gd_resource type="StandardMaterial3D" format=3 uid="uid://brwwlwb1rpro7"] [resource] +albedo_color = Color(1, 0.32686, 0.232259, 1) metallic = 1.0 +metallic_specular = 0.0 diff --git a/elements/gravity.tscn b/gui/gravity.tscn similarity index 59% rename from elements/gravity.tscn rename to gui/gravity.tscn index 05ae674..ec75a02 100644 --- a/elements/gravity.tscn +++ b/gui/gravity.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=8 format=3 uid="uid://dw0xl8644x166"] +[gd_scene load_steps=7 format=3 uid="uid://dw0xl8644x166"] [ext_resource type="Texture2D" uid="uid://ctjugvy1v3y6b" path="res://graphics/arrow.svg" id="1_4mbho"] [ext_resource type="AudioStream" uid="uid://dmdbharecy448" path="res://sounds/gravity.ogg" id="2_5uwlw"] @@ -6,60 +6,35 @@ [sub_resource type="GDScript" id="GDScript_3yq1l"] script/source = "extends Control -var player_ready = false -const normal = 7 -const stronger = normal * 3 - -func _input(_event: InputEvent) -> void: - if player_ready: - var grav = stronger if Input.is_key_pressed(KEY_SHIFT) else normal - PhysicsServer3D.area_set_param(get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY, grav) -" - -[sub_resource type="GDScript" id="GDScript_my602"] -script/source = "extends TextureRect +@onready var direction_node: TextureRect = $Direction +@onready var animation: AnimationPlayer = $Direction/AnimationPlayer +@onready var audio: AudioStreamPlayer = $Direction/AudioStreamPlayer func _ready() -> void: # set the indicator to be fully transparent when it first spawns - self.self_modulate = Color(1, 1, 1, 0) + direction_node.self_modulate = Color(1, 1, 1, 0) -func _input(ev: InputEvent) -> void: - if ev is InputEventKey and ev.is_pressed(): - var k = ev.keycode - if k == KEY_UP or k == KEY_RIGHT or k == KEY_LEFT or k == KEY_DOWN: - var direction = Vector3() - if k == KEY_UP: - direction = Vector3.UP - self.rotation_degrees = -90 - $AudioStreamPlayer.pitch_scale = 1.05 - elif k == KEY_LEFT: - direction = Vector3.LEFT - self.rotation_degrees = -180 - $AudioStreamPlayer.pitch_scale = 1.02 - elif k == KEY_RIGHT: - direction = Vector3.RIGHT - self.rotation_degrees = 0 - $AudioStreamPlayer.pitch_scale = 0.98 - elif k == KEY_DOWN: - direction = Vector3.DOWN - self.rotation_degrees = 90 - $AudioStreamPlayer.pitch_scale = 0.95 - - if get_parent().player_ready == false or direction != PhysicsServer3D.area_get_param( - get_viewport().find_world_3d().space, - PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR - ): - get_parent().player_ready = true - PhysicsServer3D.area_set_param( - get_viewport().find_world_3d().space, - PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, - direction - ) - - if $AnimationPlayer.is_playing(): - $AnimationPlayer.stop() - $AudioStreamPlayer.play() - $AnimationPlayer.play(\"grow_fadeout\") +func react_to_gravity_change(direction: Vector3) -> void: + if direction == Vector3.UP: + direction_node.rotation_degrees = -90 + audio.pitch_scale = 1.05 + elif direction == Vector3.LEFT: + direction_node.rotation_degrees = -180 + audio.pitch_scale = 1.02 + elif direction == Vector3.RIGHT: + direction = Vector3.RIGHT + direction_node.rotation_degrees = 0 + audio.pitch_scale = 0.98 + elif direction == Vector3.DOWN: + direction_node.rotation_degrees = 90 + audio.pitch_scale = 0.95 + + if animation.is_playing(): + animation.stop() + animation.play(\"grow_fadeout\") + + if Settings.sound_on_gravity_change: + audio.play() " [sub_resource type="Animation" id="Animation_6rwl4"] @@ -120,8 +95,8 @@ tracks/1/keys = { [sub_resource type="AnimationLibrary" id="AnimationLibrary_0w0ne"] _data = { -"RESET": SubResource("Animation_6rwl4"), -"grow_fadeout": SubResource("Animation_ll6d0") +&"RESET": SubResource("Animation_6rwl4"), +&"grow_fadeout": SubResource("Animation_ll6d0") } [node name="Gravity" type="Control"] @@ -131,6 +106,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +mouse_filter = 2 script = SubResource("GDScript_3yq1l") [node name="Direction" type="TextureRect" parent="."] @@ -149,15 +125,16 @@ grow_horizontal = 2 grow_vertical = 2 scale = Vector2(0.3, 0.3) pivot_offset = Vector2(400, 400) +mouse_filter = 2 texture = ExtResource("1_4mbho") -script = SubResource("GDScript_my602") [node name="AnimationPlayer" type="AnimationPlayer" parent="Direction"] libraries = { -"": SubResource("AnimationLibrary_0w0ne") +&"": SubResource("AnimationLibrary_0w0ne") } [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="Direction"] stream = ExtResource("2_5uwlw") volume_db = -6.0 mix_target = 2 +bus = &"Sounds" diff --git a/gui/map.tscn b/gui/map.tscn new file mode 100644 index 0000000..28a0ad2 --- /dev/null +++ b/gui/map.tscn @@ -0,0 +1,66 @@ +[gd_scene load_steps=2 format=3 uid="uid://bcxbw6wd54ksv"] + +[sub_resource type="GDScript" id="GDScript_r4thc"] +script/source = "extends Control + +func _ready() -> void: + $TemplateRing.hide() + +func display_rings(player: Node3D, rings: Array[Ring]) -> void: + var old_rings_display := $Rings.get_children() + var difference := len(rings) - len(old_rings_display) + + # Too many displayed, free them + for i in -difference: + old_rings_display[-(1 + i)].queue_free() + # Not enough displayed, create some + for i in difference: + var new_child := $TemplateRing.duplicate() + new_child.name = \"Ring\" + str(i + 1) + new_child.show() + $Rings.add_child(new_child) + + var rings_display := $Rings.get_children() + var center: Vector2i = get_viewport().size / 2 + for i in len(rings): + rings_display[i].color = rings[i].material.albedo_color + rings_display[i].rotation = rings[i].rotation.z + rings_display[i].position.x = center.x + rings[i].position.x - player.ball_position.x + rings_display[i].position.y = center.y - rings[i].position.y + player.ball_position.y + + if rings[i].collected: + rings_display[i].scale = $TemplateRing.scale * 2 * min(4, max(1, rings[i].scale.x)) + else: + rings_display[i].scale = $TemplateRing.scale * 3 * min(4, max(1, rings[i].scale.x)) +" + +[node name="Map" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = SubResource("GDScript_r4thc") + +[node name="ColorRect" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(1, 0, 1, 0.0392157) + +[node name="Rings" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="TemplateRing" type="ColorRect" parent="."] +layout_mode = 0 +offset_right = 2.0 +offset_bottom = 2.0 diff --git a/gui/rings.tscn b/gui/rings.tscn new file mode 100644 index 0000000..e580c7e --- /dev/null +++ b/gui/rings.tscn @@ -0,0 +1,33 @@ +[gd_scene load_steps=4 format=3 uid="uid://cn55m5dqo3m6u"] + +[ext_resource type="FontFile" uid="uid://c3fsj6knyiuhl" path="res://fonts/Knewave/Knewave-Regular.ttf" id="1_nja12"] + +[sub_resource type="LabelSettings" id="LabelSettings_cnn6y"] +font = ExtResource("1_nja12") +font_size = 32 +outline_size = 8 +outline_color = Color(0, 0, 0, 1) +shadow_size = 8 +shadow_color = Color(0, 0, 0, 1) + +[sub_resource type="GDScript" id="GDScript_nja12"] +script/source = "extends Label + +var remaining_rings := 0: + get: return remaining_rings + set(value): + remaining_rings = value + if value >= 1: + var rings_word := \"rings\" if value != 1 else \"ring\" + self.text = str(value) + \" \" + rings_word + \" to go!\" + else: + self.text = \"You did it!!\" +" + +[node name="Rings" type="Label"] +offset_right = 109.0 +offset_bottom = 23.0 +text = "69 rings to go!" +label_settings = SubResource("LabelSettings_cnn6y") +horizontal_alignment = 2 +script = SubResource("GDScript_nja12") diff --git a/gui/speed.tscn b/gui/speed.tscn new file mode 100644 index 0000000..92fadba --- /dev/null +++ b/gui/speed.tscn @@ -0,0 +1,34 @@ +[gd_scene load_steps=4 format=3 uid="uid://cckeamgkt8bqo"] + +[ext_resource type="FontFile" uid="uid://c3fsj6knyiuhl" path="res://fonts/Knewave/Knewave-Regular.ttf" id="1_xaun4"] + +[sub_resource type="LabelSettings" id="LabelSettings_8g5s8"] +font = ExtResource("1_xaun4") +font_size = 32 +font_color = Color(1, 0, 0, 1) +outline_size = 8 +shadow_size = 8 +shadow_color = Color(0, 0, 0, 1) + +[sub_resource type="GDScript" id="GDScript_xaun4"] +script/source = "extends Label + +var ball_velocity := 0.0: + get: return ball_velocity + set(value): + ball_velocity = value + var rounded: float = floor(value) + self.text = str(int(rounded)) + \" km/h\" + + const min_px = 32.0 + const max_px = 56.0 + self.label_settings.font_size = min(max(rounded / 3, min_px), max_px) + self.label_settings.outline_size = min(max(rounded / 12, min_px / 4), max_px / 4) + self.label_settings.shadow_size = min(max(rounded / 12, min_px / 4), max_px / 4) +" + +[node name="Speed" type="Label"] +text = "0 km/h" +label_settings = SubResource("LabelSettings_8g5s8") +horizontal_alignment = 2 +script = SubResource("GDScript_xaun4") diff --git a/gui/timer.tscn b/gui/timer.tscn new file mode 100644 index 0000000..a5f88dd --- /dev/null +++ b/gui/timer.tscn @@ -0,0 +1,142 @@ +[gd_scene load_steps=9 format=3 uid="uid://xd3nsiglcdfc"] + +[ext_resource type="FontFile" uid="uid://c3fsj6knyiuhl" path="res://fonts/Knewave/Knewave-Regular.ttf" id="1_m1tld"] + +[sub_resource type="GDScript" id="GDScript_q235s"] +script/source = "extends VBoxContainer + +var enabled := false: + get: return enabled + set(value): + if enabled == value: + return + enabled = value + if value == false: + $AnimationPlayer.play(\"scale_linear\") + await get_tree().create_timer($AnimationPlayer.current_animation_length).timeout + $AnimationPlayer.play_backwards(\"scale_cubic\") + +var seconds_spent_total := 0.0: + get: return seconds_spent_total + set(value): + seconds_spent_total = value + $Total.text = \"Total: \" + seconds_to_readable(seconds_spent_total) +var seconds_spent_level_attempt := 0.0: + get: return seconds_spent_level_attempt + set(value): + seconds_spent_level_attempt = value + $Level.text = \"Level: \" + seconds_to_readable(seconds_spent_level_attempt) + +func _on_visibility_changed() -> void: + if self.visible and len(SaveFiles.selected_file): + var save_file = SaveFiles.read(SaveFiles.selected_file) + if save_file.has(\"played_for\") and save_file.played_for is float: + seconds_spent_total = save_file.played_for + else: + seconds_spent_total = 0.0 + +func seconds_to_readable(seconds: float) -> String: + var minutes: int = floor(seconds / 60) + return (\"%0*d\" % [2, minutes]) + \":\" + (\"%0*.3f\" % [6, seconds - (minutes * 60)]) + +func _physics_process(delta: float) -> void: + if enabled: + seconds_spent_total += delta + seconds_spent_level_attempt += delta +" + +[sub_resource type="LabelSettings" id="LabelSettings_m1tld"] +font = ExtResource("1_m1tld") +font_size = 32 +outline_size = 8 +outline_color = Color(1, 0, 1, 1) +shadow_size = 8 +shadow_color = Color(0, 0, 0, 1) + +[sub_resource type="LabelSettings" id="LabelSettings_2a86r"] +font = ExtResource("1_m1tld") +font_size = 24 +outline_size = 8 +outline_color = Color(0, 0, 1, 1) +shadow_size = 8 +shadow_color = Color(0, 0, 0, 1) + +[sub_resource type="Animation" id="Animation_m1tld"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(1, 1)] +} + +[sub_resource type="Animation" id="Animation_houb3"] +resource_name = "scale_cubic" +length = 0.25 +step = 0.25 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.25), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector2(1, 1), Vector2(1.2, 1.2)] +} + +[sub_resource type="Animation" id="Animation_2a86r"] +resource_name = "scale_linear" +length = 0.25 +step = 0.25 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.25), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector2(1, 1), Vector2(1.2, 1.2)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_jmgpn"] +_data = { +&"RESET": SubResource("Animation_m1tld"), +&"scale_cubic": SubResource("Animation_houb3"), +&"scale_linear": SubResource("Animation_2a86r") +} + +[node name="Timer" type="VBoxContainer"] +process_mode = 3 +offset_right = 315.0 +offset_bottom = 85.0 +theme_override_constants/separation = -5 +script = SubResource("GDScript_q235s") + +[node name="Total" type="Label" parent="."] +layout_mode = 2 +text = "Total: 0:00.000" +label_settings = SubResource("LabelSettings_m1tld") + +[node name="Level" type="Label" parent="."] +layout_mode = 2 +text = "Level: 0:00.000" +label_settings = SubResource("LabelSettings_2a86r") + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +&"": SubResource("AnimationLibrary_jmgpn") +} + +[connection signal="visibility_changed" from="." to="." method="_on_visibility_changed"] diff --git a/icon.svg b/icon.svg deleted file mode 100644 index 9d8b7fa..0000000 --- a/icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/index.tscn b/index.tscn index d09f96c..c17011e 100644 --- a/index.tscn +++ b/index.tscn @@ -1,105 +1,125 @@ -[gd_scene load_steps=11 format=3 uid="uid://ccgnnif026wb4"] +[gd_scene load_steps=8 format=3 uid="uid://ccgnnif026wb4"] -[ext_resource type="PackedScene" uid="uid://n40mg5tc3bnv" path="res://levels/demo_level.tscn" id="1_08svf"] +[ext_resource type="PackedScene" uid="uid://xd3nsiglcdfc" path="res://gui/timer.tscn" id="1_356j3"] +[ext_resource type="PackedScene" uid="uid://dw0xl8644x166" path="res://gui/gravity.tscn" id="1_ir7so"] +[ext_resource type="PackedScene" uid="uid://cckeamgkt8bqo" path="res://gui/speed.tscn" id="2_2gn6w"] +[ext_resource type="PackedScene" uid="uid://bcxbw6wd54ksv" path="res://gui/map.tscn" id="2_d1yoc"] +[ext_resource type="PackedScene" uid="uid://cn55m5dqo3m6u" path="res://gui/rings.tscn" id="3_mbj17"] +[ext_resource type="PackedScene" uid="uid://dkxtwpcy4moyo" path="res://menus/pause_menu.tscn" id="4_3bfj3"] [sub_resource type="GDScript" id="GDScript_8n212"] script/source = "extends Node -var seconds_spent: float = 0.0 -var changing_level: bool = false -var base = preload(\"res://levels/base/level.tscn\") -var forest = preload(\"res://levels/forest/level.tscn\") -var night = preload(\"res://levels/night/level.tscn\") +var playing := false +var changing_level := false + +var main_menu: Node +var current_level: Level +var current_level_scene: PackedScene + +const res_main_menu = preload(\"res://menus/main/main_menu.tscn\") + +@onready var gui_gravity := $GUI/Gravity +@onready var gui_map := $GUI/Map +@onready var gui_timer := $GUI/TopLeft/Timer +@onready var gui_speed := $GUI/TopRight/Speed +@onready var gui_rings := $GUI/BottomRight/Rings +@onready var pause_menu := $PauseMenu func _ready() -> void: - var os_name = OS.get_name() - if os_name == \"Web\": ## we can't quit the game on web - $PauseMenu/VBoxContainer/Btn_Quit.hide() - - $VictoryScreen.hide() - $Informations.hide() - $PauseMenu.hide() ## Add the version of the game and the name of the OS to the footer of the start menu - $StartMenu/VBoxContainer/MarginContainer2/Notice.text += \" - build \" + ProjectSettings.get_setting(\"application/config/version\") + \" (\" + os_name + \")\" + if OS.has_feature(\"editor\"): + $DevInfos.text = \"dev \" + $DevInfos.text += \"build \" + ProjectSettings.get_setting(\"application/config/version\") + \" (\" + OS.get_name() + \")\" + + ## Hide UI stuff that shouldn't be visible until later in the game + pause_menu.hide() + + ## Connect to necessary signals + pause_menu.connect(\"request_pause\", pause_game) + pause_menu.connect(\"request_fullscreen\", fullscreen_game) + pause_menu.connect(\"request_restart\", restart_level) + + set_main_menu() -func start_level(level_scene: PackedScene) -> void: - $VictoryScreen.hide() - if level_scene and level_scene.can_instantiate(): - var level = level_scene.instantiate() - $Levels.add_child(level) - $Timer.paused = false - AudioServer.set_bus_volume_db(0, 0) - PhysicsServer3D.area_set_param( - get_viewport().find_world_3d().space, - PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, - Vector3.DOWN - ) - changing_level = false - else: - $VictoryScreen.show() - await get_tree().create_timer(2).timeout - $StartMenu/AnimationPlayer.play_backwards(\"fadeout\") - Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) - await get_tree().create_timer(1).timeout - $StartMenu.modulate = Color(1,1,1,1) +func set_main_menu() -> void: + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + $GUI.hide() + + ## If no main menu exists yet, create one + if !is_instance_valid(main_menu): + main_menu = res_main_menu.instantiate() + main_menu.connect(\"request_play_level\", start_level) + add_child(main_menu) -func stop_level() -> void: - PhysicsServer3D.area_set_param(get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY, 1) - $Timer.paused = true +func start_level(level: Level, scene: PackedScene) -> void: + if is_instance_valid(current_level): + current_level.queue_free() + if is_instance_valid(main_menu) and self.is_ancestor_of(main_menu): + self.remove_child(main_menu) + + current_level = level + current_level_scene = scene + add_child(current_level) + + current_level.connect(\"started_playing\", func(): gui_timer.enabled = true) + current_level.connect(\"gravity_change\", gui_gravity.react_to_gravity_change) + current_level.connect(\"completed\", finish_current_level) + current_level.connect(\"ring_collected\", func(): + gui_rings.remaining_rings = len(current_level.rings) - current_level.finished_rings_count + ) + gui_rings.remaining_rings = len(current_level.rings) - current_level.finished_rings_count + + $GUI.show() + Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) + pause_game(false) + + playing = true + changing_level = false + gui_timer.seconds_spent_level_attempt = 0.0 + +func finish_current_level() -> void: + gui_timer.enabled = false + PhysicsServer3D.area_set_param(get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY, 0.5) + playing = false changing_level = true - AudioServer.set_bus_volume_db(0, -5) - await get_tree().create_timer(0.5).timeout - AudioServer.set_bus_volume_db(0, -10) - await get_tree().create_timer(0.5).timeout - AudioServer.set_bus_volume_db(0, -30) - await get_tree().create_timer(0.5).timeout - AudioServer.set_bus_volume_db(0, -50) - await get_tree().create_timer(0.5).timeout + SaveFiles.change_property(\"played_for\", gui_timer.seconds_spent_total, SaveFiles.selected_file) + var save_file_data = SaveFiles.read(SaveFiles.selected_file) + var property_name := current_level.id + \"_best_time\" + if !save_file_data.has(property_name) or save_file_data[property_name] is not float or save_file_data[property_name] > gui_timer.seconds_spent_level_attempt: + SaveFiles.change_property(property_name, gui_timer.seconds_spent_level_attempt, SaveFiles.selected_file) - var next_level: PackedScene - var current_levels = $Levels.get_children(true) - if len(current_levels): - var current_level = current_levels[0] - if current_level.get_meta(\"name\") == \"Base\": - next_level = forest - elif current_level.get_meta(\"name\") == \"Forest\": - next_level = night - - for level in current_levels: - level.queue_free() + current_level.music.fadeOut(2) + await get_tree().create_timer(2).timeout + current_level.queue_free() - start_level(next_level) + set_main_menu() func restart_level() -> void: - if changing_level == false: - var current_levels = $Levels.get_children(true) - if len(current_levels): - pause_game() - changing_level = true - var current_level = current_levels[0] - - var next_level: PackedScene = base - if current_level.get_meta(\"name\") == \"Forest\": - next_level = forest - elif current_level.get_meta(\"name\") == \"Night\": - next_level = night - - for level in current_levels: - level.queue_free() - - start_level(next_level) + gui_timer.enabled = false + if !current_level or changing_level: + return + if current_level_scene is not PackedScene: + print(\"Tried to restart the level despite not having the level scene\") + return + SaveFiles.change_property(\"played_for\", gui_timer.seconds_spent_total, SaveFiles.selected_file) + start_level(current_level_scene.instantiate(), current_level_scene) -func pause_game() -> void: - if $Levels.process_mode == PROCESS_MODE_INHERIT: - $Levels.process_mode = Node.PROCESS_MODE_DISABLED - $Timer.paused = true - $PauseMenu.show() +func pause_game(to_pause: bool) -> void: + if !is_instance_valid(current_level) or changing_level: + return + + if to_pause: + SaveFiles.change_property(\"played_for\", gui_timer.seconds_spent_total, SaveFiles.selected_file) + current_level.process_mode = Node.PROCESS_MODE_DISABLED + playing = false + pause_menu.show() Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) else: - $Levels.process_mode = Node.PROCESS_MODE_INHERIT - $Timer.paused = false - $PauseMenu.hide() + current_level.process_mode = Node.PROCESS_MODE_INHERIT + playing = true + pause_menu.hide() Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) func fullscreen_game() -> void: @@ -109,390 +129,94 @@ func fullscreen_game() -> void: else: DisplayServer.window_set_mode(DisplayServer.WindowMode.WINDOW_MODE_WINDOWED) -func _on_btn_fullscreen_pressed() -> void: - fullscreen_game() - -func _on_btn_start_pressed() -> void: - seconds_spent = 0.0 - var current_levels = $Levels.get_children(true) - for level in current_levels: - level.queue_free() - - $Informations.show() - $StartMenu/AnimationPlayer.play(\"fadeout\") - Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) - start_level(base) - - $Timer.start(0) - -func _on_animation_player_animation_finished(_anim_name: StringName) -> void: - if $StartMenu.modulate == Color(1,1,1,1): - $StartMenu.show() - else: - $StartMenu.hide() - -func _on_timer_timeout() -> void: - seconds_spent = snapped(seconds_spent + 0.10, 0.01) - var minutes = floor(seconds_spent / 60) - $Informations/MarginContainer/Timer.text = (\"%0*d\" % [2, minutes]) + \":\" + (\"%0*.1f\" % [4, seconds_spent - (minutes * 60)]) - func _process(_delta: float) -> void: - var current_levels = $Levels.get_children(true) - if len(current_levels): - var current_level = current_levels[0] - if is_instance_valid(current_level): - if \"velocity\" in current_level: - $Informations/MarginContainer/VBoxContainer/Speed.text = str(floor(current_level.velocity)) + \" km/h\" - if \"rings_count\" in current_level and \"finished_rings_count\" in current_level: - $Informations/MarginContainer/VBoxContainer/Rings.text = str(current_level.finished_rings_count) + \"/\" + str(current_level.rings_count) + if is_instance_valid(current_level): + gui_speed.ball_velocity = current_level.velocity + if Input.is_action_pressed(\"display_map\"): + gui_map.display_rings(current_level.player, current_level.rings) -func _unhandled_key_input(event: InputEvent) -> void: - if event.is_pressed() and event is InputEventKey: - if $StartMenu.visible == false and changing_level == false: - if event.keycode == KEY_ESCAPE: - pause_game() - elif event.keycode == KEY_R: - pause_game() - restart_level() - -func _on_btn_resume_pressed() -> void: - pause_game() - -func _on_btn_fullscreen_2_pressed() -> void: - fullscreen_game() - -func _on_btn_restart_pressed() -> void: - restart_level() +func _input(_event: InputEvent) -> void: + if Input.is_action_just_released(\"display_map\"): + gui_map.hide() + if Input.is_action_just_pressed(\"display_map\"): + gui_map.show() + if Input.is_action_just_pressed(\"restart_level\"): + restart_level() func _on_btn_quit_pressed() -> void: get_tree().quit() " -[sub_resource type="LabelSettings" id="LabelSettings_0s07t"] -font_size = 32 -outline_size = 10 -outline_color = Color(0, 0, 0, 1) - -[sub_resource type="LabelSettings" id="LabelSettings_1bs00"] -font_size = 160 -outline_size = 20 -outline_color = Color(0, 0, 0, 1) - -[sub_resource type="LabelSettings" id="LabelSettings_0jegv"] -font_size = 32 -shadow_size = 2 -shadow_color = Color(0, 0, 0, 1) -shadow_offset = Vector2(0, 0) - -[sub_resource type="LabelSettings" id="LabelSettings_nbp4i"] -font_size = 24 -shadow_size = 2 -shadow_color = Color(0, 0, 0, 1) -shadow_offset = Vector2(0, 0) - -[sub_resource type="LabelSettings" id="LabelSettings_5jdmh"] -font_size = 20 -shadow_size = 2 -shadow_color = Color(0, 0, 0, 1) -shadow_offset = Vector2(0, 0) - -[sub_resource type="Animation" id="Animation_glb01"] -length = 0.001 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath(".:modulate") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [Color(1, 1, 1, 1)] -} - -[sub_resource type="Animation" id="Animation_75r06"] -resource_name = "fadeout" -step = 0.5 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath(".:modulate") -tracks/0/interp = 2 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0, 1), -"transitions": PackedFloat32Array(1, 1), -"update": 0, -"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)] -} - -[sub_resource type="AnimationLibrary" id="AnimationLibrary_5cb2g"] -_data = { -"RESET": SubResource("Animation_glb01"), -"fadeout": SubResource("Animation_75r06") -} - [node name="Game" type="Node"] script = SubResource("GDScript_8n212") -[node name="Informations" type="Control" parent="."] +[node name="GUI" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="Gravity" parent="GUI" instance=ExtResource("1_ir7so")] +layout_mode = 1 + +[node name="Map" parent="GUI" instance=ExtResource("2_d1yoc")] visible = false -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -mouse_filter = 1 - -[node name="MarginContainer" type="MarginContainer" parent="Informations"] 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 = 10 -theme_override_constants/margin_right = 10 -[node name="Timer" type="Label" parent="Informations/MarginContainer"] -layout_mode = 2 -size_flags_horizontal = 0 -size_flags_vertical = 8 -text = "00:00.0" -label_settings = SubResource("LabelSettings_0s07t") -vertical_alignment = 2 - -[node name="VBoxContainer" type="VBoxContainer" parent="Informations/MarginContainer"] -layout_mode = 2 -theme_override_constants/separation = -5 -alignment = 2 - -[node name="Rings" type="Label" parent="Informations/MarginContainer/VBoxContainer"] -layout_mode = 2 -text = "0/0" -label_settings = SubResource("LabelSettings_0s07t") -horizontal_alignment = 2 -vertical_alignment = 2 - -[node name="Speed" type="Label" parent="Informations/MarginContainer/VBoxContainer"] -layout_mode = 2 -text = "0 km/h" -label_settings = SubResource("LabelSettings_0s07t") -horizontal_alignment = 2 -vertical_alignment = 2 - -[node name="VictoryScreen" type="Control" parent="."] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="Label" type="Label" parent="VictoryScreen"] +[node name="TopLeft" type="MarginContainer" parent="GUI"] layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "YOU WON!" -label_settings = SubResource("LabelSettings_1bs00") -horizontal_alignment = 1 -vertical_alignment = 1 +offset_right = 160.0 +offset_bottom = 85.0 +rotation = 0.0523599 +theme_override_constants/margin_left = 15 -[node name="Levels" type="Node" parent="."] +[node name="Timer" parent="GUI/TopLeft" instance=ExtResource("1_356j3")] +layout_mode = 2 -[node name="Demo" parent="Levels" instance=ExtResource("1_08svf")] - -[node name="Timer" type="Timer" parent="."] -wait_time = 0.1 - -[node name="StartMenu" type="Control" parent="."] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 - -[node name="ColorRect" type="ColorRect" parent="StartMenu"] +[node name="TopRight" type="MarginContainer" parent="GUI"] layout_mode = 1 -anchors_preset = 15 +anchors_preset = 1 +anchor_left = 1.0 anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -color = Color(0.522749, 0.477374, 0.510111, 0.501961) +offset_left = -106.0 +offset_bottom = 51.0 +grow_horizontal = 0 +rotation = -0.0523599 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_right = 15 -[node name="VBoxContainer" type="VBoxContainer" parent="StartMenu"] +[node name="Speed" parent="GUI/TopRight" instance=ExtResource("2_2gn6w")] +layout_mode = 2 + +[node name="BottomRight" type="MarginContainer" parent="GUI"] layout_mode = 1 -anchors_preset = 15 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 anchor_right = 1.0 anchor_bottom = 1.0 +offset_left = -222.0 +offset_top = -51.0 +grow_horizontal = 0 +grow_vertical = 0 +rotation = 0.0523599 +theme_override_constants/margin_right = 15 +theme_override_constants/margin_bottom = 15 + +[node name="Rings" parent="GUI/BottomRight" instance=ExtResource("3_mbj17")] +layout_mode = 2 + +[node name="DevInfos" type="Label" parent="."] +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -23.0 grow_horizontal = 2 -grow_vertical = 2 - -[node name="Presentation" type="MarginContainer" parent="StartMenu/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 -theme_override_constants/margin_left = 20 -theme_override_constants/margin_top = 20 -theme_override_constants/margin_right = 20 -theme_override_constants/margin_bottom = 20 - -[node name="VBoxContainer" type="VBoxContainer" parent="StartMenu/VBoxContainer/Presentation"] -layout_mode = 2 - -[node name="Title" type="Label" parent="StartMenu/VBoxContainer/Presentation/VBoxContainer"] -layout_mode = 2 -text = "DreamBall" -label_settings = SubResource("LabelSettings_0jegv") +grow_vertical = 0 horizontal_alignment = 1 -[node name="Title2" type="Label" parent="StartMenu/VBoxContainer/Presentation/VBoxContainer"] -layout_mode = 2 -text = "A game about changing gravity to make a ball fly through the air" -label_settings = SubResource("LabelSettings_nbp4i") -horizontal_alignment = 1 - -[node name="MarginContainer" type="MarginContainer" parent="StartMenu/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 3 -theme_override_constants/margin_left = 20 -theme_override_constants/margin_top = 20 -theme_override_constants/margin_right = 20 -theme_override_constants/margin_bottom = 20 - -[node name="HBoxContainer" type="HBoxContainer" parent="StartMenu/VBoxContainer/MarginContainer"] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="Rules" type="VBoxContainer" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -alignment = 2 - -[node name="Label" type="Label" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Rules"] -layout_mode = 2 -text = "- Change the direction of the gravity with the ARROW KEYS" - -[node name="Label2" type="Label" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Rules"] -layout_mode = 2 -text = "- Keep LEFT SHIFT pressed to make the gravity stronger" - -[node name="Label3" type="Label" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Rules"] -layout_mode = 2 -text = "- Press ESCAPE to pause and unpause the game at any point" - -[node name="Label4" type="Label" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Rules"] -layout_mode = 2 -text = "- Press R to restart the current level from the beginning -(note that it won't reset the timer!)" - -[node name="Buttons" type="VBoxContainer" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -alignment = 2 - -[node name="Label5" type="Label" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Buttons"] -layout_mode = 2 -text = "Do your best to make the ball go through all the rings!" -horizontal_alignment = 1 - -[node name="HBoxContainer" type="HBoxContainer" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Buttons"] -layout_mode = 2 -theme_override_constants/separation = 20 -alignment = 1 - -[node name="Btn_Fullscreen" type="Button" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Buttons/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -action_mode = 0 -text = "Toggle FULLSCREEN" - -[node name="Btn_Start" type="Button" parent="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Buttons/HBoxContainer"] -layout_mode = 2 -size_flags_horizontal = 4 -text = "START the game!" - -[node name="MarginContainer2" type="MarginContainer" parent="StartMenu/VBoxContainer"] -layout_mode = 2 -theme_override_constants/margin_left = 20 -theme_override_constants/margin_top = 20 -theme_override_constants/margin_right = 20 -theme_override_constants/margin_bottom = 20 - -[node name="Notice" type="Label" parent="StartMenu/VBoxContainer/MarginContainer2"] -layout_mode = 2 -text = "Made during the 21st edition of Alakajam!" -label_settings = SubResource("LabelSettings_5jdmh") -horizontal_alignment = 1 - -[node name="AnimationPlayer" type="AnimationPlayer" parent="StartMenu"] -libraries = { -"": SubResource("AnimationLibrary_5cb2g") -} - -[node name="PauseMenu" type="Control" parent="."] -visible = false -z_index = 2 -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -mouse_filter = 1 - -[node name="ColorRect" type="ColorRect" parent="PauseMenu"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -color = Color(1, 0.54902, 1, 0.109804) - -[node name="VBoxContainer" type="VBoxContainer" parent="PauseMenu"] -layout_mode = 1 -anchors_preset = 14 -anchor_top = 0.5 -anchor_right = 1.0 -anchor_bottom = 0.5 -offset_top = -50.5 -offset_bottom = 50.5 -grow_horizontal = 2 -grow_vertical = 2 -theme_override_constants/separation = 10 - -[node name="Btn_Resume" type="Button" parent="PauseMenu/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 6 -text = "RESUME game" - -[node name="Btn_Fullscreen2" type="Button" parent="PauseMenu/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 6 -text = "Toggle FULLSCREEN" - -[node name="Btn_Restart" type="Button" parent="PauseMenu/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 6 -text = "RESTART the level" - -[node name="Btn_Quit" type="Button" parent="PauseMenu/VBoxContainer"] -layout_mode = 2 -size_flags_vertical = 6 -text = "QUIT game" - -[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"] -[connection signal="pressed" from="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Buttons/HBoxContainer/Btn_Fullscreen" to="." method="_on_btn_fullscreen_pressed"] -[connection signal="pressed" from="StartMenu/VBoxContainer/MarginContainer/HBoxContainer/Buttons/HBoxContainer/Btn_Start" to="." method="_on_btn_start_pressed"] -[connection signal="animation_finished" from="StartMenu/AnimationPlayer" to="." method="_on_animation_player_animation_finished"] -[connection signal="pressed" from="PauseMenu/VBoxContainer/Btn_Resume" to="." method="_on_btn_resume_pressed"] -[connection signal="pressed" from="PauseMenu/VBoxContainer/Btn_Fullscreen2" to="." method="_on_btn_fullscreen_2_pressed"] -[connection signal="pressed" from="PauseMenu/VBoxContainer/Btn_Restart" to="." method="_on_btn_restart_pressed"] -[connection signal="pressed" from="PauseMenu/VBoxContainer/Btn_Quit" to="." method="_on_btn_quit_pressed"] +[node name="PauseMenu" parent="." instance=ExtResource("4_3bfj3")] diff --git a/levels/base/environment.tscn b/levels/base/environment.tscn deleted file mode 100644 index a3dab31..0000000 --- a/levels/base/environment.tscn +++ /dev/null @@ -1,26 +0,0 @@ -[gd_scene load_steps=6 format=3 uid="uid://ygvokp5f78i5"] - -[sub_resource type="Gradient" id="Gradient_hs6gw"] - -[sub_resource type="GradientTexture2D" id="GradientTexture2D_hyysp"] -gradient = SubResource("Gradient_hs6gw") -fill_from = Vector2(0.536082, 1) -fill_to = Vector2(0.536082, 0) - -[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_g3k38"] -panorama = SubResource("GradientTexture2D_hyysp") - -[sub_resource type="Sky" id="Sky_du8e4"] -sky_material = SubResource("PanoramaSkyMaterial_g3k38") -radiance_size = 1 - -[sub_resource type="Environment" id="Environment_y0yoy"] -background_mode = 2 -background_color = Color(0.758192, 0.758192, 0.758192, 1) -sky = SubResource("Sky_du8e4") -ambient_light_source = 3 -ambient_light_color = Color(1, 1, 1, 1) -reflected_light_source = 2 - -[node name="Environment" type="WorldEnvironment"] -environment = SubResource("Environment_y0yoy") diff --git a/levels/base/level.tscn b/levels/base/level.tscn index d0ec56b..35859e2 100644 --- a/levels/base/level.tscn +++ b/levels/base/level.tscn @@ -1,19 +1,49 @@ -[gd_scene load_steps=8 format=3 uid="uid://b0mhosbyt1fit"] +[gd_scene load_steps=11 format=3 uid="uid://ovtknjyj83gh"] -[ext_resource type="Material" uid="uid://brwwlwb1rpro7" path="res://graphics/unhappy_material.tres" id="1_dwsqy"] -[ext_resource type="PackedScene" uid="uid://ygvokp5f78i5" path="res://levels/base/environment.tscn" id="1_n7fd8"] -[ext_resource type="Script" path="res://levels/level.gd" id="1_rj40i"] [ext_resource type="PackedScene" uid="uid://cnnvwotv33u1b" path="res://elements/player.tscn" id="2_b00jj"] [ext_resource type="PackedScene" uid="uid://cpm3laywhlbq5" path="res://elements/ring.tscn" id="3_hel5x"] [ext_resource type="PackedScene" uid="uid://c77bli40240nk" path="res://elements/sign.tscn" id="4_atq6y"] -[ext_resource type="PackedScene" uid="uid://cgt5st4qacruw" path="res://levels/base/music.tscn" id="4_uq42r"] +[ext_resource type="PackedScene" uid="uid://dnuakh7n3fuij" path="res://levels/base/music.tscn" id="4_uq42r"] + +[sub_resource type="GDScript" id="GDScript_1yugx"] +script/source = "extends Level + +func _init() -> void: + self.id = \"base\" + +func _on_player_velocity_change(new_velocity: float) -> void: + self.velocity = new_velocity + self.music.adaptInstrumentsToVelocity(new_velocity * 1.5) +" + +[sub_resource type="Gradient" id="Gradient_hs6gw"] + +[sub_resource type="GradientTexture2D" id="GradientTexture2D_hyysp"] +gradient = SubResource("Gradient_hs6gw") +fill_from = Vector2(0.536082, 1) +fill_to = Vector2(0.536082, 0) + +[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_g3k38"] +panorama = SubResource("GradientTexture2D_hyysp") + +[sub_resource type="Sky" id="Sky_du8e4"] +sky_material = SubResource("PanoramaSkyMaterial_g3k38") +radiance_size = 1 + +[sub_resource type="Environment" id="Environment_y0yoy"] +background_mode = 2 +background_color = Color(0.758192, 0.758192, 0.758192, 1) +sky = SubResource("Sky_du8e4") +ambient_light_source = 3 +ambient_light_color = Color(1, 1, 1, 1) +reflected_light_source = 2 [node name="Base" type="Node3D"] -script = ExtResource("1_rj40i") -metadata/material = ExtResource("1_dwsqy") -metadata/name = "Base" +script = SubResource("GDScript_1yugx") +metadata/_custom_type_script = "uid://w3fetao1pegm" -[node name="Environment" parent="." instance=ExtResource("1_n7fd8")] +[node name="Environment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_y0yoy") [node name="Music" parent="." instance=ExtResource("4_uq42r")] @@ -27,6 +57,7 @@ transform = Transform3D(-1, 8.74228e-08, 0, -8.74228e-08, -1, 0, 0, 0, 1, -366.4 transform = Transform3D(-1, -8.74228e-08, 0, 8.74228e-08, -1, 0, 0, 0, 1, -366.478, 3.24249e-05, 0) [node name="Text" parent="Signs/Sign" index="0"] +transform = Transform3D(20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0) text = "Press the arrow keys to change the gravity!" @@ -34,13 +65,14 @@ to change the gravity!" transform = Transform3D(4.37114e-08, -7.10543e-15, -1, -8.74228e-08, -1, 0, -1, 8.74228e-08, -4.37114e-08, 150, 40, 61) [node name="Text" parent="Signs/Sign7" index="0"] +transform = Transform3D(30, 0, 0, 0, 30, 0, 0, 0, 30, 0, 0, 0) text = "SLOW DOWN!!" -font_size = 2056 [node name="Sign2" parent="Signs" instance=ExtResource("4_atq6y")] transform = Transform3D(-1, -8.74228e-08, 0, 8.74228e-08, -1, 0, 0, 0, 1, -234.9, 2.09808e-05, 0) [node name="Text" parent="Signs/Sign2" index="0"] +transform = Transform3D(15, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0) text = "While the shift key is pressed, the gravity is much stronger!" @@ -48,6 +80,7 @@ the gravity is much stronger!" transform = Transform3D(-1, -8.74228e-08, 0, 8.74228e-08, -1, 0, 0, 0, 1, -131.629, 81.2564, 0) [node name="Text" parent="Signs/Sign4" index="0"] +transform = Transform3D(20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0) text = "You can take the rings in any order!" @@ -55,6 +88,7 @@ in any order!" transform = Transform3D(-4.37114e-08, 8.74228e-08, 1, 0, -1, 8.74228e-08, 1, 3.82137e-15, 4.37114e-08, -490.634, 50.3763, 34.0693) [node name="Text" parent="Signs/Sign5" index="0"] +transform = Transform3D(20, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0) text = "The level is over once you get all the rings!" @@ -62,13 +96,13 @@ you get all the rings!" transform = Transform3D(-0.707107, 6.18172e-08, 0.707107, -8.74228e-08, -1, 0, 0.707107, -6.18172e-08, 0.707107, -532.475, 18.0064, 60) [node name="Text" parent="Signs/Sign6" index="0"] +transform = Transform3D(30, 0, 0, 0, 30, 0, 0, 0, 30, 0, 0, 0) text = "Have fun!" -font_size = 2048 [node name="Sign3" parent="Signs" instance=ExtResource("4_atq6y")] [node name="Text" parent="Signs/Sign3" index="0"] -transform = Transform3D(-1, 8.74228e-08, 0, -8.74228e-08, -1, 0, 0, 0, 1, 0, 0, 0) +transform = Transform3D(-20, 3.01992e-06, 0, -3.01992e-06, -20, 0, 0, 0, 20, 0, 0, 0) text = "The less time you take, the more you can flex!" @@ -128,6 +162,8 @@ transform = Transform3D(0.0172464, 0.899835, 0, -0.899835, 0.0172464, 0, 0, 0, 0 [node name="Ring13" parent="Rings" instance=ExtResource("3_hel5x")] transform = Transform3D(0.0114976, 0.59989, 0, -0.59989, 0.0114976, 0, 0, 0, 0.6, -414.274, 8.64172, 0) +[connection signal="velocity_change" from="Player" to="." method="_on_player_velocity_change"] + [editable path="Signs/Sign"] [editable path="Signs/Sign7"] [editable path="Signs/Sign2"] diff --git a/levels/base/music.tscn b/levels/base/music.tscn index d6381e3..f6a2329 100644 --- a/levels/base/music.tscn +++ b/levels/base/music.tscn @@ -1,7 +1,7 @@ -[gd_scene load_steps=8 format=3 uid="uid://cgt5st4qacruw"] +[gd_scene load_steps=8 format=3 uid="uid://dnuakh7n3fuij"] [ext_resource type="AudioStream" uid="uid://b46a7y6vdqd4n" path="res://levels/base/music/hihat-closed.ogg" id="1_shxcq"] -[ext_resource type="Script" path="res://levels/music.gd" id="1_y1f1r"] +[ext_resource type="Script" uid="uid://dgpjhli3hpn0u" path="res://levels/music.gd" id="1_y1f1r"] [ext_resource type="AudioStream" uid="uid://buag3j2s22jpo" path="res://levels/base/music/hihat-open.ogg" id="3_xb717"] [ext_resource type="AudioStream" uid="uid://djmbrvp7k263k" path="res://levels/base/music/kick2.ogg" id="4_1da6f"] [ext_resource type="AudioStream" uid="uid://dma7btls87mg4" path="res://levels/base/music/kick.ogg" id="5_7thjx"] @@ -10,6 +10,7 @@ [node name="Music" type="Node"] script = ExtResource("1_y1f1r") +metadata/_custom_type_script = "uid://dgpjhli3hpn0u" [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] stream = ExtResource("1_shxcq") diff --git a/levels/demo_level.tscn b/levels/demo_level.tscn deleted file mode 100644 index 056ed1f..0000000 --- a/levels/demo_level.tscn +++ /dev/null @@ -1,29 +0,0 @@ -[gd_scene load_steps=6 format=3 uid="uid://n40mg5tc3bnv"] - -[ext_resource type="Script" path="res://levels/level.gd" id="1_ifscd"] -[ext_resource type="PackedScene" uid="uid://b6gnffoboc5j5" path="res://levels/night/environment.tscn" id="2_v6rg2"] -[ext_resource type="PackedScene" uid="uid://q7frlnx37gv6" path="res://levels/night/music.tscn" id="3_fb0ct"] -[ext_resource type="PackedScene" uid="uid://cnnvwotv33u1b" path="res://elements/player.tscn" id="4_ge8id"] -[ext_resource type="PackedScene" uid="uid://cpm3laywhlbq5" path="res://elements/ring.tscn" id="5_j060p"] - -[node name="Demo" type="Node3D"] -script = ExtResource("1_ifscd") -metadata/name = "Demo" - -[node name="Environment" parent="." instance=ExtResource("2_v6rg2")] - -[node name="Music" parent="." instance=ExtResource("3_fb0ct")] - -[node name="Player" parent="." instance=ExtResource("4_ge8id")] - -[node name="Rings" type="Node3D" parent="."] - -[node name="Ring" parent="Rings" instance=ExtResource("5_j060p")] -transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 15.6731, -50) -visible = false - -[node name="Ring2" parent="Rings" instance=ExtResource("5_j060p")] -transform = Transform3D(-4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0, 1, 10, -10, 0) - -[node name="Ring3" parent="Rings" instance=ExtResource("5_j060p")] -transform = Transform3D(-4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0, 1, -10, -10, 0) diff --git a/levels/forest/environment.tscn b/levels/forest/environment.tscn deleted file mode 100644 index 4fd7d86..0000000 --- a/levels/forest/environment.tscn +++ /dev/null @@ -1,24 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://w4h8ip754qnb"] - -[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_clvpw"] -sky_top_color = Color(0, 0.504542, 0.579919, 1) -sky_horizon_color = Color(9.62615e-08, 0.776269, 0.496436, 1) -sky_curve = 0.219613 -ground_bottom_color = Color(0.078119, 0.275869, 4.81308e-08, 1) -ground_horizon_color = Color(0.300489, 0.406247, 0.0024617, 1) -sun_angle_max = 224.83 -sun_curve = 0.212132 - -[sub_resource type="Sky" id="Sky_8w3rf"] -sky_material = SubResource("ProceduralSkyMaterial_clvpw") - -[sub_resource type="Environment" id="Environment_nda78"] -background_mode = 2 -sky = SubResource("Sky_8w3rf") -sky_rotation = Vector3(0.0872665, 0.698132, 0.0872665) -ambient_light_source = 3 -ambient_light_color = Color(1, 1, 1, 1) -reflected_light_source = 2 - -[node name="Environment" type="WorldEnvironment"] -environment = SubResource("Environment_nda78") diff --git a/levels/forest/level.tscn b/levels/forest/level.tscn index 2f096e1..458d165 100644 --- a/levels/forest/level.tscn +++ b/levels/forest/level.tscn @@ -1,18 +1,63 @@ -[gd_scene load_steps=8 format=3 uid="uid://dfvuxfxc6ooya"] +[gd_scene load_steps=10 format=3 uid="uid://e1761h6d522a"] -[ext_resource type="PackedScene" uid="uid://w4h8ip754qnb" path="res://levels/forest/environment.tscn" id="1_7clrg"] -[ext_resource type="Script" path="res://levels/level.gd" id="1_fdxcj"] [ext_resource type="PackedScene" uid="uid://cnnvwotv33u1b" path="res://elements/player.tscn" id="2_mjogx"] -[ext_resource type="PackedScene" uid="uid://dp8nvfm55te85" path="res://levels/forest/music.tscn" id="3_n1xsx"] +[ext_resource type="PackedScene" uid="uid://cakmsiye3hjfe" path="res://levels/forest/music.tscn" id="3_n1xsx"] [ext_resource type="PackedScene" uid="uid://cpm3laywhlbq5" path="res://elements/ring.tscn" id="4_p8yhq"] [ext_resource type="PackedScene" uid="uid://da6lkdiskdh8v" path="res://elements/tree.tscn" id="6_1e514"] [ext_resource type="PackedScene" uid="uid://c77bli40240nk" path="res://elements/sign.tscn" id="6_ifogr"] -[node name="Forest" type="Node3D"] -script = ExtResource("1_fdxcj") -metadata/name = "Forest" +[sub_resource type="GDScript" id="GDScript_mqwxc"] +script/source = "extends Level -[node name="Environment" parent="." instance=ExtResource("1_7clrg")] +var cycle := 0 + +func _init() -> void: + self.id = \"forest\" + self.thumbnail = load(\"res://levels/forest/thumbnail.png\") + +func _process(_delta: float) -> void: + var moving_ring: Ring = $Rings/Ring18 + if !moving_ring.collected: + if moving_ring.position.y < 55 or moving_ring.position.y > 65: + cycle += 1 + moving_ring.position.y += 0.5 if cycle % 2 else -0.5 + +func _on_player_velocity_change(new_velocity: float) -> void: + self.velocity = new_velocity + self.music.adaptInstrumentsToVelocity(new_velocity) +" + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_grcut"] +sky_top_color = Color(0, 0.504542, 0.579919, 1) +sky_horizon_color = Color(9.62615e-08, 0.776269, 0.496436, 1) +sky_curve = 0.219613 +ground_bottom_color = Color(0.078119, 0.275869, 4.81308e-08, 1) +ground_horizon_color = Color(0.300489, 0.406247, 0.0024617, 1) +sun_angle_max = 224.83 +sun_curve = 0.212132 + +[sub_resource type="Sky" id="Sky_gxmta"] +sky_material = SubResource("ProceduralSkyMaterial_grcut") + +[sub_resource type="Environment" id="Environment_y3whn"] +background_mode = 2 +sky = SubResource("Sky_gxmta") +sky_rotation = Vector3(0.0872665, 0.698132, 0.0872665) +ambient_light_source = 3 +ambient_light_color = Color(1, 1, 1, 1) +reflected_light_source = 2 + +[node name="Forest" type="Node3D"] +script = SubResource("GDScript_mqwxc") +metadata/_custom_type_script = "uid://w3fetao1pegm" + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(-0.920505, 0.195366, -0.338383, 0, 0.866025, 0.5, 0.390731, 0.460252, -0.797181, 0, 0, 0) +shadow_enabled = true +directional_shadow_mode = 0 + +[node name="Environment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_y3whn") [node name="Music" parent="." instance=ExtResource("3_n1xsx")] @@ -22,9 +67,8 @@ metadata/name = "Forest" transform = Transform3D(-4.37114e-08, 8.74228e-08, 1, 0, -1, 8.74228e-08, 1, 3.82137e-15, 4.37114e-08, -450, 132.977, 0) [node name="Text" parent="Sign" index="0"] -transform = Transform3D(-1, 8.74228e-08, 0, -8.74228e-08, -1, 0, 0, 0, 1, 0, 0, 0) +transform = Transform3D(-35, 5.28485e-06, 0, -5.28485e-06, -35, 0, 0, 0, 35, 0, 0, 0) text = "Watch out!" -font_size = 2048 [node name="Trees" type="Node3D" parent="."] @@ -110,7 +154,7 @@ transform = Transform3D(-49.1471, 0, -9.19585, 0, 50, 0, 9.19585, 0, -49.1471, - transform = Transform3D(-28.781, 0, 40.8859, 0, 50, 0, -40.8859, 0, -28.781, -460.677, -329.892, 361.614) [node name="Tree28" parent="Trees" instance=ExtResource("6_1e514")] -transform = Transform3D(-28.781, 0, 40.8859, 0, 50, 0, -40.8859, 0, -28.781, -643.482, -296.989, 101.924) +transform = Transform3D(-28.781, 0, 40.8859, 0, 50, 0, -40.8859, 0, -28.781, -643.482, -296.989, 139.279) [node name="Tree29" parent="Trees" instance=ExtResource("6_1e514")] transform = Transform3D(-29.5106, 0, 40.3624, 0, 50, 0, -40.3624, 0, -29.5106, -418.092, -296.989, 136.2) @@ -234,4 +278,6 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -218.208, 206.247, 0) [node name="Ring23" parent="Rings" instance=ExtResource("4_p8yhq")] transform = Transform3D(0.939693, 0.34202, 0, -0.34202, 0.939693, 0, 0, 0, 1, -1018.15, -96.9134, 0) +[connection signal="velocity_change" from="Player" to="." method="_on_player_velocity_change"] + [editable path="Sign"] diff --git a/levels/forest/music.tscn b/levels/forest/music.tscn index d56669b..5d3d541 100644 --- a/levels/forest/music.tscn +++ b/levels/forest/music.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=8 format=3 uid="uid://dp8nvfm55te85"] +[gd_scene load_steps=8 format=3 uid="uid://cakmsiye3hjfe"] -[ext_resource type="Script" path="res://levels/music.gd" id="1_whsrg"] +[ext_resource type="Script" uid="uid://dgpjhli3hpn0u" path="res://levels/music.gd" id="1_whsrg"] [ext_resource type="AudioStream" uid="uid://pn2b2f3egpck" path="res://levels/forest/music/dong2.ogg" id="2_pm2p2"] [ext_resource type="AudioStream" uid="uid://dghw6a7i3adcu" path="res://levels/forest/music/dong.ogg" id="3_1eawt"] [ext_resource type="AudioStream" uid="uid://bu4kmowmputnr" path="res://levels/forest/music/hihat-closed.ogg" id="4_kv4yx"] @@ -10,6 +10,7 @@ [node name="Music" type="Node"] script = ExtResource("1_whsrg") +metadata/_custom_type_script = "uid://dgpjhli3hpn0u" [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] stream = ExtResource("2_pm2p2") diff --git a/levels/forest/thumbnail.png b/levels/forest/thumbnail.png new file mode 100644 index 0000000..07c40d6 Binary files /dev/null and b/levels/forest/thumbnail.png differ diff --git a/icon.svg.import b/levels/forest/thumbnail.png.import similarity index 62% rename from icon.svg.import rename to levels/forest/thumbnail.png.import index 9a07b08..01c5a71 100644 --- a/icon.svg.import +++ b/levels/forest/thumbnail.png.import @@ -2,16 +2,16 @@ importer="texture" type="CompressedTexture2D" -uid="uid://c4nwhhum2vht5" -path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +uid="uid://dhyxogc13hnbe" +path="res://.godot/imported/thumbnail.png-6909560b6205778a3cb325a584af7ca5.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://icon.svg" -dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] +source_file="res://levels/forest/thumbnail.png" +dest_files=["res://.godot/imported/thumbnail.png-6909560b6205778a3cb325a584af7ca5.ctex"] [params] @@ -32,6 +32,3 @@ 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/levels/level.gd b/levels/level.gd index 025014a..ede459a 100644 --- a/levels/level.gd +++ b/levels/level.gd @@ -1,51 +1,104 @@ +class_name Level extends Node3D +signal started_playing +signal gravity_change +signal ring_collected +signal completed + +const gravity_strength_normal = 7 +const gravity_strength_strong = gravity_strength_normal * 3 + +## Lowercase, spaceless name of the level +var id: String +var thumbnail: CompressedTexture2D +var player: Node3D +var music: Music +var rings: Array[Ring] = [] + +var finished_rings_count: int = 0 var velocity: float = 0.0 +var has_started_playing: bool = false -var rings_count = 72727 -var finished_rings_count = 0 -var rings: Array[Node] = [] - -var stream_players: Array[AudioStreamPlayer] = [] +func _init() -> void: + assert(len(id) > 0, self.name + " has no id!") func _ready() -> void: - var music_node = get_node("Music") - assert(is_instance_valid(music_node), self.name + " has no music!") - var music = music_node.get_children() - for music_player in music: - if music_player is AudioStreamPlayer: - stream_players.push_back(music_player) + PhysicsServer3D.area_set_param( + get_viewport().find_world_3d().space, + PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, + Vector3(0, 0, 0) + ) + + PhysicsServer3D.area_set_param( + get_viewport().find_world_3d().space, + PhysicsServer3D.AREA_PARAM_GRAVITY, + 0 + ) + + var children = get_children() + for child in children: + if is_instance_of(child, Music): + music = child + if child.name == "Player" and is_instance_of(child, Node3D): + player = child + assert(is_instance_valid(music), self.name + " has no music!") var rings_node = get_node("Rings") - assert(is_instance_valid(rings_node), self.name + " has no rings!") - rings = rings_node.get_children() - rings_count = len(rings) - for ring in rings: - ring.connect("collect_signal", do_we_end_yet) + assert(is_instance_valid(rings_node), self.name + " has no Rings node!") + var rings_node_children = rings_node.get_children() + for ring in rings_node_children: + if is_instance_of(ring, Ring): + rings.push_back(ring) + ring.connect("collect_signal", collect_ring) -func do_we_end_yet(): - finished_rings_count += 1 - if finished_rings_count >= rings_count: - var game = get_parent().get_parent() - if is_instance_valid(game) and game.has_method("stop_level"): - game.stop_level() +func collect_ring(): + finished_rings_count = len(rings.filter(func(ring: Ring): return ring.collected)) + ring_collected.emit() + + if finished_rings_count >= len(rings): + completed.emit() -func _process(delta: float) -> void: - var sphere = $Player/Sphere - velocity = abs(sphere.linear_velocity.x) + abs(sphere.linear_velocity.y) - var instruments_needed = floor(velocity / 8) - var instruments_playing = stream_players.filter(func(p: AudioStreamPlayer): return p.volume_db > -50) +func _input(_event: InputEvent) -> void: + if Input.is_action_pressed("gravity_strong") or Input.is_action_just_released("gravity_strong"): + PhysicsServer3D.area_set_param( + get_viewport().find_world_3d().space, + PhysicsServer3D.AREA_PARAM_GRAVITY, + gravity_strength_strong if Input.is_action_pressed("gravity_strong") else gravity_strength_normal + ) - for index_p in len(instruments_playing): - var playing = instruments_playing[index_p] - if index_p + 1 > instruments_needed: - playing.volume_db = max(playing.volume_db - (delta * 32), -50) - elif playing.volume_db <= 0: - playing.volume_db = min(playing.volume_db + (delta * 8), 0) + var up := Input.is_action_just_pressed("gravity_up") + var left := Input.is_action_just_pressed("gravity_left") + var right := Input.is_action_just_pressed("gravity_right") + var down := Input.is_action_just_pressed("gravity_down") - if instruments_needed > len(instruments_playing): - var instruments_not_playing = stream_players.filter(func(p: AudioStreamPlayer): return p.volume_db <= -50) - if len(instruments_not_playing): - var to_play = instruments_not_playing.pick_random() - if is_instance_valid(to_play): - to_play.volume_db = min(to_play.volume_db + (delta * 16), 0) + if up or left or right or down: + if !has_started_playing: + has_started_playing = true + started_playing.emit() + PhysicsServer3D.area_set_param( + get_viewport().find_world_3d().space, + PhysicsServer3D.AREA_PARAM_GRAVITY, + gravity_strength_strong if Input.is_action_pressed("gravity_strong") else gravity_strength_normal + ) + + var direction: Vector3 + if up: + direction = Vector3.UP + elif left: + direction = Vector3.LEFT + elif right: + direction = Vector3.RIGHT + elif down: + direction = Vector3.DOWN + + if direction && direction != PhysicsServer3D.area_get_param( + get_viewport().find_world_3d().space, + PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR + ): + PhysicsServer3D.area_set_param( + get_viewport().find_world_3d().space, + PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, + direction + ) + gravity_change.emit(direction) diff --git a/levels/level.gd.uid b/levels/level.gd.uid new file mode 100644 index 0000000..0c108ea --- /dev/null +++ b/levels/level.gd.uid @@ -0,0 +1 @@ +uid://w3fetao1pegm diff --git a/levels/music.gd b/levels/music.gd index 801fb3e..a11f3c7 100644 --- a/levels/music.gd +++ b/levels/music.gd @@ -1,15 +1,69 @@ +class_name Music extends Node +## While the instruments are manipulated individually to match the gameplay, +## they are all regrouped in a single bus dedicated to this specific music. +## So we also manipulate the bus itself for the purposes of applying +## audio balance and settings and the such more efficiently. + +var bus_index: int = -1 +var instruments: Array[AudioStreamPlayer] = [] + func _ready() -> void: - var players = get_children() - for player in players: - if player is AudioStreamPlayer: - player.volume_db = -50 - var stream: AudioStreamOggVorbis = player.stream + bus_index = AudioServer.get_bus_index(self.name) + if bus_index == -1: + AudioServer.add_bus() + AudioServer.set_bus_name(AudioServer.bus_count - 1, self.name) + bus_index = AudioServer.get_bus_index(self.name) + changeVolume(0) + + var current_effects = AudioServer.get_bus_effect_count(bus_index) + for i in current_effects: + AudioServer.remove_bus_effect(bus_index, i) + + var children = get_children() + for child in children: + if child is AudioStreamPlayer: + instruments.push_back(child) + child.bus = AudioServer.get_bus_name(bus_index) + child.volume_db = -50 + var stream: AudioStreamOggVorbis = child.stream if stream is AudioStreamOggVorbis: stream.loop = true stream.bpm = 124 - for player in players: - if player is AudioStreamPlayer: - player.play() + for instrument in instruments: + if instrument is AudioStreamPlayer: + instrument.play() + +func changeVolume(db: float) -> void: + AudioServer.set_bus_volume_db(bus_index, db + Settings.volume_music) + AudioServer.set_bus_mute(bus_index, Settings.volume_music <= -15.0) + +func adaptInstrumentsToVelocity(velocity: float) -> void: + ## temp + const delta = 0.00833333333333 + var instruments_needed = floor(velocity / 8) + var instruments_playing = instruments.filter(func(i: AudioStreamPlayer): return i.volume_db > -50) + + for index_p in len(instruments_playing): + var playing = instruments_playing[index_p] + if index_p + 1 > instruments_needed: + playing.volume_db = max(playing.volume_db - (delta * 32), -50) + elif playing.volume_db <= 0: + playing.volume_db = min(playing.volume_db + (delta * 8), 0) + + if instruments_needed > len(instruments_playing): + var instruments_not_playing = instruments.filter(func(i: AudioStreamPlayer): return i.volume_db <= -50) + if len(instruments_not_playing): + var to_play = instruments_not_playing.pick_random() + if is_instance_valid(to_play): + to_play.volume_db = min(to_play.volume_db + (delta * 16), 0) + +func fadeOut(seconds: float) -> void: + var tween: Tween = create_tween() + # https://github.com/godotengine/godot/issues/32882 + AudioServer.add_bus_effect(bus_index, AudioEffectAmplify.new()) + var effect_index: int = AudioServer.get_bus_effect_count(bus_index) - 1 + var effect: AudioEffectAmplify = AudioServer.get_bus_effect(bus_index, effect_index) + tween.tween_property(effect, "volume_linear", 0, seconds) diff --git a/levels/music.gd.uid b/levels/music.gd.uid new file mode 100644 index 0000000..decd46e --- /dev/null +++ b/levels/music.gd.uid @@ -0,0 +1 @@ +uid://dgpjhli3hpn0u diff --git a/levels/night/environment.tscn b/levels/night/environment.tscn deleted file mode 100644 index 127d6d0..0000000 --- a/levels/night/environment.tscn +++ /dev/null @@ -1,22 +0,0 @@ -[gd_scene load_steps=6 format=3 uid="uid://b6gnffoboc5j5"] - -[sub_resource type="Gradient" id="Gradient_x6q8u"] - -[sub_resource type="GradientTexture1D" id="GradientTexture1D_lu6nv"] -gradient = SubResource("Gradient_x6q8u") - -[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_4yv3y"] -panorama = SubResource("GradientTexture1D_lu6nv") - -[sub_resource type="Sky" id="Sky_ys2yp"] -sky_material = SubResource("PanoramaSkyMaterial_4yv3y") - -[sub_resource type="Environment" id="Environment_8o42c"] -background_mode = 1 -sky = SubResource("Sky_ys2yp") -ambient_light_source = 2 -ambient_light_color = Color(1, 1, 1, 1) -reflected_light_source = 2 - -[node name="Environment" type="WorldEnvironment"] -environment = SubResource("Environment_8o42c") diff --git a/levels/night/level.tscn b/levels/night/level.tscn index 9ae261d..1b0ee50 100644 --- a/levels/night/level.tscn +++ b/levels/night/level.tscn @@ -1,19 +1,51 @@ -[gd_scene load_steps=9 format=3 uid="uid://c2rlx31om4gey"] +[gd_scene load_steps=13 format=3 uid="uid://drnqmu4lka22d"] -[ext_resource type="Script" path="res://levels/level.gd" id="1_3m1pa"] -[ext_resource type="PackedScene" uid="uid://q7frlnx37gv6" path="res://levels/night/music.tscn" id="1_npc74"] +[ext_resource type="PackedScene" uid="uid://drfy3vhe6skp1" path="res://levels/night/music.tscn" id="1_npc74"] [ext_resource type="PackedScene" uid="uid://cnnvwotv33u1b" path="res://elements/player.tscn" id="2_bc1ig"] -[ext_resource type="PackedScene" uid="uid://b6gnffoboc5j5" path="res://levels/night/environment.tscn" id="2_wintp"] [ext_resource type="PackedScene" uid="uid://cpm3laywhlbq5" path="res://elements/ring.tscn" id="4_brcr0"] [ext_resource type="PackedScene" uid="uid://c77bli40240nk" path="res://elements/sign.tscn" id="6_36yav"] [ext_resource type="PackedScene" uid="uid://b4jtpua36m6b1" path="res://elements/star.tscn" id="7_ltcl0"] [ext_resource type="PackedScene" uid="uid://da6lkdiskdh8v" path="res://elements/tree.tscn" id="8_kgstj"] -[node name="Night" type="Node3D"] -script = ExtResource("1_3m1pa") -metadata/name = "Night" +[sub_resource type="GDScript" id="GDScript_akhnt"] +script/source = "extends Level -[node name="Environment" parent="." instance=ExtResource("2_wintp")] +func _init() -> void: + self.id = \"night\" + +func _process(delta: float) -> void: + $Tree.rotate_x(delta / 3) + $Tree.rotate_y(delta) + +func _on_player_velocity_change(new_velocity: float) -> void: + self.velocity = new_velocity + self.music.adaptInstrumentsToVelocity(new_velocity * 2) +" + +[sub_resource type="Gradient" id="Gradient_x6q8u"] + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_lu6nv"] +gradient = SubResource("Gradient_x6q8u") + +[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_4yv3y"] +panorama = SubResource("GradientTexture1D_lu6nv") + +[sub_resource type="Sky" id="Sky_ys2yp"] +sky_material = SubResource("PanoramaSkyMaterial_4yv3y") + +[sub_resource type="Environment" id="Environment_8o42c"] +background_mode = 1 +sky = SubResource("Sky_ys2yp") +ambient_light_source = 2 +ambient_light_color = Color(1, 1, 1, 1) +reflected_light_source = 2 + +[node name="Night" type="Node3D"] +script = SubResource("GDScript_akhnt") +metadata/_custom_type_script = "uid://w3fetao1pegm" + +[node name="Environment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_8o42c") [node name="Music" parent="." instance=ExtResource("1_npc74")] @@ -171,40 +203,42 @@ transform = Transform3D(-1.31134e-07, -3, 0, 3, -1.31134e-07, 0, 0, 0, 3, -104.2 [node name="Ring2" parent="Rings" instance=ExtResource("4_brcr0")] transform = Transform3D(0.5, 0, 0, 0, 0.5, 0, 0, 0, 0.5, -12.3896, -2, 0) +[node name="Tree" parent="." instance=ExtResource("8_kgstj")] +transform = Transform3D(-3.79271, -7.04382, 0, 7.04382, -3.79271, 0, 0, 0, 8, 28.958, -413.185, -93.8242) + [node name="Signs" type="Node3D" parent="."] [node name="Sign" parent="Signs" instance=ExtResource("6_36yav")] transform = Transform3D(0.843785, 0, 0.536681, 0, 1, 0, -0.536681, 0, 0.843785, -159.605, -62.9326, 0) [node name="Text" parent="Signs/Sign" index="0"] +transform = Transform3D(37, 0, 0, 0, 37, 0, 0, 0, 37, 0, 0, 0) text = "^^^ Go UP!!" -font_size = 2048 [node name="Sign4" parent="Signs" instance=ExtResource("6_36yav")] transform = Transform3D(0.965926, 0, 0.258819, 0, 1, 0, -0.258819, 0, 0.965926, 231.92, -32.6467, 0) [node name="Text" parent="Signs/Sign4" index="0"] +transform = Transform3D(22, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0) text = "^^ Don't forget that one!" -font_size = 1500 [node name="Sign2" parent="Signs" instance=ExtResource("6_36yav")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -159.605, -30.0117, -45.6318) [node name="Text" parent="Signs/Sign2" index="0"] +transform = Transform3D(30, 0, 0, 0, 30, 0, 0, 0, 30, 0, 0, 0) text = "After taking this, go RIGHT!" -font_size = 1600 [node name="Sign3" parent="Signs" instance=ExtResource("6_36yav")] transform = Transform3D(-1, -8.74228e-08, 0, 8.74228e-08, -1, 0, 0, 0, 1, -64.0671, 131.627, -45.6318) [node name="Text" parent="Signs/Sign3" index="0"] -transform = Transform3D(-1, 8.74228e-08, 0, -8.74228e-08, -1, 0, 0, 0, 1, 0, 0, 0) +transform = Transform3D(-30, 4.52987e-06, 0, -4.52987e-06, -30, 0, 0, 0, 30, 0, 0, 0) text = "Go RIGHT!" -font_size = 2048 [node name="Stars" type="Node3D" parent="."] transform = Transform3D(4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 37.5124, -255.888) @@ -304,8 +338,7 @@ transform = Transform3D(-0.99693, 0.0731445, -0.0279554, -0.0555776, -0.912445, [node name="Star32" parent="Stars" instance=ExtResource("7_ltcl0")] transform = Transform3D(-0.99693, 0.0731445, -0.0279554, -0.0555776, -0.912445, -0.405407, -0.055161, -0.402609, 0.913709, 0.952739, 0.24193, 7.10684) -[node name="Tree" parent="." instance=ExtResource("8_kgstj")] -transform = Transform3D(-3.79443, -7.04289, 0, 7.04289, -3.79443, 0, 0, 0, 8, 28.958, -413.185, -93.8242) +[connection signal="velocity_change" from="Player" to="." method="_on_player_velocity_change"] [editable path="Signs/Sign"] [editable path="Signs/Sign4"] diff --git a/levels/night/music.tscn b/levels/night/music.tscn index d065280..ee2b7be 100644 --- a/levels/night/music.tscn +++ b/levels/night/music.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=8 format=3 uid="uid://q7frlnx37gv6"] +[gd_scene load_steps=8 format=3 uid="uid://drfy3vhe6skp1"] -[ext_resource type="Script" path="res://levels/music.gd" id="1_ok6lg"] +[ext_resource type="Script" uid="uid://dgpjhli3hpn0u" path="res://levels/music.gd" id="1_ok6lg"] [ext_resource type="AudioStream" uid="uid://dcgmuddvkcw6" path="res://levels/night/music/hihat-closed.ogg" id="2_oeg0c"] [ext_resource type="AudioStream" uid="uid://deqxl1qmwu51s" path="res://levels/night/music/hihat-open.ogg" id="3_olgpr"] [ext_resource type="AudioStream" uid="uid://028dtbgdh0os" path="res://levels/night/music/kick.ogg" id="4_utlv1"] @@ -10,6 +10,7 @@ [node name="Music" type="Node"] script = ExtResource("1_ok6lg") +metadata/_custom_type_script = "uid://dgpjhli3hpn0u" [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] stream = ExtResource("2_oeg0c") diff --git a/menus/main/initial_menu.tscn b/menus/main/initial_menu.tscn new file mode 100644 index 0000000..0df392b --- /dev/null +++ b/menus/main/initial_menu.tscn @@ -0,0 +1,51 @@ +[gd_scene load_steps=2 format=3 uid="uid://dys7qyy4b3gjt"] + +[sub_resource type="GDScript" id="GDScript_vfuxb"] +script/source = "extends Control + +signal request_start +signal request_settings + +func _on_btn_start_pressed() -> void: + request_start.emit() + +func _on_btn_settings_pressed() -> void: + request_settings.emit() + +func _on_btn_exit_pressed() -> void: + get_tree().quit() +" + +[node name="InitialMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = SubResource("GDScript_vfuxb") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +alignment = 1 + +[node name="BtnStart" type="Button" parent="VBoxContainer"] +layout_mode = 2 +text = "Start the game!" + +[node name="BtnSettings" type="Button" parent="VBoxContainer"] +layout_mode = 2 +text = "Check out the settings" + +[node name="BtnExit" type="Button" parent="VBoxContainer"] +layout_mode = 2 +text = "Exit the game" + +[connection signal="pressed" from="VBoxContainer/BtnStart" to="." method="_on_btn_start_pressed"] +[connection signal="pressed" from="VBoxContainer/BtnSettings" to="." method="_on_btn_settings_pressed"] +[connection signal="pressed" from="VBoxContainer/BtnExit" to="." method="_on_btn_exit_pressed"] diff --git a/menus/main/level_selection_menu.tscn b/menus/main/level_selection_menu.tscn new file mode 100644 index 0000000..5fc9a1f --- /dev/null +++ b/menus/main/level_selection_menu.tscn @@ -0,0 +1,152 @@ +[gd_scene load_steps=2 format=3 uid="uid://d3b12iqla7uh6"] + +[sub_resource type="GDScript" id="GDScript_rmgh7"] +script/source = "extends Control + +signal request_play_level + +@onready var carousel := $VBoxContainer/Selection/Carousel +@onready var label_time := $VBoxContainer/Presentation/MarginContainer/VBoxContainer/BestTime +const levels = [ + \"res://levels/base/level.tscn\", + \"res://levels/forest/level.tscn\", + \"res://levels/night/level.tscn\", +] +var loaded_level: Level +var loaded_level_scene: PackedScene +var loaded_level_path: String + +func _enter_tree() -> void: + if len(loaded_level_path): + prepare_level(loaded_level_path) + +func _ready() -> void: + var placeholders := carousel.get_children() + for placeholder in placeholders: + placeholder.queue_free() + + for i in len(levels): + var btn := Button.new() + btn.text = \"Level \" + str(i + 1) + btn.connect(\"pressed\", func(): prepare_level(levels[i])) + carousel.add_child(btn) + +func prepare_level(level_scene_path: String): + if is_instance_valid(loaded_level): + loaded_level.queue_free() + + ResourceLoader.load_threaded_request(level_scene_path) + loaded_level_scene = ResourceLoader.load_threaded_get(level_scene_path) + loaded_level = loaded_level_scene.instantiate() + loaded_level_path = level_scene_path + $VBoxContainer/Presentation/Thumbnail.texture = loaded_level.thumbnail + $VBoxContainer/Presentation/MarginContainer/VBoxContainer/LevelName.text = \"The \" + loaded_level.id.capitalize() + $VBoxContainer/Presentation.show() + $VBoxContainer/MarginContainer/PlayButton.show() + display_file_data(SaveFiles.read(SaveFiles.selected_file)) + +func display_file_data(data: Variant) -> void: + label_time.text = \"Best time: \" + var property_name := loaded_level.id + \"_best_time\" + if data.has(property_name) and data[property_name] is float: + var seconds: float = data[property_name] + var minutes: int = floor(seconds / 60) + label_time.text += (\"%0*d\" % [2, minutes]) + \":\" + (\"%0*.3f\" % [6, seconds - (minutes * 60)]) + else: + label_time.text += \"00:00.000\" + +func _on_play_button_pressed() -> void: + if is_instance_valid(loaded_level): + request_play_level.emit(loaded_level, loaded_level_scene) + +func seconds_to_readable(seconds: float) -> String: + var minutes: int = floor(seconds / 60) + return (\"%0*d\" % [2, minutes]) + \":\" + (\"%0*.3f\" % [6, seconds - (minutes * 60)]) + +## This prevents a memory leak that is possible when this menu is destroyed +## and the loaded_level becomes unavailable to the rest of the game +## For example in the main menu, go to this menu, select a level, +## press \"return\" and go to this menu again, boom, memory leak prevented by this +func _notification(what: int) -> void: + match what: + NOTIFICATION_PREDELETE: + if is_instance_valid(loaded_level) && !loaded_level.is_inside_tree(): + loaded_level.queue_free() +" + +[node name="LevelSelectionMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = SubResource("GDScript_rmgh7") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Selection" type="ScrollContainer" parent="VBoxContainer"] +custom_minimum_size = Vector2(0, 50) +layout_mode = 2 + +[node name="Carousel" type="HBoxContainer" parent="VBoxContainer/Selection"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/separation = 10 +alignment = 1 + +[node name="Placeholder1" type="Button" parent="VBoxContainer/Selection/Carousel"] +layout_mode = 2 +theme_override_constants/icon_max_width = 150 +text = "Placeholder" + +[node name="Placeholder2" type="Button" parent="VBoxContainer/Selection/Carousel"] +layout_mode = 2 +text = "Placeholder" + +[node name="Placeholder3" type="Button" parent="VBoxContainer/Selection/Carousel"] +layout_mode = 2 +text = "Placeholder" + +[node name="Presentation" type="HBoxContainer" parent="VBoxContainer"] +visible = false +layout_mode = 2 + +[node name="Thumbnail" type="TextureRect" parent="VBoxContainer/Presentation"] +custom_minimum_size = Vector2(150, 150) +layout_mode = 2 +expand_mode = 1 +stretch_mode = 4 + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/Presentation"] +layout_mode = 2 +theme_override_constants/margin_left = 5 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/Presentation/MarginContainer"] +layout_mode = 2 +alignment = 1 + +[node name="LevelName" type="Label" parent="VBoxContainer/Presentation/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Placeholder" + +[node name="BestTime" type="Label" parent="VBoxContainer/Presentation/MarginContainer/VBoxContainer"] +layout_mode = 2 +text = "Best time: 00:00.000" + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_top = 15 + +[node name="PlayButton" type="Button" parent="VBoxContainer/MarginContainer"] +visible = false +layout_mode = 2 +text = "Play!" + +[connection signal="pressed" from="VBoxContainer/MarginContainer/PlayButton" to="." method="_on_play_button_pressed"] diff --git a/menus/main/main_menu.tscn b/menus/main/main_menu.tscn new file mode 100644 index 0000000..235b9b6 --- /dev/null +++ b/menus/main/main_menu.tscn @@ -0,0 +1,296 @@ +[gd_scene load_steps=16 format=3 uid="uid://ikeidrgprk8k"] + +[ext_resource type="PackedScene" uid="uid://wlhsarkeqe8r" path="res://menus/main/panel.tscn" id="1_5vmsf"] +[ext_resource type="PackedScene" uid="uid://cnnvwotv33u1b" path="res://elements/player.tscn" id="2_2rexg"] + +[sub_resource type="GDScript" id="GDScript_bt14i"] +script/source = "extends Node3D + +signal request_play_level + +func _enter_tree() -> void: + $Camera3D/AnimationPlayer.play_backwards(\"camera_pan\") + PhysicsServer3D.area_set_param( + get_viewport().find_world_3d().space, + PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, + Vector3.DOWN + ) + +# Display on Panel 1 +const res_initial_menu = preload(\"res://menus/main/initial_menu.tscn\") +func _ready() -> void: + $Menus/Panel2.connect(\"request_return\", func(): rotate_cube_to(0)) + $Menus/Panel3.connect(\"request_return\", func(): rotate_cube_to(90)) + $Menus/Panel4.connect(\"request_return\", func(): rotate_cube_to(180)) + + var initial_menu := res_initial_menu.instantiate() + initial_menu.connect(\"request_start\", start) + initial_menu.connect(\"request_settings\", settings) + $Menus/Panel1.change_menu(initial_menu, false) + +# Display on Panel 2 +const res_settings_menu = preload(\"res://menus/main/settings_menu.tscn\") +func settings() -> void: + var settings_menu := res_settings_menu.instantiate() + $Menus/Panel2.change_menu(settings_menu) + rotate_cube_to(90) + +const res_save_file_manager = preload(\"res://menus/main/save_file_manager.tscn\") +func start() -> void: + var save_file_manager := res_save_file_manager.instantiate() + save_file_manager.connect(\"request_start\", level_selection) + $Menus/Panel2.change_menu(save_file_manager) + rotate_cube_to(90) + +# Display on Panel 3 +const res_level_selection_menu = preload(\"res://menus/main/level_selection_menu.tscn\") +func level_selection() -> void: + var level_selection_menu := res_level_selection_menu.instantiate() + level_selection_menu.connect(\"request_play_level\", func(level: Level, scene: PackedScene): + $Camera3D/AnimationPlayer.play(\"camera_pan\") + await get_tree().create_timer(1.5).timeout + request_play_level.emit(level, scene) + ) + $Menus/Panel3.change_menu(level_selection_menu) + rotate_cube_to(180) + +# cube +func rotate_cube_to(degrees: int) -> void: + if $Menus/AnimationPlayer.is_playing(): + return + + var cube_animation: Animation = $Menus/AnimationPlayer.get_animation(\"rotate\") + cube_animation.track_set_key_value(0, 0, $Menus.rotation_degrees) + cube_animation.track_set_key_value(0, 1, Vector3(0, -degrees, 0)) + $Menus/AnimationPlayer.play(\"rotate\") + + if $AnimationPlayer.is_playing(): + await get_tree().create_timer($AnimationPlayer.current_animation_length).timeout + var sky_animation: Animation = $AnimationPlayer.get_animation(\"sky_brightness\") + sky_animation.track_set_key_value(0, 0, $WorldEnvironment.environment.sky.sky_material.energy_multiplier) + sky_animation.track_set_key_value(0, 1, max(90, degrees * 2) / 90) + $AnimationPlayer.play(\"sky_brightness\") +" + +[sub_resource type="Animation" id="Animation_0jxef"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} + +[sub_resource type="Animation" id="Animation_bt14i"] +resource_name = "rotate" +length = 0.3 +step = 0.3 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0, 0, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_3bwb0"] +_data = { +&"RESET": SubResource("Animation_0jxef"), +&"rotate": SubResource("Animation_bt14i") +} + +[sub_resource type="Animation" id="Animation_2rexg"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("WorldEnvironment:environment:sky:sky_material:energy_multiplier") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [1.0] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Camera3D:fov") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [40.0] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("Camera3D:position") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 2.5)] +} + +[sub_resource type="Animation" id="Animation_jinmx"] +resource_name = "camera_pan" +length = 1.5 +step = 0.1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Camera3D:fov") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 1.5), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [40.0, 75.0] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Camera3D:position") +tracks/1/interp = 2 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 1.5), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 0, 2.5), Vector3(0, 0, 15)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_jinmx"] +_data = { +&"RESET": SubResource("Animation_2rexg"), +&"camera_pan": SubResource("Animation_jinmx") +} + +[sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_bt14i"] +ground_color = Color(1, 0.484315, 0.700558, 1) + +[sub_resource type="Sky" id="Sky_0jxef"] +sky_material = SubResource("PhysicalSkyMaterial_bt14i") + +[sub_resource type="Environment" id="Environment_qfa5o"] +background_mode = 2 +background_color = Color(0.804743, 0.804743, 0.804743, 1) +sky = SubResource("Sky_0jxef") +ambient_light_source = 3 +ambient_light_color = Color(0.986752, 0.986752, 0.986752, 1) +reflected_light_source = 2 + +[sub_resource type="Animation" id="Animation_j2kye"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("../../WorldEnvironment:environment:sky:sky_material:energy_multiplier") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [1.0] +} + +[sub_resource type="Animation" id="Animation_gma2u"] +resource_name = "sky_brightness" +length = 0.3 +step = 0.1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("../../WorldEnvironment:environment:sky:sky_material:energy_multiplier") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [1.0, 1.0] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_wruj6"] +_data = { +&"RESET": SubResource("Animation_j2kye"), +&"sky_brightness": SubResource("Animation_gma2u") +} + +[node name="MainMenu" type="Node3D"] +process_mode = 3 +script = SubResource("GDScript_bt14i") + +[node name="Menus" type="CSGBox3D" parent="."] +use_collision = true + +[node name="Panel1" parent="Menus" instance=ExtResource("1_5vmsf")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.501) + +[node name="Panel2" parent="Menus" instance=ExtResource("1_5vmsf")] +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0.501, 0, 0) + +[node name="Panel3" parent="Menus" instance=ExtResource("1_5vmsf")] +transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, -0.501) + +[node name="Panel4" parent="Menus" instance=ExtResource("1_5vmsf")] +transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, -0.501, 0, 0) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Menus"] +libraries = { +&"": SubResource("AnimationLibrary_3bwb0") +} + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2.5) +current = true +fov = 40.0 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Camera3D"] +root_node = NodePath("../..") +libraries = { +&"": SubResource("AnimationLibrary_jinmx") +} + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_qfa5o") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.819152, -0.412596, 0.39844, 0, 0.694658, 0.71934, -0.573576, -0.589249, 0.569031, 0, 0, 0) + +[node name="Player" parent="." instance=ExtResource("2_2rexg")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0) + +[node name="Camera" parent="Player" index="0"] +visible = false +current = false + +[node name="GPUParticles3D" parent="Player/Sphere" index="2"] +visible = false + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +root_node = NodePath("../Camera3D/AnimationPlayer") +libraries = { +&"": SubResource("AnimationLibrary_wruj6") +} + +[editable path="Player"] diff --git a/menus/main/panel.tscn b/menus/main/panel.tscn new file mode 100644 index 0000000..acadfdf --- /dev/null +++ b/menus/main/panel.tscn @@ -0,0 +1,115 @@ +[gd_scene load_steps=7 format=3 uid="uid://wlhsarkeqe8r"] + +[ext_resource type="PackedScene" uid="uid://tasbgr10p84c" path="res://menus/menu.tscn" id="1_3roig"] + +[sub_resource type="GDScript" id="GDScript_gfsnp"] +script/source = "# this whole code is from \"GUI in 3D\" +# which is something I downloaded a long time ago so no link + +extends Node3D + +var is_mouse_inside := false +var last_event_pos2D := Vector2() +var last_event_time := -1.0 + +@onready var node_viewport: SubViewport = $SubViewport +@onready var node_quad: MeshInstance3D = $MeshInstance3D +@onready var node_area: Area3D = $MeshInstance3D/Area3D + +func _ready() -> void: + node_area.mouse_entered.connect(_mouse_entered_area) + node_area.mouse_exited.connect(_mouse_exited_area) + node_area.input_event.connect(_mouse_input_event) + +func _mouse_entered_area() -> void: + is_mouse_inside = true + +func _mouse_exited_area() -> void: + is_mouse_inside = false + +func _unhandled_input(event: InputEvent) -> void: + for mouse_event in [InputEventMouseButton, InputEventMouseMotion, InputEventScreenDrag, InputEventScreenTouch]: + if is_instance_of(event, mouse_event): + return + node_viewport.push_input(event) + +func _mouse_input_event(_camera: Camera3D, event: InputEvent, event_position: Vector3, _normal: Vector3, _shape_idx: int) -> void: + var quad_mesh_size: Vector2 = node_quad.mesh.size + var now := Time.get_ticks_msec() / 1000.0 + + var event_pos3D := event_position + event_pos3D = node_quad.global_transform.affine_inverse() * event_pos3D + + var event_pos2D := Vector2() + if is_mouse_inside: + event_pos2D = Vector2(event_pos3D.x, -event_pos3D.y) + + event_pos2D.x = event_pos2D.x / quad_mesh_size.x + event_pos2D.y = event_pos2D.y / quad_mesh_size.y + + event_pos2D.x += 0.5 + event_pos2D.y += 0.5 + + event_pos2D.x *= node_viewport.size.x + event_pos2D.y *= node_viewport.size.y + + elif last_event_pos2D != null: + event_pos2D = last_event_pos2D + + event.position = event_pos2D + if event is InputEventMouse: + event.global_position = event_pos2D + + if event is InputEventMouseMotion or event is InputEventScreenDrag: + if last_event_pos2D == null: + event.relative = Vector2(0, 0) + else: + event.relative = event_pos2D - last_event_pos2D + event.velocity = event.relative / (now - last_event_time) + + last_event_pos2D = event_pos2D + last_event_time = now + node_viewport.push_input(event) + +# original code + +signal request_return + +func change_menu(new_menu: Control, return_button: bool = true): + $SubViewport/Menu.add(new_menu, return_button) + $SubViewport/Menu.connect(\"disabled\", func(): request_return.emit()) +" + +[sub_resource type="QuadMesh" id="QuadMesh_gfsnp"] + +[sub_resource type="ViewportTexture" id="ViewportTexture_gfsnp"] +viewport_path = NodePath("SubViewport") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_a5lkq"] +resource_local_to_scene = true +transparency = 1 +albedo_texture = SubResource("ViewportTexture_gfsnp") + +[sub_resource type="BoxShape3D" id="BoxShape3D_gfsnp"] +size = Vector3(1, 1, 0.01) + +[node name="Panel" type="Node3D"] +process_mode = 3 +script = SubResource("GDScript_gfsnp") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("QuadMesh_gfsnp") +surface_material_override/0 = SubResource("StandardMaterial3D_a5lkq") + +[node name="Area3D" type="Area3D" parent="MeshInstance3D"] +collision_layer = 2 +input_capture_on_drag = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="MeshInstance3D/Area3D"] +shape = SubResource("BoxShape3D_gfsnp") + +[node name="SubViewport" type="SubViewport" parent="."] +gui_embed_subwindows = true +render_target_update_mode = 4 + +[node name="Menu" parent="SubViewport" instance=ExtResource("1_3roig")] diff --git a/menus/main/save_file_manager.tscn b/menus/main/save_file_manager.tscn new file mode 100644 index 0000000..8054c7e --- /dev/null +++ b/menus/main/save_file_manager.tscn @@ -0,0 +1,125 @@ +[gd_scene load_steps=2 format=3 uid="uid://w5te3qujco7d"] + +[sub_resource type="GDScript" id="GDScript_a5kgg"] +script/source = "extends Control + +signal request_start + +@onready var label_name = $VBoxContainer/MarginContainer/VBoxContainer/Description/Name + +func _ready() -> void: + $VBoxContainer/MarginContainer.hide() + +## Get the newest \"played_for\" when the main menu appears again +func _enter_tree() -> void: + if len(SaveFiles.selected_file): + display_file_data(SaveFiles.selected_file) + +func _on_save_1_pressed() -> void: + label_name.text = $VBoxContainer/Save1.text + display_file_data(SaveFiles.names[0]) + +func _on_save_2_pressed() -> void: + label_name.text = $VBoxContainer/Save2.text + display_file_data(SaveFiles.names[1]) + +func _on_save_3_pressed() -> void: + label_name.text = $VBoxContainer/Save3.text + display_file_data(SaveFiles.names[2]) + +func display_file_data(file_name: String) -> void: + $VBoxContainer/MarginContainer.show() + var label_time := $VBoxContainer/MarginContainer/VBoxContainer/Description/Time + var data = SaveFiles.read(file_name) + $VBoxContainer/MarginContainer.show() + label_time.text = \" | \" + if data.has(\"played_for\") and data.played_for is float: + var seconds: float = data.played_for + var minutes: int = floor(seconds / 60) + label_time.text += (\"%0*d\" % [2, minutes]) + \":\" + (\"%0*.3f\" % [6, seconds - (minutes * 60)]) + else: + label_time.text += \"00:00.000\" + +func _on_start_pressed() -> void: + request_start.emit() + +func _on_delete_pressed() -> void: + SaveFiles.empty(SaveFiles.selected_file) + display_file_data(SaveFiles.selected_file) +" + +[node name="SaveFileManager" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = SubResource("GDScript_a5kgg") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 14 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_top = -50.5 +offset_bottom = 50.5 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +alignment = 1 + +[node name="Save1" type="Button" parent="VBoxContainer"] +layout_mode = 2 +text = "Save file #1" + +[node name="Save2" type="Button" parent="VBoxContainer"] +layout_mode = 2 +text = "Save file #2" + +[node name="Save3" type="Button" parent="VBoxContainer"] +layout_mode = 2 +text = "Save file #3" + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 30 +theme_override_constants/margin_top = 30 +theme_override_constants/margin_right = 30 +theme_override_constants/margin_bottom = 30 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/MarginContainer"] +layout_mode = 2 + +[node name="Description" type="HBoxContainer" parent="VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +alignment = 1 + +[node name="Name" type="Label" parent="VBoxContainer/MarginContainer/VBoxContainer/Description"] +layout_mode = 2 +text = "Save File" +horizontal_alignment = 1 + +[node name="Time" type="Label" parent="VBoxContainer/MarginContainer/VBoxContainer/Description"] +layout_mode = 2 + +[node name="Buttons" type="HBoxContainer" parent="VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/separation = 10 +alignment = 1 + +[node name="Start" type="Button" parent="VBoxContainer/MarginContainer/VBoxContainer/Buttons"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Start" + +[node name="Delete" type="Button" parent="VBoxContainer/MarginContainer/VBoxContainer/Buttons"] +layout_mode = 2 +text = "Delete" + +[connection signal="pressed" from="VBoxContainer/Save1" to="." method="_on_save_1_pressed"] +[connection signal="pressed" from="VBoxContainer/Save2" to="." method="_on_save_2_pressed"] +[connection signal="pressed" from="VBoxContainer/Save3" to="." method="_on_save_3_pressed"] +[connection signal="pressed" from="VBoxContainer/MarginContainer/VBoxContainer/Buttons/Start" to="." method="_on_start_pressed"] +[connection signal="pressed" from="VBoxContainer/MarginContainer/VBoxContainer/Buttons/Delete" to="." method="_on_delete_pressed"] diff --git a/menus/main/settings_menu.tscn b/menus/main/settings_menu.tscn new file mode 100644 index 0000000..285436f --- /dev/null +++ b/menus/main/settings_menu.tscn @@ -0,0 +1,96 @@ +[gd_scene load_steps=2 format=3 uid="uid://opwiiusu80nu"] + +[sub_resource type="GDScript" id="GDScript_wbybg"] +script/source = "extends Control + +func _ready() -> void: + $VBoxContainer/Fullscreen/CheckButton.button_pressed = Settings.fullscreen + $VBoxContainer/SoundGravity/CheckButton.button_pressed = Settings.sound_on_gravity_change + $VBoxContainer/VolumeMusic/HSlider.value = Settings.volume_music + $VBoxContainer/VolumeSounds/HSlider.value = Settings.volume_sounds + +func _on_fullscreen_check_button_toggled(toggled_on: bool) -> void: + Settings.fullscreen = toggled_on + +func _on_soundgravity_check_button_toggled(toggled_on: bool) -> void: + Settings.sound_on_gravity_change = toggled_on + +func _on_volumemusic_h_slider_value_changed(value: float) -> void: + Settings.volume_music = int(value) + +func _on_volumesounds_h_slider_value_changed(value: float) -> void: + Settings.volume_sounds = int(value) +" + +[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 = SubResource("GDScript_wbybg") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +alignment = 1 + +[node name="Fullscreen" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 +alignment = 1 + +[node name="Label" type="Label" parent="VBoxContainer/Fullscreen"] +layout_mode = 2 +text = "Fullscreen" + +[node name="CheckButton" type="CheckButton" parent="VBoxContainer/Fullscreen"] +layout_mode = 2 + +[node name="SoundGravity" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 +alignment = 1 + +[node name="Label" type="Label" parent="VBoxContainer/SoundGravity"] +layout_mode = 2 +text = "Play sound on gravity change" + +[node name="CheckButton" type="CheckButton" parent="VBoxContainer/SoundGravity"] +layout_mode = 2 + +[node name="VolumeMusic" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 +alignment = 1 + +[node name="Label" type="Label" parent="VBoxContainer/VolumeMusic"] +layout_mode = 2 +text = "Music volume" + +[node name="HSlider" type="HSlider" parent="VBoxContainer/VolumeMusic"] +custom_minimum_size = Vector2(200, 28) +layout_mode = 2 +min_value = -15.0 +max_value = 15.0 + +[node name="VolumeSounds" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 +alignment = 1 + +[node name="Label" type="Label" parent="VBoxContainer/VolumeSounds"] +layout_mode = 2 +text = "Sound volume" + +[node name="HSlider" type="HSlider" parent="VBoxContainer/VolumeSounds"] +custom_minimum_size = Vector2(200, 28) +layout_mode = 2 +min_value = -15.0 +max_value = 15.0 + +[connection signal="toggled" from="VBoxContainer/Fullscreen/CheckButton" to="." method="_on_fullscreen_check_button_toggled"] +[connection signal="toggled" from="VBoxContainer/SoundGravity/CheckButton" to="." method="_on_soundgravity_check_button_toggled"] +[connection signal="value_changed" from="VBoxContainer/VolumeMusic/HSlider" to="." method="_on_volumemusic_h_slider_value_changed"] +[connection signal="value_changed" from="VBoxContainer/VolumeSounds/HSlider" to="." method="_on_volumesounds_h_slider_value_changed"] diff --git a/menus/menu.tscn b/menus/menu.tscn new file mode 100644 index 0000000..7551ab7 --- /dev/null +++ b/menus/menu.tscn @@ -0,0 +1,139 @@ +[gd_scene load_steps=8 format=3 uid="uid://tasbgr10p84c"] + +[ext_resource type="AudioStream" uid="uid://bnbf1nfaxuagi" path="res://sounds/select.ogg" id="1_y8e4h"] +[ext_resource type="AudioStream" uid="uid://bq3tw55s0ud55" path="res://sounds/confirm.ogg" id="2_hl3ms"] + +[sub_resource type="GDScript" id="GDScript_18a3y"] +script/source = "extends MarginContainer + +signal disabled + +func add(node: Control, return_button: bool): + var add_to := $VSplitContainer/MarginContainer/ColorRect + var children := add_to.get_children(true) + for child in children: + child.queue_free() + + var regex := RegEx.new() + regex.compile(\"([A-Z])\") + var menu_name := regex.sub(node.name, \" $1\", true, 1) + $VSplitContainer/Label.text = menu_name + add_to.add_child(node) + $VSplitContainer/AnimationPlayer.play(\"split_offset\") + + if return_button: + var button = Button.new() + button.text = \"Return\" + button.anchor_top = 1.0 + button.anchor_bottom = 1.0 + button.grow_vertical = Control.GROW_DIRECTION_BEGIN + button.connect(\"pressed\", disable) + node.add_child(button) + + link_to_sounds(node) + +func link_to_sounds(node: Control): + var children := node.find_children(\"*\", \"\", true, false) + + var buttons := children.filter(func(child): return is_instance_of(child, Button)) + for button in buttons as Array[Button]: + button.mouse_entered.connect(func(): $Select.play()) + button.pressed.connect(func(): $Confirm.play()) + + var sliders := children.filter(func(child): return is_instance_of(child, HSlider)) + for slider in sliders as Array[HSlider]: + slider.mouse_entered.connect(func(): $Select.play()) + slider.drag_ended.connect(func(_value): $Confirm.play()) + +func disable(): + $VSplitContainer/AnimationPlayer.play_backwards(\"split_offset\") + disabled.emit() +" + +[sub_resource type="Animation" id="Animation_y8e4h"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:split_offset") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [500] +} + +[sub_resource type="Animation" id="Animation_85u52"] +resource_name = "split_offset" +length = 0.5 +step = 0.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:split_offset") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.5), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [500, 0] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_hl3ms"] +_data = { +&"RESET": SubResource("Animation_y8e4h"), +&"split_offset": SubResource("Animation_85u52") +} + +[sub_resource type="LabelSettings" id="LabelSettings_2d4ws"] +font_size = 48 + +[node name="Menu" type="MarginContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 20 +theme_override_constants/margin_top = 20 +theme_override_constants/margin_right = 20 +theme_override_constants/margin_bottom = 20 +script = SubResource("GDScript_18a3y") + +[node name="VSplitContainer" type="VSplitContainer" parent="."] +layout_mode = 2 +split_offset = 500 +dragger_visibility = 1 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="VSplitContainer"] +libraries = { +&"": SubResource("AnimationLibrary_hl3ms") +} + +[node name="Label" type="Label" parent="VSplitContainer"] +custom_minimum_size = Vector2(1, 1) +layout_mode = 2 +text = "MENU NAME" +label_settings = SubResource("LabelSettings_2d4ws") +horizontal_alignment = 1 +autowrap_mode = 3 +uppercase = true + +[node name="MarginContainer" type="MarginContainer" parent="VSplitContainer"] +layout_mode = 2 +theme_override_constants/margin_top = 20 + +[node name="ColorRect" type="ColorRect" parent="VSplitContainer/MarginContainer"] +layout_mode = 2 +color = Color(0, 0, 0, 1) + +[node name="Select" type="AudioStreamPlayer" parent="."] +stream = ExtResource("1_y8e4h") +bus = &"Sounds" + +[node name="Confirm" type="AudioStreamPlayer" parent="."] +stream = ExtResource("2_hl3ms") +bus = &"Sounds" diff --git a/menus/pause_menu.tscn b/menus/pause_menu.tscn new file mode 100644 index 0000000..27f7e68 --- /dev/null +++ b/menus/pause_menu.tscn @@ -0,0 +1,78 @@ +[gd_scene load_steps=2 format=3 uid="uid://dkxtwpcy4moyo"] + +[sub_resource type="GDScript" id="GDScript_d8v8v"] +script/source = "extends Control + +signal request_pause +signal request_fullscreen +signal request_restart + +func _ready() -> void: + var os_name = OS.get_name() + if os_name == \"Web\": ## you can't quit the game on web (you're stuck here forever :)) + $VBoxContainer/Btn_Quit.hide() + +func _input(_event: InputEvent) -> void: + if Input.is_action_just_pressed(\"pause_game\"): + request_pause.emit(!self.visible) + +func _on_btn_resume_pressed() -> void: + request_pause.emit(false) + +func _on_btn_fullscreen_pressed() -> void: + request_fullscreen.emit() + +func _on_btn_restart_pressed() -> void: + request_restart.emit() + +func _on_btn_quit_pressed() -> void: + get_tree().quit() +" + +[node name="PauseMenu" type="Control"] +z_index = 2 +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 1 +script = SubResource("GDScript_d8v8v") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 14 +anchor_top = 0.5 +anchor_right = 1.0 +anchor_bottom = 0.5 +offset_top = -50.5 +offset_bottom = 50.5 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/separation = 10 + +[node name="Btn_Resume" type="Button" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 6 +text = "RESUME game" + +[node name="Btn_Fullscreen" type="Button" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 6 +text = "Toggle FULLSCREEN" + +[node name="Btn_Restart" type="Button" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 6 +text = "RESTART the level" + +[node name="Btn_Quit" type="Button" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 6 +text = "QUIT game" + +[connection signal="pressed" from="VBoxContainer/Btn_Resume" to="." method="_on_btn_resume_pressed"] +[connection signal="pressed" from="VBoxContainer/Btn_Fullscreen" to="." method="_on_btn_fullscreen_pressed"] +[connection signal="pressed" from="VBoxContainer/Btn_Restart" to="." method="_on_btn_restart_pressed"] +[connection signal="pressed" from="VBoxContainer/Btn_Quit" to="." method="_on_btn_quit_pressed"] diff --git a/project.godot b/project.godot index ba95dec..3a00814 100644 --- a/project.godot +++ b/project.godot @@ -11,19 +11,80 @@ config_version=5 [application] config/name="DreamBall" -config/description="I'm Taevas, and this is \"DreamBall\", my entry for the 21st edition of \"Alakajam!\", a gamejam that lasts for 48 hours and starts on 2025-02-21 19:00UTC -https://alakajam.com/21st-alakajam -https://kitsunes.dev/Taevas/AlakajamEntry" -config/version="20250223.2" +config/description="Manipulate the gravity to make a ball go through every ring! +https://kitsunes.dev/Taevas/DreamBall" +config/version="20250503.0" run/main_scene="res://index.tscn" -config/features=PackedStringArray("4.3", "GL Compatibility") +config/features=PackedStringArray("4.4", "GL Compatibility") boot_splash/show_image=false config/icon="res://icon.png" config/windows_native_icon="res://icon.ico" -[audio] +[autoload] -buses/default_bus_layout="" +Settings="*res://settings.gd" +SaveFiles="*res://save_files.gd" + +[input] + +gravity_up={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":122,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":11,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null) +] +} +gravity_left={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":13,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null) +] +} +gravity_right={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":14,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null) +] +} +gravity_down={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":12,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null) +] +} +gravity_strong={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":false,"script":null) +] +} +pause_game={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":6,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":4,"pressure":0.0,"pressed":false,"script":null) +] +} +restart_level={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":114,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":2,"pressure":0.0,"pressed":false,"script":null) +] +} +display_map={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":9,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":false,"script":null) +] +} [physics] @@ -32,6 +93,7 @@ common/physics_ticks_per_second=120 common/max_physics_steps_per_frame=20 3d/physics_engine="GodotPhysics3D" 3d/default_gravity=1.0 +3d/default_gravity_vector=Vector3(0, -0.5, 0) 3d/solver/solver_iterations=40 3d/solver/default_contact_bias=1.0 common/physics_interpolation=true diff --git a/save_files.gd b/save_files.gd new file mode 100644 index 0000000..8521082 --- /dev/null +++ b/save_files.gd @@ -0,0 +1,49 @@ +extends Node + +const names := [ + "user://save_file_1.save", + "user://save_file_2.save", + "user://save_file_3.save", +] + +var selected_file: String + +func _ready() -> void: + for save_file_name in names: + ensure_existence(save_file_name) + +func ensure_existence(save_file_name: String) -> void: + if save_file_name in names and not FileAccess.file_exists(save_file_name): + print("Save file ", save_file_name, " not found, creating it") + empty(save_file_name) + +func empty(save_file_name: String) -> void: + print("Writing an empty object on ", save_file_name) + write(JSON.stringify({}), save_file_name) + +func read(save_file_name: String) -> Variant: + print("Reading from save file ", save_file_name) + ensure_existence(save_file_name) + selected_file = save_file_name + + var save_file := FileAccess.open(save_file_name, FileAccess.READ) + var json := JSON.new() + var json_string := save_file.get_line() + + if json.parse(json_string) != OK: + print("(SAVES) JSON Parse Error: ", json.get_error_message(), " in ", json_string, " at line ", json.get_error_line()) + return {} + + return json.data + +func write(json_string: String, save_file_name: String) -> void: + var save_file := FileAccess.open(save_file_name, FileAccess.WRITE) + save_file.store_line(json_string) + save_file.store_line("FOR YOUR SAFETY, ALWAYS CHECK IF THE DATA OF THE FILES YOU DOWNLOAD LOOKS OKAY") + +func change_property(property: String, value, save_file_name: String) -> void: + print("Changing property '", property, "' on save file ", save_file_name) + ensure_existence(save_file_name) + var data = read(save_file_name) + data[property] = value + write(JSON.stringify(data), save_file_name) diff --git a/save_files.gd.uid b/save_files.gd.uid new file mode 100644 index 0000000..7ccd88d --- /dev/null +++ b/save_files.gd.uid @@ -0,0 +1 @@ +uid://crfwrvs7rlc5h diff --git a/settings.gd b/settings.gd new file mode 100644 index 0000000..012d467 --- /dev/null +++ b/settings.gd @@ -0,0 +1,78 @@ +extends Node + +const settings_file_name := "user://settings.save" + +var fullscreen := false : set = _set_fullscreen, get = _get_fullscreen +func _get_fullscreen() -> bool: + return fullscreen +func _set_fullscreen(new_fullscreen: bool) -> void: + fullscreen = new_fullscreen + var new_state := DisplayServer.WindowMode.WINDOW_MODE_FULLSCREEN if new_fullscreen else DisplayServer.WindowMode.WINDOW_MODE_WINDOWED + DisplayServer.window_set_mode(new_state) + save_settings() + +var sound_on_gravity_change := true : set = _set_sound_on_gravity_change, get = _get_sound_on_gravity_change +func _get_sound_on_gravity_change() -> bool: + return sound_on_gravity_change +func _set_sound_on_gravity_change(new_sound_on_gravity_change: bool) -> void: + sound_on_gravity_change = new_sound_on_gravity_change + save_settings() + +var volume_music := 0.0 : set = _set_volume_music, get = _get_volume_music +func _get_volume_music() -> float: + return volume_music +func _set_volume_music(new_volume_music: float) -> void: + volume_music = new_volume_music + for i in AudioServer.bus_count: + var bus_name := AudioServer.get_bus_name(i) + if bus_name != "Master" and bus_name != "Sounds": + AudioServer.set_bus_volume_db(i, volume_music) + AudioServer.set_bus_mute(i, volume_music <= -15.0) + save_settings() + +var volume_sounds := 0.0 : set = _set_volume_sounds, get = _get_volume_sounds +func _get_volume_sounds() -> float: + return volume_sounds +func _set_volume_sounds(new_volume_sounds: float) -> void: + var bus_index := AudioServer.get_bus_index("Sounds") + if bus_index == -1: + print("The Sounds audio bus is missing, can't set new volume!") + return + + volume_sounds = new_volume_sounds + AudioServer.set_bus_mute(bus_index, volume_sounds <= -15.0) + AudioServer.set_bus_volume_db(bus_index, volume_sounds) + save_settings() + +func _ready() -> void: + if not FileAccess.file_exists(settings_file_name): + print("The settings file has not been found, not reading from it") + return + + var settings_file := FileAccess.open(settings_file_name, FileAccess.READ) + var json := JSON.new() + var json_string := settings_file.get_line() + + if json.parse(json_string) != OK: + print("(SETTINGS) JSON Parse Error: ", json.get_error_message(), " in ", json_string, " at line ", json.get_error_line()) + return + + if json.data.has("fullscreen") and typeof(json.data["fullscreen"]) == TYPE_BOOL: + fullscreen = json.data["fullscreen"] + if json.data.has("sound_on_gravity_change") and typeof(json.data["sound_on_gravity_change"]) == TYPE_BOOL: + sound_on_gravity_change = json.data["sound_on_gravity_change"] + if json.data.has("volume_music") and typeof(json.data["volume_music"]) == TYPE_FLOAT: + volume_music = json.data["volume_music"] + if json.data.has("volume_sounds") and typeof(json.data["volume_sounds"]) == TYPE_FLOAT: + volume_sounds = json.data["volume_sounds"] + +func save_settings() -> void: + var settings_file := FileAccess.open(settings_file_name, FileAccess.WRITE) + var json_string := JSON.stringify({ + "fullscreen": fullscreen, + "sound_on_gravity_change": sound_on_gravity_change, + "volume_music": volume_music, + "volume_sounds": volume_sounds, + }) + settings_file.store_line(json_string) + settings_file.store_line("FOR YOUR SAFETY, ALWAYS CHECK IF THE DATA OF THE FILES YOU DOWNLOAD LOOKS OKAY") diff --git a/settings.gd.uid b/settings.gd.uid new file mode 100644 index 0000000..6ac33eb --- /dev/null +++ b/settings.gd.uid @@ -0,0 +1 @@ +uid://6or7tnhtbqe6 diff --git a/sounds/confirm.ogg b/sounds/confirm.ogg new file mode 100644 index 0000000..f059bcc Binary files /dev/null and b/sounds/confirm.ogg differ diff --git a/sounds/confirm.ogg.import b/sounds/confirm.ogg.import new file mode 100644 index 0000000..26d36e7 --- /dev/null +++ b/sounds/confirm.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bq3tw55s0ud55" +path="res://.godot/imported/confirm.ogg-611700f2069cfd206385315fc10e9491.oggvorbisstr" + +[deps] + +source_file="res://sounds/confirm.ogg" +dest_files=["res://.godot/imported/confirm.ogg-611700f2069cfd206385315fc10e9491.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/sounds/select.ogg b/sounds/select.ogg new file mode 100644 index 0000000..7cc9589 Binary files /dev/null and b/sounds/select.ogg differ diff --git a/sounds/select.ogg.import b/sounds/select.ogg.import new file mode 100644 index 0000000..4eaade7 --- /dev/null +++ b/sounds/select.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bnbf1nfaxuagi" +path="res://.godot/imported/select.ogg-c7e346119419231e86eb892abcba5520.oggvorbisstr" + +[deps] + +source_file="res://sounds/select.ogg" +dest_files=["res://.godot/imported/select.ogg-c7e346119419231e86eb892abcba5520.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/sounds/templateiguess.mmpz b/sounds/templateiguess.mmpz deleted file mode 100644 index d1d4b4b..0000000 Binary files a/sounds/templateiguess.mmpz and /dev/null differ diff --git a/sounds/templateiguess.mmpz.bak b/sounds/templateiguess.mmpz.bak deleted file mode 100644 index 2efa8e2..0000000 Binary files a/sounds/templateiguess.mmpz.bak and /dev/null differ