diff --git a/addons/capri_tools/capri_tools.gd b/addons/capri_tools/capri_tools.gd new file mode 100644 index 0000000..5532114 --- /dev/null +++ b/addons/capri_tools/capri_tools.gd @@ -0,0 +1,17 @@ +@tool +extends EditorPlugin + + +const GlobalSoundSelectorPlugin = preload("global_sound_selector_plugin.gd") + + +var global_sound_selector_plugin: EditorInspectorPlugin + + +func _enter_tree() -> void: + global_sound_selector_plugin = GlobalSoundSelectorPlugin.new() + add_inspector_plugin(global_sound_selector_plugin) + + +func _exit_tree() -> void: + remove_inspector_plugin(global_sound_selector_plugin) diff --git a/addons/capri_tools/capri_tools.gd.uid b/addons/capri_tools/capri_tools.gd.uid new file mode 100644 index 0000000..cc84e25 --- /dev/null +++ b/addons/capri_tools/capri_tools.gd.uid @@ -0,0 +1 @@ +uid://b6rylu4028qec diff --git a/addons/capri_tools/global_music_selector.gd b/addons/capri_tools/global_music_selector.gd new file mode 100644 index 0000000..53d9f8f --- /dev/null +++ b/addons/capri_tools/global_music_selector.gd @@ -0,0 +1,46 @@ +extends EditorProperty + + +var _dropdown_button := Button.new() + +var _popup_menu := PopupMenu.new() + + +func _init() -> void: + _dropdown_button.pressed.connect(_show_popup) + _dropdown_button.icon = EditorInterface.get_editor_theme().get_icon("AudioStreamWAV", "EditorIcons") + + _popup_menu.index_pressed.connect(_on_song_selected) + + add_child(_dropdown_button) + add_child(_popup_menu) + add_focusable(_dropdown_button) + + +func _update_property() -> void: + var new_value: StringName = get_edited_object()[get_edited_property()] + _dropdown_button.text = new_value.capitalize() + + +func _show_popup() -> void: + var songs = Music.songs.keys() + + _popup_menu.clear() + for sound: StringName in songs: + _popup_menu.add_icon_item( + EditorInterface.get_editor_theme().get_icon("AudioStreamWAV", "EditorIcons"), + sound.capitalize() + ) + + var button_rect = _dropdown_button.get_global_rect() + _popup_menu.reset_size() + var popup_pos = button_rect.position + Vector2(DisplayServer.window_get_position()) + _popup_menu.position = popup_pos + _popup_menu.min_size.x = button_rect.size.x + _popup_menu.popup() + + +func _on_song_selected(index: int) -> void: + var sound = Music.songs.keys()[index] + _dropdown_button.grab_focus() + emit_changed(get_edited_property(), sound) diff --git a/addons/capri_tools/global_music_selector.gd.uid b/addons/capri_tools/global_music_selector.gd.uid new file mode 100644 index 0000000..817031e --- /dev/null +++ b/addons/capri_tools/global_music_selector.gd.uid @@ -0,0 +1 @@ +uid://uc6u3ls6jx3y diff --git a/addons/capri_tools/global_sound_selector.gd b/addons/capri_tools/global_sound_selector.gd new file mode 100644 index 0000000..65fcd12 --- /dev/null +++ b/addons/capri_tools/global_sound_selector.gd @@ -0,0 +1,46 @@ +extends EditorProperty + + +var _dropdown_button := Button.new() + +var _popup_menu := PopupMenu.new() + + +func _init() -> void: + _dropdown_button.pressed.connect(_show_popup) + _dropdown_button.icon = EditorInterface.get_editor_theme().get_icon("AudioStreamPlayer", "EditorIcons") + + _popup_menu.index_pressed.connect(_on_sound_selected) + + add_child(_dropdown_button) + add_child(_popup_menu) + add_focusable(_dropdown_button) + + +func _update_property() -> void: + var new_value: StringName = get_edited_object()[get_edited_property()] + _dropdown_button.text = new_value.capitalize() + + +func _show_popup() -> void: + var sounds = GlobalSounds.sounds.keys() + + _popup_menu.clear() + for sound: StringName in sounds: + _popup_menu.add_icon_item( + EditorInterface.get_editor_theme().get_icon("AudioStreamPlayer", "EditorIcons"), + sound.capitalize() + ) + + var button_rect = _dropdown_button.get_global_rect() + _popup_menu.reset_size() + var popup_pos = button_rect.position + Vector2(DisplayServer.window_get_position()) + _popup_menu.position = popup_pos + _popup_menu.min_size.x = button_rect.size.x + _popup_menu.popup() + + +func _on_sound_selected(index: int) -> void: + var sound = GlobalSounds.sounds.keys()[index] + _dropdown_button.grab_focus() + emit_changed(get_edited_property(), sound) diff --git a/addons/capri_tools/global_sound_selector.gd.uid b/addons/capri_tools/global_sound_selector.gd.uid new file mode 100644 index 0000000..146a83e --- /dev/null +++ b/addons/capri_tools/global_sound_selector.gd.uid @@ -0,0 +1 @@ +uid://bwr5g1ae4dxs4 diff --git a/addons/capri_tools/global_sound_selector_plugin.gd b/addons/capri_tools/global_sound_selector_plugin.gd new file mode 100644 index 0000000..4f0e5bc --- /dev/null +++ b/addons/capri_tools/global_sound_selector_plugin.gd @@ -0,0 +1,20 @@ +extends EditorInspectorPlugin + + +const GlobalSoundSelector = preload("global_sound_selector.gd") +const GlobalMusicSelector = preload("global_music_selector.gd") + + +func _can_handle(object: Object) -> bool: + return true + + +func _parse_property(object: Object, type: Variant.Type, name: String, hint_type: PropertyHint, hint_string: String, usage_flags: int, wide: bool) -> bool: + if type == TYPE_STRING_NAME: + if hint_string == "global_sound": + add_property_editor(name, GlobalSoundSelector.new()) + return true + if hint_string == "global_music": + add_property_editor(name, GlobalMusicSelector.new()) + return true + return false diff --git a/addons/capri_tools/global_sound_selector_plugin.gd.uid b/addons/capri_tools/global_sound_selector_plugin.gd.uid new file mode 100644 index 0000000..fdc9d0a --- /dev/null +++ b/addons/capri_tools/global_sound_selector_plugin.gd.uid @@ -0,0 +1 @@ +uid://c3qk8q16lbsk6 diff --git a/addons/capri_tools/plugin.cfg b/addons/capri_tools/plugin.cfg new file mode 100644 index 0000000..98c00f8 --- /dev/null +++ b/addons/capri_tools/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Capri Tools" +description="Bespoke tools for Capri's systems that require an editor plugin to be nicer to use." +author="fogwaves" +version="0.1.0" +script="capri_tools.gd" diff --git a/assets/audio/sfx/se_Attack.wav b/assets/audio/sfx/se_Attack.wav new file mode 100644 index 0000000..841c979 Binary files /dev/null and b/assets/audio/sfx/se_Attack.wav differ diff --git a/assets/audio/sfx/se_Attack.wav.import b/assets/audio/sfx/se_Attack.wav.import new file mode 100644 index 0000000..b64d502 --- /dev/null +++ b/assets/audio/sfx/se_Attack.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://c7b60nylv85rw" +path="res://.godot/imported/se_Attack.wav-e31f042a30847251fde3ee8a3d40f914.sample" + +[deps] + +source_file="res://assets/audio/sfx/se_Attack.wav" +dest_files=["res://.godot/imported/se_Attack.wav-e31f042a30847251fde3ee8a3d40f914.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/sfx/se_turn2.ogg b/assets/audio/sfx/se_turn2.ogg new file mode 100644 index 0000000..97b4b4a Binary files /dev/null and b/assets/audio/sfx/se_turn2.ogg differ diff --git a/assets/audio/sfx/se_turn2.ogg.import b/assets/audio/sfx/se_turn2.ogg.import new file mode 100644 index 0000000..de753e1 --- /dev/null +++ b/assets/audio/sfx/se_turn2.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bhr0uvens076m" +path="res://.godot/imported/se_turn2.ogg-c618521a75be55e5e6d2e2c6dda2432f.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/se_turn2.ogg" +dest_files=["res://.godot/imported/se_turn2.ogg-c618521a75be55e5e6d2e2c6dda2432f.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/spark_bounce.ogg b/assets/audio/sfx/spark_bounce.ogg new file mode 100644 index 0000000..4810a23 Binary files /dev/null and b/assets/audio/sfx/spark_bounce.ogg differ diff --git a/assets/audio/sfx/spark_bounce.ogg.import b/assets/audio/sfx/spark_bounce.ogg.import new file mode 100644 index 0000000..ef15a05 --- /dev/null +++ b/assets/audio/sfx/spark_bounce.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://cmvbwm6gk8n6b" +path="res://.godot/imported/spark_bounce.ogg-224666db975db87c427084fd6483ed17.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/spark_bounce.ogg" +dest_files=["res://.godot/imported/spark_bounce.ogg-224666db975db87c427084fd6483ed17.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/sfx/talking.ogg b/assets/audio/sfx/talking.ogg new file mode 100644 index 0000000..247bdc9 Binary files /dev/null and b/assets/audio/sfx/talking.ogg differ diff --git a/assets/audio/sfx/talking.ogg.import b/assets/audio/sfx/talking.ogg.import new file mode 100644 index 0000000..8c549fe --- /dev/null +++ b/assets/audio/sfx/talking.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dp7tqt5uocg0g" +path="res://.godot/imported/talking.ogg-c9f0588d86aab0968d7be785daa18ffa.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/sfx/talking.ogg" +dest_files=["res://.godot/imported/talking.ogg-c9f0588d86aab0968d7be785daa18ffa.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/vox/capri_die.ogg b/assets/audio/vox/capri_die.ogg index 2ce76ce..e9cc5ff 100644 Binary files a/assets/audio/vox/capri_die.ogg and b/assets/audio/vox/capri_die.ogg differ diff --git a/assets/audio/vox/capri_die2.ogg b/assets/audio/vox/capri_die2.ogg new file mode 100644 index 0000000..a08b241 Binary files /dev/null and b/assets/audio/vox/capri_die2.ogg differ diff --git a/assets/audio/vox/capri_die2.ogg.import b/assets/audio/vox/capri_die2.ogg.import new file mode 100644 index 0000000..6a8da0c --- /dev/null +++ b/assets/audio/vox/capri_die2.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://cxfl2cqlre0ma" +path="res://.godot/imported/capri_die2.ogg-18c0b1c511e561c078406a2aa0e5e748.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/vox/capri_die2.ogg" +dest_files=["res://.godot/imported/capri_die2.ogg-18c0b1c511e561c078406a2aa0e5e748.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/vox/capri_die3.ogg b/assets/audio/vox/capri_die3.ogg new file mode 100644 index 0000000..7015035 Binary files /dev/null and b/assets/audio/vox/capri_die3.ogg differ diff --git a/assets/audio/vox/capri_die3.ogg.import b/assets/audio/vox/capri_die3.ogg.import new file mode 100644 index 0000000..163d0e9 --- /dev/null +++ b/assets/audio/vox/capri_die3.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://c6gck1lyk6aer" +path="res://.godot/imported/capri_die3.ogg-807c3e5821ef93d5e753c3908db8331e.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/vox/capri_die3.ogg" +dest_files=["res://.godot/imported/capri_die3.ogg-807c3e5821ef93d5e753c3908db8331e.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/vox/capri_jump.ogg b/assets/audio/vox/capri_jump.ogg index b1a8cd9..7683a40 100644 Binary files a/assets/audio/vox/capri_jump.ogg and b/assets/audio/vox/capri_jump.ogg differ diff --git a/assets/audio/vox/capri_jump2.ogg b/assets/audio/vox/capri_jump2.ogg new file mode 100644 index 0000000..a4998e8 Binary files /dev/null and b/assets/audio/vox/capri_jump2.ogg differ diff --git a/assets/audio/vox/capri_jump2.ogg.import b/assets/audio/vox/capri_jump2.ogg.import new file mode 100644 index 0000000..de3084f --- /dev/null +++ b/assets/audio/vox/capri_jump2.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://4kxio0mlrr4k" +path="res://.godot/imported/capri_jump2.ogg-138f7506a8a2d9c132199102602dc2e8.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/vox/capri_jump2.ogg" +dest_files=["res://.godot/imported/capri_jump2.ogg-138f7506a8a2d9c132199102602dc2e8.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/vox/capri_jump3.ogg b/assets/audio/vox/capri_jump3.ogg new file mode 100644 index 0000000..f5fd19a Binary files /dev/null and b/assets/audio/vox/capri_jump3.ogg differ diff --git a/assets/audio/vox/capri_jump3.ogg.import b/assets/audio/vox/capri_jump3.ogg.import new file mode 100644 index 0000000..033480c --- /dev/null +++ b/assets/audio/vox/capri_jump3.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://c350jqy4yue8c" +path="res://.godot/imported/capri_jump3.ogg-168c550662b5a80e215318bca06ff59a.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/vox/capri_jump3.ogg" +dest_files=["res://.godot/imported/capri_jump3.ogg-168c550662b5a80e215318bca06ff59a.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/vox/capri_whee.ogg b/assets/audio/vox/capri_whee.ogg new file mode 100644 index 0000000..487746e Binary files /dev/null and b/assets/audio/vox/capri_whee.ogg differ diff --git a/assets/audio/vox/capri_whee.ogg.import b/assets/audio/vox/capri_whee.ogg.import new file mode 100644 index 0000000..11c5b64 --- /dev/null +++ b/assets/audio/vox/capri_whee.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://cquhska140wrt" +path="res://.godot/imported/capri_whee.ogg-177e99e3b3a8ad5a2d776cf66a13a3f7.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/vox/capri_whee.ogg" +dest_files=["res://.godot/imported/capri_whee.ogg-177e99e3b3a8ad5a2d776cf66a13a3f7.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/vox/capri_whee2.ogg b/assets/audio/vox/capri_whee2.ogg new file mode 100644 index 0000000..6ff0d88 Binary files /dev/null and b/assets/audio/vox/capri_whee2.ogg differ diff --git a/assets/audio/vox/capri_whee2.ogg.import b/assets/audio/vox/capri_whee2.ogg.import new file mode 100644 index 0000000..915734e --- /dev/null +++ b/assets/audio/vox/capri_whee2.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://e3ptgegyv17" +path="res://.godot/imported/capri_whee2.ogg-fe3f7cf3d1a8f02e34e728c2a3933520.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/vox/capri_whee2.ogg" +dest_files=["res://.godot/imported/capri_whee2.ogg-fe3f7cf3d1a8f02e34e728c2a3933520.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/audio/vox/capri_whee3.ogg b/assets/audio/vox/capri_whee3.ogg new file mode 100644 index 0000000..f435ab4 Binary files /dev/null and b/assets/audio/vox/capri_whee3.ogg differ diff --git a/assets/audio/vox/capri_whee3.ogg.import b/assets/audio/vox/capri_whee3.ogg.import new file mode 100644 index 0000000..1345ce9 --- /dev/null +++ b/assets/audio/vox/capri_whee3.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bauqpxusk0p1i" +path="res://.godot/imported/capri_whee3.ogg-8d73a1d93bb396025b986657ecaaf3d7.oggvorbisstr" + +[deps] + +source_file="res://assets/audio/vox/capri_whee3.ogg" +dest_files=["res://.godot/imported/capri_whee3.ogg-8d73a1d93bb396025b986657ecaaf3d7.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/music/bug_music.ogg b/assets/music/bug_music.ogg new file mode 100644 index 0000000..f36408e Binary files /dev/null and b/assets/music/bug_music.ogg differ diff --git a/assets/music/bug_music.ogg.import b/assets/music/bug_music.ogg.import new file mode 100644 index 0000000..d2bb39b --- /dev/null +++ b/assets/music/bug_music.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dmctaba7v1rgu" +path="res://.godot/imported/bug_music.ogg-4e14ca93037a40f8bd3b8d23ee565dcc.oggvorbisstr" + +[deps] + +source_file="res://assets/music/bug_music.ogg" +dest_files=["res://.godot/imported/bug_music.ogg-4e14ca93037a40f8bd3b8d23ee565dcc.oggvorbisstr"] + +[params] + +loop=true +loop_offset=28.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/assets/shaders/orbit.gdshader b/assets/shaders/orbit.gdshader new file mode 100644 index 0000000..6a7d2ac --- /dev/null +++ b/assets/shaders/orbit.gdshader @@ -0,0 +1,9 @@ +shader_type canvas_item; + +uniform float radius = 0.0; +uniform float speed = 0.0; + +void vertex() { + VERTEX.x += cos(TIME * speed) * radius; + VERTEX.y += sin(TIME * speed) * radius; +} \ No newline at end of file diff --git a/assets/shaders/orbit.gdshader.uid b/assets/shaders/orbit.gdshader.uid new file mode 100644 index 0000000..cba262d --- /dev/null +++ b/assets/shaders/orbit.gdshader.uid @@ -0,0 +1 @@ +uid://bc8j5jyjynbca diff --git a/assets/textures/effects/spark.png b/assets/textures/effects/spark.png new file mode 100644 index 0000000..ab73f11 Binary files /dev/null and b/assets/textures/effects/spark.png differ diff --git a/assets/textures/effects/spark.png.import b/assets/textures/effects/spark.png.import new file mode 100644 index 0000000..4c2eadd --- /dev/null +++ b/assets/textures/effects/spark.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://rhc3c5j1lfw" +path="res://.godot/imported/spark.png-81510591edeaafcb46d1dae5039251df.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/effects/spark.png" +dest_files=["res://.godot/imported/spark.png-81510591edeaafcb46d1dae5039251df.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/textures/effects/star.png b/assets/textures/effects/star.png new file mode 100644 index 0000000..6f40653 Binary files /dev/null and b/assets/textures/effects/star.png differ diff --git a/assets/textures/effects/star.png.import b/assets/textures/effects/star.png.import new file mode 100644 index 0000000..76a1bb4 --- /dev/null +++ b/assets/textures/effects/star.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://350f21o7jrwq" +path="res://.godot/imported/star.png-38ac4bbd5414650c87c46e4e35f1e557.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/effects/star.png" +dest_files=["res://.godot/imported/star.png-38ac4bbd5414650c87c46e4e35f1e557.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/textures/images/descent.png b/assets/textures/images/descent.png new file mode 100644 index 0000000..00f6bcb Binary files /dev/null and b/assets/textures/images/descent.png differ diff --git a/assets/textures/images/descent.png.import b/assets/textures/images/descent.png.import new file mode 100644 index 0000000..51f43ec --- /dev/null +++ b/assets/textures/images/descent.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d20y42ga1toxx" +path="res://.godot/imported/descent.png-006f7735d1f2d70f080ecd6b75c4d623.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/images/descent.png" +dest_files=["res://.godot/imported/descent.png-006f7735d1f2d70f080ecd6b75c4d623.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/textures/player/capri.png b/assets/textures/player/capri.png index c2ac482..dfd1bf4 100644 Binary files a/assets/textures/player/capri.png and b/assets/textures/player/capri.png differ diff --git a/assets/textures/player/capri.xcf b/assets/textures/player/capri.xcf index 35f1b36..6cd12ef 100644 Binary files a/assets/textures/player/capri.xcf and b/assets/textures/player/capri.xcf differ diff --git a/assets/textures/portal/portal.png b/assets/textures/portal/portal.png index db2cc58..a7b11af 100644 Binary files a/assets/textures/portal/portal.png and b/assets/textures/portal/portal.png differ diff --git a/assets/textures/portal/portal_light.png b/assets/textures/portal/portal_light.png new file mode 100644 index 0000000..2480336 Binary files /dev/null and b/assets/textures/portal/portal_light.png differ diff --git a/assets/textures/portal/portal_light.png.import b/assets/textures/portal/portal_light.png.import new file mode 100644 index 0000000..4299299 --- /dev/null +++ b/assets/textures/portal/portal_light.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://h45qkvmrh0ey" +path="res://.godot/imported/portal_light.png-d532b82e892c0e52c813f6e6c6a7a723.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/portal/portal_light.png" +dest_files=["res://.godot/imported/portal_light.png-d532b82e892c0e52c813f6e6c6a7a723.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/textures/portal/portal_normal.png b/assets/textures/portal/portal_normal.png new file mode 100644 index 0000000..66dd095 Binary files /dev/null and b/assets/textures/portal/portal_normal.png differ diff --git a/assets/textures/portal/portal_normal.png.import b/assets/textures/portal/portal_normal.png.import new file mode 100644 index 0000000..b08963f --- /dev/null +++ b/assets/textures/portal/portal_normal.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cv7rv8wlhpbg1" +path="res://.godot/imported/portal_normal.png-451e042ab64ba3e4f59ef197b788c326.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/portal/portal_normal.png" +dest_files=["res://.godot/imported/portal_normal.png-451e042ab64ba3e4f59ef197b788c326.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/textures/rotoboy/rotoboy_face.png b/assets/textures/rotoboy/rotoboy_face.png index 138bb55..6f49dbe 100644 Binary files a/assets/textures/rotoboy/rotoboy_face.png and b/assets/textures/rotoboy/rotoboy_face.png differ diff --git a/assets/textures/rotoboy/rotoboy_smile.png b/assets/textures/rotoboy/rotoboy_smile.png index 747ee6f..77784af 100644 Binary files a/assets/textures/rotoboy/rotoboy_smile.png and b/assets/textures/rotoboy/rotoboy_smile.png differ diff --git a/autoloads/global_sounds.gd b/autoloads/global_sounds.gd new file mode 100644 index 0000000..81a3cfb --- /dev/null +++ b/autoloads/global_sounds.gd @@ -0,0 +1,18 @@ +@tool +extends Node + + +@export_tool_button("Update Sounds") var _update_sounds_action = _update_sounds +@export var sounds: Dictionary[StringName, AudioStreamPlayer] + + +func play_sound(id: StringName) -> void: + var sound := sounds.get(id) as AudioStreamPlayer + sound.play() + +func _update_sounds() -> void: + sounds.clear() + for node in get_children(): + if node is AudioStreamPlayer: + sounds[node.name] = node + notify_property_list_changed() diff --git a/autoloads/global_sounds.gd.uid b/autoloads/global_sounds.gd.uid new file mode 100644 index 0000000..764c3a9 --- /dev/null +++ b/autoloads/global_sounds.gd.uid @@ -0,0 +1 @@ +uid://c1yco1xiqppw diff --git a/autoloads/global_sounds.tscn b/autoloads/global_sounds.tscn new file mode 100644 index 0000000..f848e22 --- /dev/null +++ b/autoloads/global_sounds.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=4 format=3 uid="uid://cof2sm0drv2i"] + +[ext_resource type="Script" uid="uid://c1yco1xiqppw" path="res://autoloads/global_sounds.gd" id="1_22s5s"] +[ext_resource type="AudioStream" uid="uid://sci5aqar0oyx" path="res://assets/audio/bgs/amb_sog.wav" id="2_3njyb"] +[ext_resource type="AudioStream" uid="uid://flc817bekeh6" path="res://assets/audio/sfx/level_win.ogg" id="3_pqonv"] + +[node name="GlobalSounds" type="Node" node_paths=PackedStringArray("sounds")] +script = ExtResource("1_22s5s") +sounds = { +&"SoggyAmbience": NodePath("SoggyAmbience"), +&"WinSound": NodePath("WinSound") +} + +[node name="SoggyAmbience" type="AudioStreamPlayer" parent="."] +stream = ExtResource("2_3njyb") +volume_db = -10.0 +bus = &"Background Sound" + +[node name="WinSound" type="AudioStreamPlayer" parent="."] +stream = ExtResource("3_pqonv") +volume_db = -6.558 +bus = &"Sound Effects" diff --git a/autoloads/levels.gd b/autoloads/levels.gd index dc97f4e..2e73738 100644 --- a/autoloads/levels.gd +++ b/autoloads/levels.gd @@ -2,3 +2,61 @@ extends Node @export var level_sets: Array[LevelSet] = [] + + +var current_set_index: int = 0 +var current_level_index: int = 0 + +var current_set: LevelSet: + get(): + return level_sets[current_set_index] + +var current_level: LevelInfo: + get(): + return current_set.levels[current_level_index] + + +func _ready() -> void: + SceneManager.current_scene_changed.connect(_on_current_scene_changed) + + +func get_level(set_idx: int, level_idx: int) -> LevelInfo: + if set_idx >= level_sets.size(): + return null + var lvl_set = level_sets[set_idx] + if level_idx >= lvl_set.levels.size(): + return null + return lvl_set.levels[level_idx] + + +func advance_level() -> void: + var next_idx = current_level_index + 1 + + # change scene to end-of-set scene if it is reached + if next_idx >= current_set.levels.size(): + SceneManager.current_scene = current_set.end_scene.instantiate() + return + + var level_info = current_set.levels[next_idx] + var level = load(level_info.scene_path) as PackedScene + if level: + SceneManager.current_scene = level.instantiate() + +func _detect_current_level() -> void: + if not SceneManager.current_scene is Level: + current_set_index = -1 + current_level_index = -1 + return + + for idx_set in level_sets.size(): + var level_set = level_sets[idx_set] + for idx_lvl in level_set.levels.size(): + var level = level_set.levels[idx_lvl] + if level.scene_path == SceneManager.current_scene.scene_file_path: + current_set_index = idx_set + current_level_index = idx_lvl + return + + +func _on_current_scene_changed(_new_scene: Node) -> void: + _detect_current_level() diff --git a/autoloads/levels.tscn b/autoloads/levels.tscn index 54258b7..dea6664 100644 --- a/autoloads/levels.tscn +++ b/autoloads/levels.tscn @@ -1,6 +1,9 @@ -[gd_scene load_steps=2 format=3 uid="uid://dbqsgks307bto"] +[gd_scene load_steps=4 format=3 uid="uid://dbqsgks307bto"] [ext_resource type="Script" uid="uid://4na03iques5r" path="res://autoloads/levels.gd" id="1_b8434"] +[ext_resource type="Script" uid="uid://dak8il8fxqyph" path="res://scripts/level/level_set.gd" id="2_ebfuu"] +[ext_resource type="Resource" uid="uid://g36wkssommtr" path="res://maps/descent.tres" id="3_hgsu8"] [node name="Levels" type="Node"] script = ExtResource("1_b8434") +level_sets = Array[ExtResource("2_ebfuu")]([ExtResource("3_hgsu8")]) diff --git a/autoloads/music.gd b/autoloads/music.gd new file mode 100644 index 0000000..2a2e7e3 --- /dev/null +++ b/autoloads/music.gd @@ -0,0 +1,53 @@ +@tool +extends Node + + +@export_dir var songs_dir: String +@export_tool_button("Update Songs") var _update_songs_action = _update_songs +@export var songs: Dictionary[StringName, AudioStream] + +@export var player_a: AudioStreamPlayer +@export var player_b: AudioStreamPlayer + + +@onready var _active_player: AudioStreamPlayer = player_a +@onready var _tween: Tween = null + + +func play_song(id: StringName, crossfade_time: float = 0.0, restart: bool = false) -> void: + var new_stream = songs.get(id) as AudioStream + if new_stream: + if not restart and _active_player.stream == new_stream: + return + var new_player = player_b if _active_player == player_a else player_a + new_player.stream = new_stream + new_player.play() + + if crossfade_time > 0.0: + new_player.volume_linear = 0.0 + if _tween: + _tween.kill() + _tween = create_tween().set_parallel() + _tween.tween_property(new_player, ^"volume_linear", 1.0, crossfade_time) + _tween.tween_property(_active_player, ^"volume_linear", 0.0, crossfade_time) + _tween.chain().tween_callback(_active_player.stop) + else: + new_player.volume_linear = 1.0 + _active_player.stop() + + _active_player = new_player + + +func _update_songs() -> void: + songs.clear() + var dir = DirAccess.open(songs_dir) + if dir: + dir.list_dir_begin() + var file = dir.get_next() + while file != "": + if not dir.current_is_dir() and not file.ends_with(".import"): + var stream := load(songs_dir + "/" + file) as AudioStream + if stream: + songs[file.get_basename()] = stream + file = dir.get_next() + notify_property_list_changed() diff --git a/autoloads/music.gd.uid b/autoloads/music.gd.uid new file mode 100644 index 0000000..9bbeb91 --- /dev/null +++ b/autoloads/music.gd.uid @@ -0,0 +1 @@ +uid://dgi1v18r8dx4q diff --git a/autoloads/music.tscn b/autoloads/music.tscn new file mode 100644 index 0000000..7a7902e --- /dev/null +++ b/autoloads/music.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://cxrhw5ic2vunh"] + +[ext_resource type="Script" uid="uid://dgi1v18r8dx4q" path="res://autoloads/music.gd" id="1_16wm1"] +[ext_resource type="AudioStream" uid="uid://dmctaba7v1rgu" path="res://assets/music/bug_music.ogg" id="2_kl0u4"] + +[node name="Music" type="Node" node_paths=PackedStringArray("player_a", "player_b")] +script = ExtResource("1_16wm1") +songs_dir = "res://assets/music" +songs = Dictionary[StringName, AudioStream]({ +&"bug_music": ExtResource("2_kl0u4") +}) +player_a = NodePath("MusicPlayerA") +player_b = NodePath("MusicPlayerB") + +[node name="MusicPlayerA" type="AudioStreamPlayer" parent="."] +bus = &"Music" + +[node name="MusicPlayerB" type="AudioStreamPlayer" parent="."] +bus = &"Music" diff --git a/autoloads/scene_manager.gd b/autoloads/scene_manager.gd index ca9f723..e47dccd 100644 --- a/autoloads/scene_manager.gd +++ b/autoloads/scene_manager.gd @@ -1,6 +1,10 @@ extends Node +## Emitted when the current scene is changed. +signal current_scene_changed(new_scene: Node) + + ## Methods of scaling the game viewport. enum ScaleMode { ## Maintain aspect ratio and scale by highest whole number that will fit within the screen. @@ -28,7 +32,6 @@ enum ScaleMode { ProjectSettings.get_setting("display/window/size/viewport_height") ) -@onready var win_sound = $WinSound ## The currently active scene. ## @@ -40,13 +43,14 @@ var current_scene: Node: return # remove current scene if current_scene: - viewport.remove_child(current_scene) + viewport.remove_child.call_deferred(current_scene) current_scene.queue_free() # add new scene if new_scene.is_inside_tree(): - new_scene.get_parent().remove_child(new_scene) - viewport.add_child(new_scene) + new_scene.get_parent().remove_child.call_deferred(new_scene) + viewport.add_child.call_deferred(new_scene) current_scene = new_scene + current_scene_changed.emit(new_scene) func _ready() -> void: diff --git a/autoloads/scene_manager.tscn b/autoloads/scene_manager.tscn index 4ac64e0..18ede0a 100644 --- a/autoloads/scene_manager.tscn +++ b/autoloads/scene_manager.tscn @@ -1,8 +1,6 @@ -[gd_scene load_steps=4 format=3 uid="uid://ckgsfhfpg00ys"] +[gd_scene load_steps=2 format=3 uid="uid://ckgsfhfpg00ys"] [ext_resource type="Script" uid="uid://crlo6ow7fo6ca" path="res://autoloads/scene_manager.gd" id="1_1hxm1"] -[ext_resource type="AudioStream" uid="uid://sci5aqar0oyx" path="res://assets/audio/bgs/amb_sog.wav" id="2_dr7pa"] -[ext_resource type="AudioStream" uid="uid://flc817bekeh6" path="res://assets/audio/sfx/level_win.ogg" id="3_8ri5f"] [node name="SceneManager" type="Node" node_paths=PackedStringArray("viewport", "viewport_holder")] script = ExtResource("1_1hxm1") @@ -47,16 +45,6 @@ pivot_offset = Vector2(144, 108) [node name="SubViewport" type="SubViewport" parent="ViewportHolder/ViewportContainer"] handle_input_locally = false canvas_item_default_texture_filter = 0 +audio_listener_enable_2d = true size = Vector2i(288, 216) render_target_update_mode = 4 - -[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] -stream = ExtResource("2_dr7pa") -volume_db = -10.0 -autoplay = true -bus = &"Background Sound" - -[node name="WinSound" type="AudioStreamPlayer" parent="."] -stream = ExtResource("3_8ri5f") -volume_db = -6.558 -bus = &"Sound Effects" diff --git a/cutscenes/world1_cut.tscn b/cutscenes/world1_cut.tscn new file mode 100644 index 0000000..884aad6 --- /dev/null +++ b/cutscenes/world1_cut.tscn @@ -0,0 +1,173 @@ +[gd_scene load_steps=7 format=3 uid="uid://bt3mxr1j3qyul"] + +[ext_resource type="Texture2D" uid="uid://d20y42ga1toxx" path="res://assets/textures/images/descent.png" id="1_edpvw"] +[ext_resource type="FontFile" uid="uid://dets0g4ce7npf" path="res://assets/fonts/Super Mario Bros. NES.ttf" id="2_3lnes"] +[ext_resource type="AudioStream" uid="uid://dp7tqt5uocg0g" path="res://assets/audio/sfx/talking.ogg" id="3_3lnes"] + +[sub_resource type="Animation" id="Animation_edpvw"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Label:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(7, 6)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Label2:position") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(169, 186)] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("ColorRect:color") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(0, 0, 0, 1)] +} +tracks/3/type = "value" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath("AudioStreamPlayer:playing") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [false] +} + +[sub_resource type="Animation" id="Animation_5wwpe"] +resource_name = "fade" +length = 6.0 +step = 0.25 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Label:position") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(2, 2.5, 2.56061, 2.62121), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 0, +"values": [Vector2(-126.41, 6), Vector2(7, 6), Vector2(8, 6), Vector2(7, 6)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Label2:position") +tracks/1/interp = 2 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(2.55, 3.06515, 3.12576, 3.18636), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 0, +"values": [Vector2(295, 186), Vector2(169, 186), Vector2(170, 186), Vector2(169, 186)] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("ColorRect:color") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0.030303, 2), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Color(0, 0, 0, 1), Color(0, 0, 0, 0)] +} +tracks/3/type = "method" +tracks/3/imported = false +tracks/3/enabled = false +tracks/3/path = NodePath("AudioStreamPlayer") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"times": PackedFloat32Array(1.33333), +"transitions": PackedFloat32Array(1), +"values": [{ +"args": [0.0], +"method": &"play" +}] +} +tracks/4/type = "value" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath("AudioStreamPlayer:playing") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"times": PackedFloat32Array(2), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [true] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_iw1oc"] +_data = { +&"RESET": SubResource("Animation_edpvw"), +&"fade": SubResource("Animation_5wwpe") +} + +[node name="World1Cut" type="Node2D"] + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +&"": SubResource("AnimationLibrary_iw1oc") +} +autoplay = "fade" + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(144, 108) +texture = ExtResource("1_edpvw") + +[node name="Label" type="Label" parent="."] +offset_left = 7.0 +offset_top = 6.0 +offset_right = 119.0 +offset_bottom = 29.0 +theme_override_colors/font_shadow_color = Color(0, 0, 0, 1) +theme_override_constants/shadow_outline_size = 8 +theme_override_fonts/font = ExtResource("2_3lnes") +theme_override_font_sizes/font_size = 16 +text = "WORLD 1" + +[node name="Label2" type="Label" parent="."] +offset_left = 169.0 +offset_top = 186.0 +offset_right = 281.0 +offset_bottom = 209.0 +theme_override_colors/font_shadow_color = Color(0, 0, 0, 1) +theme_override_constants/shadow_outline_size = 8 +theme_override_fonts/font = ExtResource("2_3lnes") +theme_override_font_sizes/font_size = 16 +text = "DESCENT" + +[node name="ColorRect" type="ColorRect" parent="."] +offset_right = 293.0 +offset_bottom = 219.0 +color = Color(0, 0, 0, 1) + +[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] +stream = ExtResource("3_3lnes") + +[connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_animation_player_animation_finished"] diff --git a/default_bus_layout.tres b/default_bus_layout.tres index c20f634..86cc9b8 100644 --- a/default_bus_layout.tres +++ b/default_bus_layout.tres @@ -10,23 +10,29 @@ spread = 0.3 wet = 0.1 [resource] -bus/1/name = &"Capri" +bus/1/name = &"Music" bus/1/solo = false bus/1/mute = false bus/1/bypass_fx = false bus/1/volume_db = 0.0 bus/1/send = &"Master" -bus/1/effect/0/effect = SubResource("AudioEffectReverb_rn7sq") -bus/1/effect/0/enabled = true -bus/2/name = &"Background Sound" +bus/2/name = &"Capri" bus/2/solo = false bus/2/mute = false bus/2/bypass_fx = false bus/2/volume_db = 0.0 bus/2/send = &"Master" -bus/3/name = &"Sound Effects" +bus/2/effect/0/effect = SubResource("AudioEffectReverb_rn7sq") +bus/2/effect/0/enabled = true +bus/3/name = &"Background Sound" bus/3/solo = false bus/3/mute = false bus/3/bypass_fx = false bus/3/volume_db = 0.0 bus/3/send = &"Master" +bus/4/name = &"Sound Effects" +bus/4/solo = false +bus/4/mute = false +bus/4/bypass_fx = false +bus/4/volume_db = 0.0 +bus/4/send = &"Master" diff --git a/maps/descent.tres b/maps/descent.tres new file mode 100644 index 0000000..b1f42cd --- /dev/null +++ b/maps/descent.tres @@ -0,0 +1,57 @@ +[gd_resource type="Resource" script_class="LevelSet" load_steps=10 format=3 uid="uid://g36wkssommtr"] + +[ext_resource type="Script" uid="uid://d3hlv706rwapg" path="res://scripts/level/level_info.gd" id="1_47duy"] +[ext_resource type="PackedScene" uid="uid://bbnq7ptk8hhxa" path="res://maps/level1.tscn" id="1_d6k11"] +[ext_resource type="Script" uid="uid://dak8il8fxqyph" path="res://scripts/level/level_set.gd" id="2_f3ju2"] +[ext_resource type="PackedScene" uid="uid://bt3mxr1j3qyul" path="res://cutscenes/world1_cut.tscn" id="4_i5ovp"] + +[sub_resource type="Resource" id="Resource_d6k11"] +resource_name = "Obligatory Tutorial Level" +script = ExtResource("1_47duy") +title = "Obligatory Tutorial Level" +id = "tutorial" +order = 0 +scene_path = "res://maps/descent/tutorial.tscn" + +[sub_resource type="Resource" id="Resource_i5ovp"] +resource_name = "Yikes! Spikes!" +script = ExtResource("1_47duy") +title = "Yikes! Spikes!" +id = "spikes" +order = 1 +scene_path = "res://maps/descent/yikes_spikes.tscn" + +[sub_resource type="Resource" id="Resource_p1poa"] +resource_name = "Yikes! More Spikes!" +script = ExtResource("1_47duy") +title = "Yikes! More Spikes!" +id = "more-spikes" +order = 2 +scene_path = "res://maps/descent/yikes_more_spikes.tscn" + +[sub_resource type="Resource" id="Resource_sgm6x"] +resource_name = "Spring Time!" +script = ExtResource("1_47duy") +title = "Spring Time!" +id = "spring-time" +order = 3 +scene_path = "res://maps/descent/its_spring.tscn" + +[sub_resource type="Resource" id="Resource_ba8kn"] +resource_name = "Purple Portals" +script = ExtResource("1_47duy") +title = "Purple Portals" +id = "purple-portals" +order = 4 +scene_path = "res://maps/descent/purple_portals.tscn" + +[resource] +resource_name = "Descent" +script = ExtResource("2_f3ju2") +title = "Descent" +id = "descent" +start_scene = ExtResource("4_i5ovp") +end_scene = ExtResource("1_d6k11") +levels_dir = "res://maps/descent" +levels = Array[ExtResource("1_47duy")]([SubResource("Resource_d6k11"), SubResource("Resource_i5ovp"), SubResource("Resource_p1poa"), SubResource("Resource_sgm6x"), SubResource("Resource_ba8kn")]) +metadata/_custom_type_script = "uid://dak8il8fxqyph" diff --git a/maps/its_spring.tscn b/maps/descent/its_spring.tscn similarity index 89% rename from maps/its_spring.tscn rename to maps/descent/its_spring.tscn index 37ca0ac..cffb372 100644 --- a/maps/its_spring.tscn +++ b/maps/descent/its_spring.tscn @@ -1,12 +1,13 @@ -[gd_scene load_steps=12 format=3 uid="uid://bd2srrfspy7ft"] +[gd_scene load_steps=13 format=3 uid="uid://bd2srrfspy7ft"] +[ext_resource type="Script" uid="uid://d3v13a4er2h1x" path="res://scripts/level/level.gd" id="1_dnp5v"] [ext_resource type="Texture2D" uid="uid://d13tqqx8ygak4" path="res://assets/textures/backgrounds/hell.png" id="1_p8vut"] [ext_resource type="Shader" uid="uid://cwktxks6mchp2" path="res://assets/shaders/noise.gdshader" id="2_hpwyk"] [ext_resource type="PackedScene" uid="uid://bwtpsjpe2lf7l" path="res://objects/player/player.tscn" id="3_edpy5"] [ext_resource type="TileSet" uid="uid://xwfn24if3pxk" path="res://assets/tilesets/chocomint.tres" id="4_onc0l"] [ext_resource type="FontFile" uid="uid://dets0g4ce7npf" path="res://assets/fonts/Super Mario Bros. NES.ttf" id="5_s8gph"] [ext_resource type="PackedScene" uid="uid://bhnse651bcybm" path="res://objects/end_door/end_door.tscn" id="6_8fhro"] -[ext_resource type="PackedScene" uid="uid://bbnq7ptk8hhxa" path="res://maps/level1.tscn" id="7_bmr8a"] +[ext_resource type="PackedScene" uid="uid://dmg4t4vm6fd5s" path="res://maps/descent/purple_portals.tscn" id="7_ri7pq"] [ext_resource type="PackedScene" uid="uid://cnqmbq84hbnvj" path="res://objects/spikes/spikes.tscn" id="8_cfxl1"] [ext_resource type="PackedScene" uid="uid://68lav5rke5ag" path="res://objects/spring/spring.tscn" id="9_dtd3x"] @@ -18,7 +19,11 @@ shader_parameter/animate_noise = true shader_parameter/noise_intensity = 1.0 shader_parameter/fps = 15.0 -[node name="Level1" type="Node2D"] +[node name="SpringTime" type="Node2D"] +script = ExtResource("1_dnp5v") +title = "Spring Time!" +id = "spring-time" +order = 3 [node name="Sprite2D" type="Sprite2D" parent="."] material = SubResource("ShaderMaterial_sf5kh") @@ -52,7 +57,7 @@ horizontal_alignment = 1 [node name="EndDoor" parent="." instance=ExtResource("6_8fhro")] position = Vector2(280, 24) -next_map = ExtResource("7_bmr8a") +next_map = ExtResource("7_ri7pq") [node name="Node2D" type="Node2D" parent="."] diff --git a/maps/descent/purple_portals.tscn b/maps/descent/purple_portals.tscn new file mode 100644 index 0000000..31e73b0 --- /dev/null +++ b/maps/descent/purple_portals.tscn @@ -0,0 +1,85 @@ +[gd_scene load_steps=12 format=3 uid="uid://dmg4t4vm6fd5s"] + +[ext_resource type="Script" uid="uid://d3v13a4er2h1x" path="res://scripts/level/level.gd" id="1_srnft"] +[ext_resource type="Texture2D" uid="uid://d13tqqx8ygak4" path="res://assets/textures/backgrounds/hell.png" id="2_lx20c"] +[ext_resource type="Shader" uid="uid://cwktxks6mchp2" path="res://assets/shaders/noise.gdshader" id="3_bgmin"] +[ext_resource type="PackedScene" uid="uid://bwtpsjpe2lf7l" path="res://objects/player/player.tscn" id="4_v3h03"] +[ext_resource type="TileSet" uid="uid://xwfn24if3pxk" path="res://assets/tilesets/chocomint.tres" id="5_hgo3q"] +[ext_resource type="PackedScene" uid="uid://cypj35yv5auuc" path="res://objects/portal/portal.tscn" id="6_hgo3q"] +[ext_resource type="PackedScene" uid="uid://bhnse651bcybm" path="res://objects/end_door/end_door.tscn" id="7_ti0gq"] +[ext_resource type="PackedScene" uid="uid://bbnq7ptk8hhxa" path="res://maps/level1.tscn" id="8_o4epc"] +[ext_resource type="PackedScene" uid="uid://cnqmbq84hbnvj" path="res://objects/spikes/spikes.tscn" id="9_o4epc"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_v3h03"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_hgo3q"] +shader = ExtResource("3_bgmin") +shader_parameter/animate_noise = true +shader_parameter/noise_intensity = 1.0 +shader_parameter/fps = 15.0 + +[node name="PurplePortals" type="Node2D"] +script = ExtResource("1_srnft") +title = "Purple Portals" +id = "purple-portals" +order = 4 +metadata/_custom_type_script = "uid://d3v13a4er2h1x" + +[node name="Sprite2D" type="Sprite2D" parent="."] +material = SubResource("ShaderMaterial_v3h03") +position = Vector2(144, 108) +texture = ExtResource("2_lx20c") + +[node name="ColorRect" type="ColorRect" parent="Sprite2D"] +material = SubResource("ShaderMaterial_hgo3q") +offset_left = -144.0 +offset_top = -108.0 +offset_right = 144.0 +offset_bottom = 108.0 +color = Color(0.194349, 0.194349, 0.194349, 0.447059) + +[node name="Player" parent="." instance=ExtResource("4_v3h03")] +position = Vector2(24, 168) + +[node name="TileMap" type="TileMap" parent="."] +tile_set = ExtResource("5_hgo3q") +format = 2 +layer_0/tile_data = PackedInt32Array(720896, 0, 0, 720897, 0, 0, 720898, 0, 0, 720899, 0, 0, 720900, 0, 0, 720901, 0, 0, 720902, 0, 0, 720903, 0, 0, 720904, 0, 0, 720905, 0, 0, 720906, 0, 0, 720907, 0, 0, 720908, 0, 0, 720909, 0, 0, 720910, 0, 0, 720911, 0, 0, 720912, 0, 0, 720913, 0, 0, 15, 0, 0, 65551, 0, 0, 131087, 0, 0, 196623, 0, 0, 262159, 0, 0, 327695, 0, 0, 393231, 0, 0, 458767, 0, 0, 524303, 0, 0, 589839, 0, 0, 655375, 0, 0, 0, 0, 0, 65536, 0, 0, 131072, 0, 0, 196608, 0, 0, 6, 0, 0, 65542, 0, 0, 131078, 0, 0, 196614, 0, 0, 262150, 0, 0, 327686, 0, 0, 393222, 0, 0, 393216, 0, 0, 262144, 0, 0, 327680, 0, 0, 458758, 0, 0, 524294, 0, 0, 589830, 0, 0, 655366, 0, 0, 393227, 0, 0, 393228, 0, 0, 393229, 0, 0, 393230, 0, 0, 458757, 0, 0, 458756, 0, 0, 458755, 0, 0, 458754, 0, 0, 458753, 0, 0, 458752, 0, 0) + +[node name="Portal" parent="." node_paths=PackedStringArray("linked_portal") instance=ExtResource("6_hgo3q")] +position = Vector2(73, 144) +linked_portal = NodePath("../Portal2") + +[node name="Portal2" parent="." node_paths=PackedStringArray("linked_portal") instance=ExtResource("6_hgo3q")] +position = Vector2(152, 120) +linked_portal = NodePath("../Portal") + +[node name="Portal3" parent="." node_paths=PackedStringArray("linked_portal") instance=ExtResource("6_hgo3q")] +position = Vector2(233, 144) +linked_portal = NodePath("../Portal4") + +[node name="Portal4" parent="." node_paths=PackedStringArray("linked_portal") instance=ExtResource("6_hgo3q")] +position = Vector2(40, 56) +linked_portal = NodePath("../Portal3") + +[node name="EndDoor" parent="." instance=ExtResource("7_ti0gq")] +position = Vector2(24, 88) +next_map = ExtResource("8_o4epc") + +[node name="Spikes" parent="." instance=ExtResource("9_o4epc")] +position = Vector2(168, 168) + +[node name="Spikes2" parent="." instance=ExtResource("9_o4epc")] +position = Vector2(88, 104) + +[node name="Spikes3" parent="." instance=ExtResource("9_o4epc")] +position = Vector2(72, 104) + +[node name="Spikes4" parent="." instance=ExtResource("9_o4epc")] +position = Vector2(56, 104) + +[node name="Spikes5" parent="." instance=ExtResource("9_o4epc")] +position = Vector2(40, 104) + +[node name="Spikes6" parent="." instance=ExtResource("9_o4epc")] +position = Vector2(24, 104) diff --git a/maps/tutorial.tscn b/maps/descent/tutorial.tscn similarity index 86% rename from maps/tutorial.tscn rename to maps/descent/tutorial.tscn index 45a2d8f..039b2dd 100644 --- a/maps/tutorial.tscn +++ b/maps/descent/tutorial.tscn @@ -1,12 +1,13 @@ -[gd_scene load_steps=10 format=3 uid="uid://byx8blpt2i8hx"] +[gd_scene load_steps=11 format=3 uid="uid://byx8blpt2i8hx"] [ext_resource type="Texture2D" uid="uid://d13tqqx8ygak4" path="res://assets/textures/backgrounds/hell.png" id="1_5dne7"] +[ext_resource type="Script" uid="uid://d3v13a4er2h1x" path="res://scripts/level/level.gd" id="1_8bygc"] [ext_resource type="Shader" uid="uid://cwktxks6mchp2" path="res://assets/shaders/noise.gdshader" id="2_els7d"] [ext_resource type="PackedScene" uid="uid://bwtpsjpe2lf7l" path="res://objects/player/player.tscn" id="3_imjpd"] [ext_resource type="TileSet" uid="uid://xwfn24if3pxk" path="res://assets/tilesets/chocomint.tres" id="4_1rmvv"] [ext_resource type="FontFile" uid="uid://dets0g4ce7npf" path="res://assets/fonts/Super Mario Bros. NES.ttf" id="5_ae2vf"] [ext_resource type="PackedScene" uid="uid://bhnse651bcybm" path="res://objects/end_door/end_door.tscn" id="6_yywag"] -[ext_resource type="PackedScene" uid="uid://cun6ov7vdfr6a" path="res://maps/yikes_spikes.tscn" id="7_0g05i"] +[ext_resource type="PackedScene" uid="uid://cun6ov7vdfr6a" path="res://maps/descent/yikes_spikes.tscn" id="7_0g05i"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_sf5kh"] @@ -16,7 +17,11 @@ shader_parameter/animate_noise = true shader_parameter/noise_intensity = 1.0 shader_parameter/fps = 15.0 -[node name="Level1" type="Node2D"] +[node name="Tutorial" type="Node2D"] +script = ExtResource("1_8bygc") +title = "Obligatory Tutorial Level" +id = "tutorial" +music = &"bug_music" [node name="Sprite2D" type="Sprite2D" parent="."] material = SubResource("ShaderMaterial_sf5kh") diff --git a/maps/yikes_more_spikes.tscn b/maps/descent/yikes_more_spikes.tscn similarity index 89% rename from maps/yikes_more_spikes.tscn rename to maps/descent/yikes_more_spikes.tscn index c7c142f..f133912 100644 --- a/maps/yikes_more_spikes.tscn +++ b/maps/descent/yikes_more_spikes.tscn @@ -1,12 +1,13 @@ -[gd_scene load_steps=11 format=3 uid="uid://hrrypch7psfa"] +[gd_scene load_steps=12 format=3 uid="uid://hrrypch7psfa"] [ext_resource type="Texture2D" uid="uid://d13tqqx8ygak4" path="res://assets/textures/backgrounds/hell.png" id="1_6i0lb"] +[ext_resource type="Script" uid="uid://d3v13a4er2h1x" path="res://scripts/level/level.gd" id="1_73lj3"] [ext_resource type="Shader" uid="uid://cwktxks6mchp2" path="res://assets/shaders/noise.gdshader" id="2_3dp43"] [ext_resource type="PackedScene" uid="uid://bwtpsjpe2lf7l" path="res://objects/player/player.tscn" id="3_mts2t"] [ext_resource type="TileSet" uid="uid://xwfn24if3pxk" path="res://assets/tilesets/chocomint.tres" id="4_evy0b"] [ext_resource type="FontFile" uid="uid://dets0g4ce7npf" path="res://assets/fonts/Super Mario Bros. NES.ttf" id="5_eo1kb"] [ext_resource type="PackedScene" uid="uid://bhnse651bcybm" path="res://objects/end_door/end_door.tscn" id="6_vvcgd"] -[ext_resource type="PackedScene" uid="uid://bd2srrfspy7ft" path="res://maps/its_spring.tscn" id="7_4f1b6"] +[ext_resource type="PackedScene" uid="uid://bd2srrfspy7ft" path="res://maps/descent/its_spring.tscn" id="7_4f1b6"] [ext_resource type="PackedScene" uid="uid://cnqmbq84hbnvj" path="res://objects/spikes/spikes.tscn" id="8_8qxg7"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_sf5kh"] @@ -17,7 +18,11 @@ shader_parameter/animate_noise = true shader_parameter/noise_intensity = 1.0 shader_parameter/fps = 15.0 -[node name="Level1" type="Node2D"] +[node name="YikesMoreSpikes" type="Node2D"] +script = ExtResource("1_73lj3") +title = "Yikes! More Spikes!" +id = "more-spikes" +order = 2 [node name="Sprite2D" type="Sprite2D" parent="."] material = SubResource("ShaderMaterial_sf5kh") diff --git a/maps/yikes_spikes.tscn b/maps/descent/yikes_spikes.tscn similarity index 88% rename from maps/yikes_spikes.tscn rename to maps/descent/yikes_spikes.tscn index c0f1f2f..847fa8f 100644 --- a/maps/yikes_spikes.tscn +++ b/maps/descent/yikes_spikes.tscn @@ -1,12 +1,13 @@ -[gd_scene load_steps=11 format=3 uid="uid://cun6ov7vdfr6a"] +[gd_scene load_steps=12 format=3 uid="uid://cun6ov7vdfr6a"] [ext_resource type="Texture2D" uid="uid://d13tqqx8ygak4" path="res://assets/textures/backgrounds/hell.png" id="1_588ks"] +[ext_resource type="Script" uid="uid://d3v13a4er2h1x" path="res://scripts/level/level.gd" id="1_3317b"] [ext_resource type="Shader" uid="uid://cwktxks6mchp2" path="res://assets/shaders/noise.gdshader" id="2_rvhjv"] [ext_resource type="PackedScene" uid="uid://bwtpsjpe2lf7l" path="res://objects/player/player.tscn" id="3_pdn7u"] [ext_resource type="TileSet" uid="uid://xwfn24if3pxk" path="res://assets/tilesets/chocomint.tres" id="4_pcxb3"] [ext_resource type="FontFile" uid="uid://dets0g4ce7npf" path="res://assets/fonts/Super Mario Bros. NES.ttf" id="5_bpruh"] [ext_resource type="PackedScene" uid="uid://bhnse651bcybm" path="res://objects/end_door/end_door.tscn" id="6_uyuca"] -[ext_resource type="PackedScene" uid="uid://hrrypch7psfa" path="res://maps/yikes_more_spikes.tscn" id="7_7rv68"] +[ext_resource type="PackedScene" uid="uid://hrrypch7psfa" path="res://maps/descent/yikes_more_spikes.tscn" id="7_7rv68"] [ext_resource type="PackedScene" uid="uid://cnqmbq84hbnvj" path="res://objects/spikes/spikes.tscn" id="7_y3eq7"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_sf5kh"] @@ -17,7 +18,11 @@ shader_parameter/animate_noise = true shader_parameter/noise_intensity = 1.0 shader_parameter/fps = 15.0 -[node name="Level1" type="Node2D"] +[node name="YikesSpikes" type="Node2D"] +script = ExtResource("1_3317b") +title = "Yikes! Spikes!" +id = "spikes" +order = 1 [node name="Sprite2D" type="Sprite2D" parent="."] material = SubResource("ShaderMaterial_sf5kh") diff --git a/maps/level1.tscn b/maps/level1.tscn index 58422e9..48df287 100644 --- a/maps/level1.tscn +++ b/maps/level1.tscn @@ -32,6 +32,13 @@ color = Color(0.194349, 0.194349, 0.194349, 0.447059) [node name="Player" parent="." instance=ExtResource("2_kip56")] position = Vector2(31, 139) +run_acceleration = 0.0 +max_run_speed = 0.0 +turn_acceleration = 0.0 +stopping_force = 0.0 +jump_power = 0.0 +splat_launch_power = 0.0 +splat_offset = 0.0 [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource("3_4td23") diff --git a/maps/level_z.tscn b/maps/level_z.tscn index 7e4ad2c..defe54d 100644 --- a/maps/level_z.tscn +++ b/maps/level_z.tscn @@ -1,29 +1,42 @@ -[gd_scene load_steps=6 format=4 uid="uid://cccb8wltupasj"] +[gd_scene load_steps=8 format=4 uid="uid://cccb8wltupasj"] [ext_resource type="Texture2D" uid="uid://b6a7l24y30iht" path="res://assets/textures/backgrounds/chocomint.png" id="1_h5jcm"] [ext_resource type="Script" uid="uid://d3v13a4er2h1x" path="res://scripts/level/level.gd" id="1_hcs1r"] [ext_resource type="TileSet" uid="uid://xwfn24if3pxk" path="res://assets/tilesets/chocomint.tres" id="2_dj7w1"] [ext_resource type="PackedScene" uid="uid://c8r040r4glui4" path="res://objects/enemies/lashy/lashy.tscn" id="4_gykx6"] [ext_resource type="PackedScene" uid="uid://bwtpsjpe2lf7l" path="res://objects/player/player.tscn" id="5_5v7mr"] +[ext_resource type="PackedScene" uid="uid://68lav5rke5ag" path="res://objects/spring/spring.tscn" id="6_tlqas"] +[ext_resource type="PackedScene" uid="uid://bwtjfpfkykfdr" path="res://objects/rotoboy/roto_boy.tscn" id="7_j1102"] [node name="LevelZ" type="Node2D"] script = ExtResource("1_hcs1r") title = "Test Level Z" id = "z-level" order = 2 +music = &"bug_music" [node name="Background" type="Sprite2D" parent="."] modulate = Color(0.996924, 0.421436, 0, 1) +z_index = -200 position = Vector2(144, 108) texture = ExtResource("1_h5jcm") [node name="TileMap" type="TileMapLayer" parent="."] +z_index = -100 use_parent_material = true -tile_map_data = PackedByteArray("AAAAAAsAAAAAAAAAAAABAAsAAAAAAAAAAAACAAsAAAAAAAAAAAAHAAsAAAAAAAAAAAAIAAsAAAAAAAAAAAAJAAsAAAAAAAAAAAAKAAsAAAAAAAAAAAALAAsAAAAAAAAAAAANAAsAAAAAAAAAAAAOAAsAAAAAAAAAAAAPAAsAAAAAAAAAAAAQAAsAAAAAAAAAAAARAAsAAAAAAAAAAAADAAsAAAAAAAAAAAAEAAsAAAAAAAAAAAAFAAsAAAAAAAAAAAAGAAsAAAAAAAAAAAAMAAsAAAAAAAAAAAAFAAoAAAAAAAAAAAAGAAoAAAAAAAAAAAAGAAkAAAAAAAAAAAAHAAkAAAAAAAAAAAAIAAkAAAAAAAAAAAAJAAkAAAAAAAAAAAAKAAkAAAAAAAAAAAALAAkAAAAAAAAAAAAMAAkAAAAAAAAAAAALAAoAAAAAAAAAAAAKAAoAAAAAAAAAAAAJAAoAAAAAAAAAAAAIAAoAAAAAAAAAAAAHAAoAAAAAAAAAAAAMAAoAAAAAAAAAAAANAAoAAAAAAAAAAAAOAAoAAAAAAAAAAAAPAAoAAAAAAAAAAAAPAAkAAAAAAAAAAAAQAAkAAAAAAAAAAAAQAAgAAAAAAAAAAAAQAAcAAAAAAAAAAAAQAAYAAAAAAAAAAAARAAcAAAAAAAAAAAAQAAoAAAAAAAAAAAARAAkAAAAAAAAAAAARAAgAAAAAAAAAAAARAAoAAAAAAAAAAAARAAYAAAAAAAAAAAARAAUAAAAAAAAAAAARAAQAAAAAAAAAAAAQAAQAAAAAAAAAAAAQAAUAAAAAAAAAAAAFAAkAAAAAAAAAAAAEAAkAAAAAAAAAAAADAAkAAAAAAAAAAAACAAkAAAAAAAAAAAABAAkAAAAAAAAAAAABAAoAAAAAAAAAAAACAAoAAAAAAAAAAAADAAoAAAAAAAAAAAAEAAoAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAkAAAAAAAAAAAA=") +tile_map_data = PackedByteArray("AAAAAAsAAAAAAAAAAAABAAsAAAAAAAAAAAACAAsAAAAAAAAAAAAHAAsAAAAAAAAAAAAIAAsAAAAAAAAAAAAJAAsAAAAAAAAAAAAKAAsAAAAAAAAAAAALAAsAAAAAAAAAAAANAAsAAAAAAAAAAAAOAAsAAAAAAAAAAAAPAAsAAAAAAAAAAAAQAAsAAAAAAAAAAAARAAsAAAAAAAAAAAADAAsAAAAAAAAAAAAEAAsAAAAAAAAAAAAFAAsAAAAAAAAAAAAGAAsAAAAAAAAAAAAMAAsAAAAAAAAAAAAFAAoAAAAAAAAAAAAGAAoAAAAAAAAAAAAGAAkAAAAAAAAAAAAHAAkAAAAAAAAAAAAIAAkAAAAAAAAAAAAJAAkAAAAAAAAAAAAKAAkAAAAAAAAAAAALAAkAAAAAAAAAAAAMAAkAAAAAAAAAAAALAAoAAAAAAAAAAAAKAAoAAAAAAAAAAAAJAAoAAAAAAAAAAAAIAAoAAAAAAAAAAAAHAAoAAAAAAAAAAAAMAAoAAAAAAAAAAAANAAoAAAAAAAAAAAAOAAoAAAAAAAAAAAAPAAoAAAAAAAAAAAAPAAkAAAAAAAAAAAAQAAkAAAAAAAAAAAAQAAoAAAAAAAAAAAARAAkAAAAAAAAAAAARAAoAAAAAAAAAAAAFAAkAAAAAAAAAAAAEAAkAAAAAAAAAAAADAAkAAAAAAAAAAAACAAkAAAAAAAAAAAABAAkAAAAAAAAAAAABAAoAAAAAAAAAAAACAAoAAAAAAAAAAAADAAoAAAAAAAAAAAAEAAoAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAkAAAAAAAAAAAABAAgAAAAAAAAAAAABAAcAAAAAAAAAAAABAAYAAAAAAAAAAAABAAUAAAAAAAAAAAABAAQAAAAAAAAAAAABAAMAAAAAAAAAAAABAAIAAAAAAAAAAAANAAkAAAAAAAAAAAAOAAkAAAAAAAAAAAAFAAYAAAAAAAAAAAAFAAUAAAAAAAAAAAAFAAQAAAAAAAAAAAAFAAMAAAAAAAAAAAAFAAIAAAAAAAAAAAAFAAEAAAAAAAAAAAABAAEAAAAAAAAAAAABAAAAAAAAAAAAAAABAP//AAAAAAAAAAABAP7/AAAAAAAAAAABAP3/AAAAAAAAAAACAP3/AAAAAAAAAAADAP3/AAAAAAAAAAAEAP3/AAAAAAAAAAAFAP3/AAAAAAAAAAAGAP3/AAAAAAAAAAAHAP3/AAAAAAAAAAAIAP3/AAAAAAAAAAAJAP3/AAAAAAAAAAAKAAgAAAAAAAAAAAAKAAcAAAAAAAAAAAALAAcAAAAAAAAAAAALAAgAAAAAAAAAAAAMAAYAAAAAAAAAAAAMAAUAAAAAAAAAAAAMAAQAAAAAAAAAAAANAAQAAAAAAAAAAAANAAUAAAAAAAAAAAANAAYAAAAAAAAAAAANAAcAAAAAAAAAAAANAAgAAAAAAAAAAAAMAAgAAAAAAAAAAAAMAAcAAAAAAAAAAAAOAAQAAAAAAAAAAAAOAAUAAAAAAAAAAAAOAAYAAAAAAAAAAAAOAAcAAAAAAAAAAAAOAAgAAAAAAAAAAAA=") tile_set = ExtResource("2_dj7w1") [node name="Lashy" parent="." instance=ExtResource("4_gykx6")] -position = Vector2(141, 99) +position = Vector2(272, 104) +launch_power = 300.0 +idle_radius = 6.0 [node name="Player" parent="." instance=ExtResource("5_5v7mr")] -position = Vector2(40, 144) +position = Vector2(96, 136) + +[node name="Spring" parent="." instance=ExtResource("6_tlqas")] +position = Vector2(256, 144) + +[node name="RotoBoy" parent="." instance=ExtResource("7_j1102")] +position = Vector2(240, 40) diff --git a/objects/effects/bouncing_spark.gd b/objects/effects/bouncing_spark.gd new file mode 100644 index 0000000..e66c818 --- /dev/null +++ b/objects/effects/bouncing_spark.gd @@ -0,0 +1,35 @@ +extends RigidBody2D + + +@export var scale_min: float +@export var scale_max: float +@export var velocity_min: float +@export var velocity_max: float +@export_custom(0, "radians_as_degrees") var spin_min: float +@export_custom(0, "radians_as_degrees") var spin_max: float +@export var decay_speed_threshold: float +@export var decay_time: float + + +var _tween: Tween = null + + +func _ready() -> void: + var rnd_scale = randf_range(scale_min, scale_max) + $Sprite2D.scale = Vector2.ONE * rnd_scale + + linear_velocity = Vector2.from_angle(randf() * TAU) * randf_range(velocity_min, velocity_max) + angular_velocity = randf_range(spin_min, spin_max) + + +func _physics_process(delta: float) -> void: + if linear_velocity.length() <= decay_speed_threshold: + if _tween: + return + _tween = create_tween().set_process_mode(Tween.TWEEN_PROCESS_PHYSICS) + _tween.tween_property(self, ^"scale", Vector2.ZERO, decay_time) + _tween.tween_callback(queue_free) + + +func _on_solid_detector_body_entered(body: Node2D) -> void: + print("BLEP") diff --git a/objects/effects/bouncing_spark.gd.uid b/objects/effects/bouncing_spark.gd.uid new file mode 100644 index 0000000..48a2682 --- /dev/null +++ b/objects/effects/bouncing_spark.gd.uid @@ -0,0 +1 @@ +uid://b6krgij5xfu1w diff --git a/objects/effects/bouncing_spark.tscn b/objects/effects/bouncing_spark.tscn new file mode 100644 index 0000000..8eeb0ec --- /dev/null +++ b/objects/effects/bouncing_spark.tscn @@ -0,0 +1,57 @@ +[gd_scene load_steps=8 format=3 uid="uid://djdpcsmms727b"] + +[ext_resource type="Script" uid="uid://b6krgij5xfu1w" path="res://objects/effects/bouncing_spark.gd" id="1_62ynp"] +[ext_resource type="Texture2D" uid="uid://rhc3c5j1lfw" path="res://assets/textures/effects/spark.png" id="1_ag5ij"] +[ext_resource type="AudioStream" uid="uid://cmvbwm6gk8n6b" path="res://assets/audio/sfx/spark_bounce.ogg" id="3_4uvf2"] + +[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_62ynp"] +bounce = 0.8 + +[sub_resource type="CircleShape2D" id="CircleShape2D_4uvf2"] +radius = 2.0 + +[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_us66k"] +random_pitch = 1.25 +streams_count = 1 +stream_0/stream = ExtResource("3_4uvf2") + +[sub_resource type="CircleShape2D" id="CircleShape2D_us66k"] +radius = 6.0 + +[node name="Spark" type="RigidBody2D"] +z_index = -10 +collision_layer = 0 +collision_mask = 3 +mass = 0.1 +physics_material_override = SubResource("PhysicsMaterial_62ynp") +gravity_scale = 0.25 +linear_damp = 0.3 +script = ExtResource("1_62ynp") +scale_min = 0.5 +scale_max = 1.0 +velocity_min = 40.0 +velocity_max = 80.0 +spin_min = -1.5708 +spin_max = 1.5708 +decay_speed_threshold = 15.0 +decay_time = 0.2 + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_ag5ij") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("CircleShape2D_4uvf2") + +[node name="BounceSound" type="AudioStreamPlayer2D" parent="."] +stream = SubResource("AudioStreamRandomizer_us66k") +bus = &"Sound Effects" + +[node name="SolidDetector" type="Area2D" parent="."] +collision_layer = 0 +collision_mask = 3 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="SolidDetector"] +shape = SubResource("CircleShape2D_us66k") + +[connection signal="body_entered" from="SolidDetector" to="." method="_on_solid_detector_body_entered"] +[connection signal="body_entered" from="SolidDetector" to="BounceSound" method="play" unbinds=1] diff --git a/objects/end_door/end_door.gd b/objects/end_door/end_door.gd index ece7293..e9d73f0 100644 --- a/objects/end_door/end_door.gd +++ b/objects/end_door/end_door.gd @@ -1,18 +1,13 @@ extends Node2D -@export var next_map:PackedScene -# Called when the node enters the scene tree for the first time. -func _ready() -> void: - pass # Replace with function body. +signal door_entered() -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass +@export var next_map: PackedScene -func _on_area_2d_body_entered(body: Node2D) -> void: +func _on_player_detector_body_entered(body: Node2D) -> void: if body is Player: - SceneManager.current_scene = next_map.instantiate() - SceneManager.win_sound.play() + door_entered.emit() + Levels.advance_level() diff --git a/objects/end_door/end_door.tscn b/objects/end_door/end_door.tscn index 858971d..8976ee9 100644 --- a/objects/end_door/end_door.tscn +++ b/objects/end_door/end_door.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=4 format=3 uid="uid://bhnse651bcybm"] +[gd_scene load_steps=5 format=3 uid="uid://bhnse651bcybm"] [ext_resource type="Texture2D" uid="uid://bwq21el575t1g" path="res://assets/textures/door/door.png" id="1_4beu0"] [ext_resource type="Script" uid="uid://b3ynfi0yyc7t5" path="res://objects/end_door/end_door.gd" id="1_ph88k"] +[ext_resource type="Script" uid="uid://cg3hwyafaokvs" path="res://scripts/global_sound_player/global_sound_player.gd" id="3_8mj78"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_qkffx"] size = Vector2(16, 16) @@ -12,11 +13,18 @@ script = ExtResource("1_ph88k") [node name="Sprite2D" type="Sprite2D" parent="."] texture = ExtResource("1_4beu0") -[node name="Area2D" type="Area2D" parent="."] +[node name="PlayerDetector" type="Area2D" parent="."] collision_mask = 16 +monitorable = false -[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +[node name="CollisionShape2D" type="CollisionShape2D" parent="PlayerDetector"] shape = SubResource("RectangleShape2D_qkffx") debug_color = Color(0, 1, 0.701961, 0.419608) -[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"] +[node name="GlobalSoundPlayer" type="Node" parent="."] +script = ExtResource("3_8mj78") +sound = &"WinSound" +metadata/_custom_type_script = "uid://cg3hwyafaokvs" + +[connection signal="door_entered" from="." to="GlobalSoundPlayer" method="play"] +[connection signal="body_entered" from="PlayerDetector" to="." method="_on_player_detector_body_entered"] diff --git a/objects/enemies/lashy/blast_star.tscn b/objects/enemies/lashy/blast_star.tscn new file mode 100644 index 0000000..60b2b16 --- /dev/null +++ b/objects/enemies/lashy/blast_star.tscn @@ -0,0 +1,91 @@ +[gd_scene load_steps=5 format=3 uid="uid://bcgj0wb1ra11e"] + +[ext_resource type="Texture2D" uid="uid://350f21o7jrwq" path="res://assets/textures/effects/star.png" id="1_1xc4y"] + +[sub_resource type="Animation" id="Animation_6qf6s"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D: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)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:rotation") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} + +[sub_resource type="Animation" id="Animation_1xc4y"] +resource_name = "blast" +length = 0.3 +step = 0.1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:scale") +tracks/0/interp = 2 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.1, 0.3), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [Vector2(1e-05, 1e-05), Vector2(1.5, 1.5), Vector2(1e-05, 1e-05)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:rotation") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.0, 1.5708] +} +tracks/2/type = "method" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath(".") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0.3), +"transitions": PackedFloat32Array(1), +"values": [{ +"args": [], +"method": &"queue_free" +}] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_kd46a"] +_data = { +&"RESET": SubResource("Animation_6qf6s"), +&"blast": SubResource("Animation_1xc4y") +} + +[node name="BlastStar" type="Node2D"] +z_index = -1 + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_1xc4y") + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +&"": SubResource("AnimationLibrary_kd46a") +} +autoplay = "blast" diff --git a/objects/enemies/lashy/lashy.gd b/objects/enemies/lashy/lashy.gd index 4991781..646e017 100644 --- a/objects/enemies/lashy/lashy.gd +++ b/objects/enemies/lashy/lashy.gd @@ -2,82 +2,73 @@ extends Node2D -enum State { - IDLE, - WINDING_UP, - ATTACK, - RECOVER, -} +@export var launch_power: float +@export var idle_radius: float +@export var draw_back_distance: float +@export var smash_distance: float -@export var idle_distance: float -@export_custom(PROPERTY_HINT_NONE, "radians_as_degrees") -var idle_rotate_speed: float - -@export var wind_up_time: float -@export var wind_up_distance: float - -@export var attack_time: float -@export var attack_distance: float - -@export var recover_time: float - -@export_range(0,1,1,"or_greater") var detection_radius: float: - set(value): - detection_radius = value - if not is_inside_tree(): - await tree_entered - var shape = detector_shape.shape as CircleShape2D - if shape: - shape.radius = detection_radius +@export_group("Timing", "time_") +@export var time_draw_back: float +@export var time_smash: float +@export var time_recover: float @export_group("Internal References") +@export var smash_effect: PackedScene @export var head: Node2D -@export var head_pivot: Node2D -@export var detector_shape: CollisionShape2D -var state: State = State.IDLE -var tween: Tween = null -var tracked_player: Player = null -var idle_angle: float = 0.0 -var target_pos: Vector2 = Vector2.ZERO -var progress: float = 0.0 - - -func _process(delta: float) -> void: - if Engine.is_editor_hint(): - return - - match state: - State.IDLE: - idle_angle = fposmod(idle_angle + idle_rotate_speed * delta, TAU) - head_pivot.rotation = idle_angle - State.WINDING_UP: - target_pos = tracked_player.global_position - var angle = (global_position - target_pos).angle() - progress += delta / wind_up_time - head_pivot.rotation = lerp_angle(head_pivot.rotation, angle, progress) - State.RECOVER: - progress += delta / recover_time - head_pivot.rotation = lerp_angle(head_pivot.rotation, idle_angle, progress) +var _player: Player = null +var _tween: Tween = null +var _go_again: bool = false func _start_attack() -> void: - state = State.WINDING_UP - if tween: - tween.kill() - tween = create_tween().set_process_mode(Tween.TWEEN_PROCESS_PHYSICS) - tween.tween_property(head, ^"position:x", wind_up_distance, wind_up_time) - tween.tween_property(self, ^"state", State.ATTACK, 0.0) - tween.tween_property(head, ^"position:x", -attack_distance, attack_time).set_trans(Tween.TRANS_BOUNCE) - tween.tween_property(self, ^"state", State.RECOVER, 0.0) - tween.tween_property(head, ^"position:x", idle_distance, recover_time) - tween.tween_property(self, ^"state", State.IDLE, 0.0) + # do nothing if already doing animation or player gone + if not _go_again or (_tween and _tween.is_running()): + return + + var effect = smash_effect.instantiate() as Node2D + effect.position = to_local(_player.global_position) + effect.rotation = randf() * TAU + + _tween = create_tween().set_process_mode(Tween.TWEEN_PROCESS_PHYSICS) + # launch player + _tween.tween_callback(_player.launch.bind( + global_position.direction_to(_player.global_position) * launch_power + )) + # spawn smash effect + _tween.tween_callback(add_child.bind(effect)) + # draw back away from player + _tween.tween_property(head.material, ^"shader_parameter/radius", 0.0, 0.1) + _tween.parallel().tween_method(_move_facing_player, 0.0, -draw_back_distance, time_draw_back)\ + .set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) + # smash towards player + _tween.tween_method(_move_facing_player, -draw_back_distance, smash_distance, time_smash)\ + .set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_ELASTIC) + # return to center + _tween.tween_method(_move_facing_player, smash_distance, 0.0, time_recover)\ + .set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BOUNCE) + _tween.tween_property(head.material, ^"shader_parameter/radius", idle_radius, 0.1) + _tween.tween_callback(_start_attack.call_deferred) + + +## move head this disatance from (0,0) towards (or away if negative) from player +func _move_facing_player(distance: float) -> void: + if not _player: + return + + var dir = global_position.direction_to(_player.global_position) + head.position = dir * distance func _on_player_detector_body_entered(body: Node2D) -> void: if body is Player: - if state == State.IDLE: - tracked_player = body - _start_attack() + _player = body + _go_again = true + _start_attack() + + +func _on_player_detector_body_exited(body: Node2D) -> void: + if body is Player: + _go_again = false diff --git a/objects/enemies/lashy/lashy.tscn b/objects/enemies/lashy/lashy.tscn index 6124073..83155fa 100644 --- a/objects/enemies/lashy/lashy.tscn +++ b/objects/enemies/lashy/lashy.tscn @@ -1,31 +1,34 @@ -[gd_scene load_steps=8 format=3 uid="uid://c8r040r4glui4"] +[gd_scene load_steps=10 format=3 uid="uid://c8r040r4glui4"] [ext_resource type="Script" uid="uid://lxppe1op1240" path="res://objects/enemies/lashy/lashy.gd" id="1_34o54"] [ext_resource type="Texture2D" uid="uid://cm4cantqbhkwx" path="res://assets/textures/enemies/lashy/lashy_anchor.png" id="2_8ls3k"] +[ext_resource type="PackedScene" uid="uid://bcgj0wb1ra11e" path="res://objects/enemies/lashy/blast_star.tscn" id="2_42oum"] [ext_resource type="Script" uid="uid://bt4bdjyekgh53" path="res://scripts/ball_snake/ball_snake.gd" id="3_8edxw"] [ext_resource type="Texture2D" uid="uid://gnkke4rr0wcr" path="res://assets/textures/enemies/lashy/lashy_body.png" id="4_xnkdk"] [ext_resource type="Texture2D" uid="uid://bf0i64q2dw0au" path="res://assets/textures/enemies/lashy/lashy_head.png" id="5_b5g1y"] +[ext_resource type="Shader" uid="uid://bc8j5jyjynbca" path="res://assets/shaders/orbit.gdshader" id="5_dkkk6"] [sub_resource type="CircleShape2D" id="CircleShape2D_woon5"] resource_local_to_scene = true -radius = 64.0 +radius = 32.0 -[sub_resource type="CircleShape2D" id="CircleShape2D_g5iss"] -radius = 6.0 +[sub_resource type="ShaderMaterial" id="ShaderMaterial_42oum"] +resource_local_to_scene = true +shader = ExtResource("5_dkkk6") +shader_parameter/radius = 6.0 +shader_parameter/speed = 3.142 -[node name="Lashy" type="Node2D" node_paths=PackedStringArray("head", "head_pivot", "detector_shape")] +[node name="Lashy" type="Node2D" node_paths=PackedStringArray("head")] script = ExtResource("1_34o54") -idle_distance = 16.0 -idle_rotate_speed = 1.5708 -wind_up_time = 2.0 -wind_up_distance = 32.0 -attack_time = 0.5 -attack_distance = 64.0 -recover_time = 2.0 -detection_radius = 64.0 -head = NodePath("HeadPivot/Head") -head_pivot = NodePath("HeadPivot") -detector_shape = NodePath("PlayerDetector/DetectorShape") +launch_power = 240.0 +idle_radius = 4.0 +draw_back_distance = 24.0 +smash_distance = 32.0 +time_draw_back = 0.1 +time_smash = 0.2 +time_recover = 0.1 +smash_effect = ExtResource("2_42oum") +head = NodePath("Head") [node name="PlayerDetector" type="Area2D" parent="."] collision_layer = 0 @@ -39,34 +42,18 @@ debug_color = Color(0.752941, 0.196078, 1, 0.25098) [node name="Anchor" type="Sprite2D" parent="."] texture = ExtResource("2_8ls3k") -[node name="BallSnake" type="Node2D" parent="." node_paths=PackedStringArray("target")] +[node name="BallSnake" type="Node2D" parent="Anchor" node_paths=PackedStringArray("target")] script = ExtResource("3_8edxw") texture = ExtResource("4_xnkdk") -target = NodePath("../HeadPivot/Head") -segments = 2 +target = NodePath("../../Head") +segments = -1 head_segment = false -tail_segment = true auto_density = true pixels_per_segment = 5.0 -[node name="HeadSprite" type="Sprite2D" parent="."] -position = Vector2(-5.79198e-05, -16) +[node name="Head" type="Sprite2D" parent="."] +material = SubResource("ShaderMaterial_42oum") texture = ExtResource("5_b5g1y") -[node name="HeadPivot" type="Node2D" parent="."] -rotation = -1.5708 - -[node name="Head" type="Area2D" parent="HeadPivot"] -position = Vector2(16, 0) -metadata/_edit_group_ = true - -[node name="CollisionShape2D" type="CollisionShape2D" parent="HeadPivot/Head"] -shape = SubResource("CircleShape2D_g5iss") -debug_color = Color(1, 0, 0, 0.419608) - -[node name="RemoteTransform2D" type="RemoteTransform2D" parent="HeadPivot/Head"] -remote_path = NodePath("../../../HeadSprite") -update_rotation = false -update_scale = false - [connection signal="body_entered" from="PlayerDetector" to="." method="_on_player_detector_body_entered"] +[connection signal="body_exited" from="PlayerDetector" to="." method="_on_player_detector_body_exited"] diff --git a/objects/ice/ice.gd b/objects/ice/ice.gd index c061843..33292e2 100644 --- a/objects/ice/ice.gd +++ b/objects/ice/ice.gd @@ -1,20 +1,18 @@ extends Node2D -# Called when the node enters the scene tree for the first time. -func _ready() -> void: - pass # Replace with function body. +var _player: Player = null -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass +func _physics_process(delta: float) -> void: + _player.state_chart.send_event(&"touched_ice") -func _on_area_2d_body_entered(body: Node2D) -> void: +func _on_player_detector_body_entered(body: Node2D) -> void: if body is Player: - body.ices_touched += 1 + _player = body -func _on_area_2d_body_exited(body: Node2D) -> void: - body.ices_touched -= 1 +func _on_player_detector_body_exited(body: Node2D) -> void: + if body == _player: + _player = null diff --git a/objects/ice/ice.tscn b/objects/ice/ice.tscn index b979059..4d473b7 100644 --- a/objects/ice/ice.tscn +++ b/objects/ice/ice.tscn @@ -12,23 +12,24 @@ size = Vector2(16, 16) [node name="Ice" type="Node2D"] script = ExtResource("1_hgdc3") -[node name="Sprite2D" type="Sprite2D" parent="."] -texture = ExtResource("1_0p7ug") - -[node name="Area2D" type="Area2D" parent="."] +[node name="PlayerDetector" type="Area2D" parent="."] collision_layer = 0 collision_mask = 16 +monitorable = false -[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +[node name="CollisionShape2D" type="CollisionShape2D" parent="PlayerDetector"] position = Vector2(0, -0.5) shape = SubResource("RectangleShape2D_sv4q1") [node name="StaticBody2D" type="StaticBody2D" parent="."] collision_layer = 2 -collision_mask = 16 +collision_mask = 0 [node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D"] shape = SubResource("RectangleShape2D_xodyg") -[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"] -[connection signal="body_exited" from="Area2D" to="." method="_on_area_2d_body_exited"] +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_0p7ug") + +[connection signal="body_entered" from="PlayerDetector" to="." method="_on_player_detector_body_entered"] +[connection signal="body_exited" from="PlayerDetector" to="." method="_on_player_detector_body_exited"] diff --git a/objects/player/player.gd b/objects/player/player.gd index edd2994..8bf6459 100644 --- a/objects/player/player.gd +++ b/objects/player/player.gd @@ -8,15 +8,34 @@ extends CharacterBody2D @export var turn_acceleration: float @export var stopping_force: float +@export_group("Bonk") +@export var bonk_speed_threshold: float +@export var bonk_power: float +@export var bonk_effect_count: int +@export var bonk_effect_scene: PackedScene + @export_group("Air Movement") @export var gravity: float +@export var fast_gravity: float @export var jump_power: float +@export var jump_horizontal_boost: float +@export var splat_launch_power: float +@export var splat_offset: float +@export var chomp_vault_impulse: Vector2 @export_group("Internal References") @export var state_chart: StateChart @export var graphics: Node2D @export var run_animation: SpritesheetAnimation +@export var wall_cast: ShapeCast2D +@export var corner_cast: RayCast2D +@export var corner_height_cast: RayCast2D +@export var corner_snap_point: Node2D +@export var vault_off_point: Node2D + +@export var bonk_effect_point: Node2D + @onready var start_position: Vector2 = global_position @@ -26,8 +45,13 @@ var input_dir: Vector2 = Vector2.ZERO: input_dir = value.sign() state_chart.set_expression_property(&"input_dir", input_dir) +var _last_velocity: Vector2 = Vector2.ZERO +var _splat_normal: Vector2 = Vector2.ZERO +var _bonk_cancel_velocity: Vector2 = Vector2.ZERO + func _physics_process(delta: float) -> void: + _last_velocity = velocity move_and_slide() state_chart.set_expression_property(&"velocity", velocity) if velocity.x != 0.0: @@ -43,6 +67,10 @@ func _physics_process(delta: float) -> void: func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed(&"jump"): state_chart.send_event(&"jump_pressed") + if event.is_action_pressed(&"grab"): + state_chart.send_event(&"grab_pressed") + if event.is_action_released(&"grab"): + state_chart.send_event(&"grab_released") func kill() -> void: @@ -75,24 +103,101 @@ func _apply_turn_acceleration(delta: float) -> void: #endregion +#region Bonk +func _check_for_bonk(_delta: float) -> void: + if absf(velocity.x) >= bonk_speed_threshold: + wall_cast.force_shapecast_update() + if wall_cast.is_colliding(): + state_chart.send_event(&"bonked") + +func _enter_bonk() -> void: + _bonk_cancel_velocity = velocity * Vector2(-1.0, 1.0) # horizontally inverted velocity + velocity = Vector2.ZERO + +func _cancel_bonk() -> void: + velocity = _bonk_cancel_velocity + +func _apply_bonk() -> void: + velocity.x = signf(_bonk_cancel_velocity.x) * bonk_power + for _i in bonk_effect_count: + var effect_instance = bonk_effect_scene.instantiate() + effect_instance.global_position = global_position + get_parent().add_child(effect_instance) +#endregion + + #region Falling func _apply_gravity(delta: float) -> void: - velocity.y += gravity * delta + if input_dir.y > 0.0: + velocity.y += fast_gravity * delta + else: + velocity.y += gravity * delta #endregion #region Jumping func _start_jump() -> void: velocity.y = -jump_power + velocity.x += input_dir.x * jump_horizontal_boost +#endregion + + +#region ChompVault +func _check_for_corner(_delta: float) -> void: + if signf(input_dir.x) == signf(graphics.scale.x): + corner_cast.force_raycast_update() + if not corner_cast.is_colliding(): + wall_cast.force_shapecast_update() + if wall_cast.is_colliding(): + state_chart.send_event(&"corner_detected") + +func _start_chomp_vault() -> void: + corner_height_cast.force_raycast_update() + global_position.x = wall_cast.get_collision_point(0).x + global_position.y = corner_height_cast.get_collision_point().y + global_position -= to_local(corner_snap_point.global_position) + velocity = Vector2.ZERO + +func _end_chomp_vault() -> void: + global_position += to_local(corner_snap_point.global_position) + global_position -= to_local(vault_off_point.global_position) + velocity = chomp_vault_impulse + velocity.x *= signf(graphics.scale.x) #endregion #region Missile +func _restore_graphics_rotation() -> void: + graphics.rotation = 0.0 + + func _face_towards_velocity(_delta: float) -> void: graphics.rotation = Vector2(graphics.scale.x, 0.0).angle_to(velocity) -func _restore_graphics_rotation() -> void: - graphics.rotation = 0.0 +func _check_for_splat(delta: float) -> void: + var col = move_and_collide(_last_velocity * delta, true) + if col: + _splat_normal = col.get_normal() + if _splat_normal.dot(Vector2.UP) > 0.5: + return + velocity = Vector2.ZERO + global_position += col.get_travel() + var angle = col.get_normal().angle() + if graphics.scale.x > 0.0: + angle += PI + graphics.set_deferred(&"rotation", angle) + state_chart.send_event(&"splatted") +#endregion + + +#region Splatting +func _do_splat_launch() -> void: + var dir = input_dir.project(_splat_normal.orthogonal()).normalized() + if dir == Vector2.ZERO: + dir = _splat_normal + dir = dir.rotated(dir.angle_to(_splat_normal) * 0.5) + + launch(dir * splat_launch_power) #endregion @@ -100,4 +205,6 @@ func _restore_graphics_rotation() -> void: func _reset_position() -> void: global_position = start_position velocity = Vector2.ZERO + graphics.scale.x = 1.0 + graphics.rotation = 0.0 #endregion diff --git a/objects/player/player.tscn b/objects/player/player.tscn index c08bdcd..c101986 100644 --- a/objects/player/player.tscn +++ b/objects/player/player.tscn @@ -1,19 +1,60 @@ -[gd_scene load_steps=21 format=3 uid="uid://bwtpsjpe2lf7l"] +[gd_scene load_steps=37 format=3 uid="uid://bwtpsjpe2lf7l"] [ext_resource type="Script" uid="uid://dhyi4yn0xleoy" path="res://objects/player/player.gd" id="1_xs4s5"] +[ext_resource type="PackedScene" uid="uid://djdpcsmms727b" path="res://objects/effects/bouncing_spark.tscn" id="2_28utn"] [ext_resource type="Texture2D" uid="uid://c71nqfyw4a3v4" path="res://assets/textures/player/capri.png" id="3_trcll"] [ext_resource type="Script" uid="uid://cv55s54clajw5" path="res://scripts/spritesheet_animation/spritesheet_animation.gd" id="4_bsdw5"] +[ext_resource type="AudioStream" uid="uid://4kxio0mlrr4k" path="res://assets/audio/vox/capri_jump2.ogg" id="5_45urx"] [ext_resource type="Script" uid="uid://bhrh1qkv7nlyl" path="res://addons/godot_state_charts/state_chart.gd" id="5_bcjtl"] [ext_resource type="AudioStream" uid="uid://dfa1ev73rsc7g" path="res://assets/audio/vox/capri_die.ogg" id="5_bi5m7"] +[ext_resource type="AudioStream" uid="uid://c350jqy4yue8c" path="res://assets/audio/vox/capri_jump3.ogg" id="6_c34wb"] [ext_resource type="Script" uid="uid://b11v7h3ny6kh1" path="res://addons/godot_state_charts/compound_state.gd" id="6_jnxnd"] [ext_resource type="Script" uid="uid://rrj3six8lu8p" path="res://addons/godot_state_charts/transition.gd" id="7_rgjdc"] [ext_resource type="Script" uid="uid://b6u7unac5srh0" path="res://addons/godot_state_charts/expression_guard.gd" id="8_8i2im"] +[ext_resource type="AudioStream" uid="uid://cxfl2cqlre0ma" path="res://assets/audio/vox/capri_die2.ogg" id="8_45rsp"] [ext_resource type="AudioStream" uid="uid://7be7ts3rdegh" path="res://assets/audio/vox/capri_jump.ogg" id="9_8c74o"] +[ext_resource type="AudioStream" uid="uid://c6gck1lyk6aer" path="res://assets/audio/vox/capri_die3.ogg" id="9_ylcck"] [ext_resource type="Script" uid="uid://cyvphy8py4ntr" path="res://addons/godot_state_charts/atomic_state.gd" id="10_mvu25"] +[ext_resource type="AudioStream" uid="uid://cquhska140wrt" path="res://assets/audio/vox/capri_whee.ogg" id="10_xlkbi"] +[ext_resource type="AudioStream" uid="uid://e3ptgegyv17" path="res://assets/audio/vox/capri_whee2.ogg" id="11_l55sg"] +[ext_resource type="AudioStream" uid="uid://bauqpxusk0p1i" path="res://assets/audio/vox/capri_whee3.ogg" id="12_28utn"] +[ext_resource type="AudioStream" uid="uid://bhr0uvens076m" path="res://assets/audio/sfx/se_turn2.ogg" id="13_yyeqs"] +[ext_resource type="AudioStream" uid="uid://c7b60nylv85rw" path="res://assets/audio/sfx/se_Attack.wav" id="14_l55sg"] [sub_resource type="CircleShape2D" id="CircleShape2D_tvyy1"] radius = 6.0 +[sub_resource type="RectangleShape2D" id="RectangleShape2D_l55sg"] +size = Vector2(4, 5) + +[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_45rsp"] +streams_count = 3 +stream_0/stream = ExtResource("9_8c74o") +stream_1/stream = ExtResource("5_45urx") +stream_2/stream = ExtResource("6_c34wb") + +[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_x5bgp"] +streams_count = 3 +stream_0/stream = ExtResource("5_bi5m7") +stream_1/stream = ExtResource("8_45rsp") +stream_2/stream = ExtResource("9_ylcck") + +[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_u8bnf"] +streams_count = 3 +stream_0/stream = ExtResource("10_xlkbi") +stream_1/stream = ExtResource("11_l55sg") +stream_2/stream = ExtResource("12_28utn") + +[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_lc6id"] +random_pitch = 1.1 +streams_count = 1 +stream_0/stream = ExtResource("13_yyeqs") + +[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_28utn"] +random_pitch = 1.1 +streams_count = 1 +stream_0/stream = ExtResource("14_l55sg") + [sub_resource type="Resource" id="Resource_sfpnl"] resource_name = "Not On Floor" script = ExtResource("8_8i2im") @@ -68,7 +109,7 @@ script = ExtResource("8_8i2im") expression = "velocity.y > 0.0" metadata/_custom_type_script = "uid://b6u7unac5srh0" -[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("state_chart", "graphics", "run_animation")] +[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("state_chart", "graphics", "run_animation", "wall_cast", "corner_cast", "corner_height_cast", "corner_snap_point", "vault_off_point", "bonk_effect_point")] collision_layer = 16 collision_mask = 3 floor_snap_length = 3.0 @@ -76,25 +117,38 @@ script = ExtResource("1_xs4s5") run_acceleration = 200.0 max_run_speed = 100.0 turn_acceleration = 300.0 -stopping_force = 200.0 +stopping_force = 250.0 +bonk_speed_threshold = 75.0 +bonk_power = 100.0 +bonk_effect_count = 3 +bonk_effect_scene = ExtResource("2_28utn") gravity = 450.0 +fast_gravity = 675.0 jump_power = 180.0 +jump_horizontal_boost = 25.0 +splat_launch_power = 240.0 +splat_offset = 6.0 +chomp_vault_impulse = Vector2(60, -60) state_chart = NodePath("StateChart") graphics = NodePath("Graphics") run_animation = NodePath("Graphics/Sprite/Run") +wall_cast = NodePath("Graphics/CornerDetector/WallCast") +corner_cast = NodePath("Graphics/CornerDetector/CornerCast") +corner_height_cast = NodePath("Graphics/CornerDetector/CornerHeightCast") +corner_snap_point = NodePath("Graphics/CornerDetector/CornerSnapPoint") +vault_off_point = NodePath("Graphics/CornerDetector/VaultOffPoint") +bonk_effect_point = NodePath("Graphics/SparksPoint") [node name="CollisionShape" type="CollisionShape2D" parent="."] -position = Vector2(0, -6) shape = SubResource("CircleShape2D_tvyy1") debug_color = Color(3.32102e-06, 0.648976, 0.161954, 0.42) [node name="Graphics" type="Node2D" parent="."] -position = Vector2(0, -6) [node name="Sprite" type="Sprite2D" parent="Graphics"] texture = ExtResource("3_trcll") offset = Vector2(0, -2) -hframes = 4 +hframes = 8 vframes = 4 region_rect = Rect2(0, 0, 64, 64) @@ -105,6 +159,14 @@ script = ExtResource("4_bsdw5") script = ExtResource("4_bsdw5") first_frame = Vector2i(1, 0) +[node name="Bonk" type="Node" parent="Graphics/Sprite"] +script = ExtResource("4_bsdw5") +first_frame = Vector2i(3, 0) + +[node name="StunnedFall" type="Node" parent="Graphics/Sprite"] +script = ExtResource("4_bsdw5") +first_frame = Vector2i(3, 2) + [node name="Skid" type="Node" parent="Graphics/Sprite"] script = ExtResource("4_bsdw5") first_frame = Vector2i(2, 0) @@ -128,19 +190,78 @@ first_frame = Vector2i(1, 2) script = ExtResource("4_bsdw5") first_frame = Vector2i(2, 2) +[node name="Splat" type="Node" parent="Graphics/Sprite"] +script = ExtResource("4_bsdw5") +first_frame = Vector2i(0, 3) +frames = 2 +fps = 8.0 + +[node name="UnSplat" type="Node" parent="Graphics/Sprite"] +script = ExtResource("4_bsdw5") +first_frame = Vector2i(2, 3) +frames = 2 +fps = 8.0 + +[node name="ChompVault" type="Node" parent="Graphics/Sprite"] +editor_description = "Triggers transition out of ChompVault state when animation is finished." +script = ExtResource("4_bsdw5") +first_frame = Vector2i(4, 0) +frames = 3 +fps = 10.0 +metadata/_custom_type_script = "uid://cv55s54clajw5" + +[node name="CornerDetector" type="Node2D" parent="Graphics"] +metadata/_edit_group_ = true + +[node name="WallCast" type="ShapeCast2D" parent="Graphics/CornerDetector"] +position = Vector2(0, 2.5) +enabled = false +shape = SubResource("RectangleShape2D_l55sg") +target_position = Vector2(6, 0) +max_results = 1 + +[node name="CornerCast" type="RayCast2D" parent="Graphics/CornerDetector"] +position = Vector2(0, -1) +enabled = false +target_position = Vector2(8, 0) + +[node name="CornerHeightCast" type="RayCast2D" parent="Graphics/CornerDetector"] +position = Vector2(9, -1) +enabled = false +target_position = Vector2(0, 8) + +[node name="CornerSnapPoint" type="Node2D" parent="Graphics/CornerDetector"] +position = Vector2(4, 2) + +[node name="VaultOffPoint" type="Node2D" parent="Graphics/CornerDetector"] +position = Vector2(2, 7) + +[node name="SparksPoint" type="Node2D" parent="Graphics"] +position = Vector2(8, 0) + [node name="Sounds" type="Node" parent="."] -[node name="Voice" type="AudioStreamPlayer" parent="Sounds"] -stream = ExtResource("9_8c74o") +[node name="Jump" type="AudioStreamPlayer" parent="Sounds"] +stream = SubResource("AudioStreamRandomizer_45rsp") bus = &"Capri" [node name="Death" type="AudioStreamPlayer" parent="Sounds"] -stream = ExtResource("5_bi5m7") +stream = SubResource("AudioStreamRandomizer_x5bgp") bus = &"Capri" +[node name="Whee" type="AudioStreamPlayer" parent="Sounds"] +stream = SubResource("AudioStreamRandomizer_u8bnf") + +[node name="Wallkick" type="AudioStreamPlayer" parent="Sounds"] +stream = SubResource("AudioStreamRandomizer_lc6id") +volume_db = -20.0 + +[node name="HitWall" type="AudioStreamPlayer" parent="Sounds"] +stream = SubResource("AudioStreamRandomizer_28utn") +volume_db = -10.0 + [node name="StateChart" type="Node" parent="."] script = ExtResource("5_bcjtl") -track_in_editor = true initial_expression_properties = { &"input_dir": Vector2(0, 0), &"on_floor": false, @@ -168,6 +289,12 @@ editor_description = "Player is standing on a floor." script = ExtResource("6_jnxnd") initial_state = NodePath("Standing") +[node name="on Bonked" type="Node" parent="StateChart/Root/Grounded"] +script = ExtResource("7_rgjdc") +to = NodePath("../../Floating/Bonk") +event = &"bonked" +delay_in_seconds = "0.0" + [node name="on JumpPressed" type="Node" parent="StateChart/Root/Grounded"] script = ExtResource("7_rgjdc") to = NodePath("../../Airborne/Jumping") @@ -270,9 +397,22 @@ delay_in_seconds = "0.0" editor_description = "Player is falling down." script = ExtResource("10_mvu25") +[node name="on CornerDetected" type="Node" parent="StateChart/Root/Airborne/Falling"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Floating/ChompVault") +event = &"corner_detected" +delay_in_seconds = "0.0" + +[node name="on Bonked" type="Node" parent="StateChart/Root/Airborne/Falling"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Floating/Bonk") +event = &"bonked" +delay_in_seconds = "0.0" + [node name="Jumping" type="Node" parent="StateChart/Root/Airborne"] editor_description = "Player has jumped and is rising." -script = ExtResource("10_mvu25") +script = ExtResource("6_jnxnd") +initial_state = NodePath("FromGround") [node name="if DownVelocity" type="Node" parent="StateChart/Root/Airborne/Jumping"] editor_description = "Transition to the falling state if moving downwards." @@ -281,26 +421,140 @@ to = NodePath("../../Falling") guard = SubResource("Resource_whx0j") delay_in_seconds = "0.0" +[node name="on CornerDetected" type="Node" parent="StateChart/Root/Airborne/Jumping"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Floating/ChompVault") +event = &"corner_detected" +delay_in_seconds = "0.0" + +[node name="on Bonked" type="Node" parent="StateChart/Root/Airborne/Jumping"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Floating/Bonk") +event = &"bonked" +delay_in_seconds = "0.0" + +[node name="FromGround" type="Node" parent="StateChart/Root/Airborne/Jumping"] +script = ExtResource("10_mvu25") + +[node name="NoBoost" type="Node" parent="StateChart/Root/Airborne/Jumping"] +script = ExtResource("10_mvu25") + [node name="Missile" type="Node" parent="StateChart/Root/Airborne"] editor_description = "Player is hurtling through the air and ricocheting off of surfaces." script = ExtResource("10_mvu25") +[node name="on Splatted" type="Node" parent="StateChart/Root/Airborne/Missile"] +editor_description = "Transition to splat state when the player hits a wall" +script = ExtResource("7_rgjdc") +to = NodePath("../../../Floating/Splat") +event = &"splatted" +delay_in_seconds = "0.0" + +[node name="StunnedFalling" type="Node" parent="StateChart/Root/Airborne"] +script = ExtResource("10_mvu25") + +[node name="on Bonked" type="Node" parent="StateChart/Root/Airborne/StunnedFalling"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Floating/Bonk") +event = &"bonked" +delay_in_seconds = "0.0" + +[node name="Floating" type="Node" parent="StateChart/Root"] +script = ExtResource("6_jnxnd") +initial_state = NodePath("UnSplat") + +[node name="ChompVault" type="Node" parent="StateChart/Root/Floating"] +editor_description = "Player is launching off of a corner." +script = ExtResource("10_mvu25") + +[node name="on AnimationFinished" type="Node" parent="StateChart/Root/Floating/ChompVault"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Airborne/Jumping/NoBoost") +event = &"*animation_finished" +delay_in_seconds = "0.0" + +[node name="Splat" type="Node" parent="StateChart/Root/Floating"] +editor_description = "Player has slammed into a surface (and has a moment to perform an action?)" +script = ExtResource("10_mvu25") + +[node name="on JumpPressed" type="Node" parent="StateChart/Root/Floating/Splat"] +script = ExtResource("7_rgjdc") +to = NodePath("..") +event = &"jump_pressed" +delay_in_seconds = "0.0" + +[node name="on GrabPressed" type="Node" parent="StateChart/Root/Floating/Splat"] +editor_description = "Detach from wall early if \"grab\" is pressed." +script = ExtResource("7_rgjdc") +to = NodePath("../../../Airborne/Falling") +event = &"grab_pressed" +delay_in_seconds = "0.0" + +[node name="on Timeout" type="Node" parent="StateChart/Root/Floating/Splat"] +script = ExtResource("7_rgjdc") +to = NodePath("../../UnSplat") +delay_in_seconds = "0.75" + +[node name="UnSplat" type="Node" parent="StateChart/Root/Floating"] +editor_description = "Player is unsticking from a surface." +script = ExtResource("10_mvu25") + +[node name="on TimeOut" type="Node" parent="StateChart/Root/Floating/UnSplat"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Airborne/Falling") +delay_in_seconds = "0.25" + +[node name="Bonk" type="Node" parent="StateChart/Root/Floating"] +script = ExtResource("10_mvu25") + +[node name="on Timeout" type="Node" parent="StateChart/Root/Floating/Bonk"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Airborne/StunnedFalling") +delay_in_seconds = "0.2" + +[node name="on JumpPressed" type="Node" parent="StateChart/Root/Floating/Bonk"] +script = ExtResource("7_rgjdc") +to = NodePath("../../../Airborne/Jumping/FromGround") +event = &"jump_pressed" +delay_in_seconds = "0.0" + +[connection signal="finished" from="Graphics/Sprite/ChompVault" to="StateChart/Root/Floating/ChompVault/on AnimationFinished" method="take"] [connection signal="taken" from="StateChart/Root/on Killed" to="." method="_reset_position"] [connection signal="taken" from="StateChart/Root/on Killed" to="Sounds/Death" method="play"] +[connection signal="state_physics_processing" from="StateChart/Root/Grounded" to="." method="_check_for_bonk"] [connection signal="state_entered" from="StateChart/Root/Grounded/Standing/Idle" to="Graphics/Sprite/Idle" method="play"] [connection signal="state_entered" from="StateChart/Root/Grounded/Standing/Stopping" to="Graphics/Sprite/Run" method="play"] -[connection signal="state_physics_processing" from="StateChart/Root/Grounded/Standing/Stopping" to="." method="_scale_run_animation"] [connection signal="state_physics_processing" from="StateChart/Root/Grounded/Standing/Stopping" to="." method="_slow_to_stop"] +[connection signal="state_physics_processing" from="StateChart/Root/Grounded/Standing/Stopping" to="." method="_scale_run_animation"] [connection signal="state_entered" from="StateChart/Root/Grounded/Running" to="Graphics/Sprite/Run" method="play"] [connection signal="state_physics_processing" from="StateChart/Root/Grounded/Running" to="." method="_scale_run_animation"] [connection signal="state_physics_processing" from="StateChart/Root/Grounded/Running" to="." method="_apply_run_acceleration"] [connection signal="state_entered" from="StateChart/Root/Grounded/Turning" to="Graphics/Sprite/Skid" method="play"] [connection signal="state_physics_processing" from="StateChart/Root/Grounded/Turning" to="." method="_apply_turn_acceleration"] +[connection signal="state_physics_processing" from="StateChart/Root/Airborne" to="." method="_check_for_bonk"] [connection signal="state_physics_processing" from="StateChart/Root/Airborne" to="." method="_apply_gravity"] +[connection signal="state_physics_processing" from="StateChart/Root/Airborne" to="." method="_check_for_corner"] [connection signal="state_entered" from="StateChart/Root/Airborne/Falling" to="Graphics/Sprite/Fall" method="play"] -[connection signal="state_entered" from="StateChart/Root/Airborne/Jumping" to="." method="_start_jump"] [connection signal="state_entered" from="StateChart/Root/Airborne/Jumping" to="Graphics/Sprite/Jump" method="play"] -[connection signal="state_entered" from="StateChart/Root/Airborne/Jumping" to="Sounds/Voice" method="play"] +[connection signal="state_entered" from="StateChart/Root/Airborne/Jumping/FromGround" to="." method="_start_jump"] +[connection signal="state_entered" from="StateChart/Root/Airborne/Jumping/FromGround" to="Sounds/Jump" method="play"] [connection signal="state_entered" from="StateChart/Root/Airborne/Missile" to="Graphics/Sprite/Missile" method="play"] +[connection signal="state_entered" from="StateChart/Root/Airborne/Missile" to="Sounds/Whee" method="play"] +[connection signal="state_entered" from="StateChart/Root/Airborne/Missile" to="Sounds/Wallkick" method="play"] [connection signal="state_exited" from="StateChart/Root/Airborne/Missile" to="." method="_restore_graphics_rotation"] +[connection signal="state_physics_processing" from="StateChart/Root/Airborne/Missile" to="." method="_check_for_splat"] [connection signal="state_physics_processing" from="StateChart/Root/Airborne/Missile" to="." method="_face_towards_velocity"] +[connection signal="taken" from="StateChart/Root/Airborne/Missile/on Splatted" to="Sounds/HitWall" method="play"] +[connection signal="state_entered" from="StateChart/Root/Airborne/StunnedFalling" to="Graphics/Sprite/StunnedFall" method="play"] +[connection signal="state_entered" from="StateChart/Root/Floating/ChompVault" to="." method="_start_chomp_vault"] +[connection signal="state_entered" from="StateChart/Root/Floating/ChompVault" to="Graphics/Sprite/ChompVault" method="play"] +[connection signal="taken" from="StateChart/Root/Floating/ChompVault/on AnimationFinished" to="." method="_end_chomp_vault"] +[connection signal="state_entered" from="StateChart/Root/Floating/Splat" to="Graphics/Sprite/Splat" method="play"] +[connection signal="taken" from="StateChart/Root/Floating/Splat/on JumpPressed" to="." method="_do_splat_launch"] +[connection signal="taken" from="StateChart/Root/Floating/Splat/on GrabPressed" to="." method="_restore_graphics_rotation"] +[connection signal="state_entered" from="StateChart/Root/Floating/UnSplat" to="Graphics/Sprite/UnSplat" method="play"] +[connection signal="state_exited" from="StateChart/Root/Floating/UnSplat" to="." method="_restore_graphics_rotation"] +[connection signal="state_entered" from="StateChart/Root/Floating/Bonk" to="." method="_enter_bonk"] +[connection signal="state_entered" from="StateChart/Root/Floating/Bonk" to="Graphics/Sprite/Bonk" method="play"] +[connection signal="taken" from="StateChart/Root/Floating/Bonk/on Timeout" to="." method="_apply_bonk"] +[connection signal="taken" from="StateChart/Root/Floating/Bonk/on JumpPressed" to="." method="_cancel_bonk"] diff --git a/objects/portal/portal.gd b/objects/portal/portal.gd new file mode 100644 index 0000000..22a46e8 --- /dev/null +++ b/objects/portal/portal.gd @@ -0,0 +1,71 @@ +@tool +class_name Portal +extends Node2D + + +## color the portal is tinted as +@export_color_no_alpha var color: Color = Color.PURPLE: + set(value): + color = value + sprite.modulate = color + if linked_portal and linked_portal.color != color: + linked_portal.color = color + queue_redraw() + +## Other connected portal. The linked +@export var linked_portal: Portal: + set(new_portal): + if new_portal == self: + return + if new_portal == null: + linked_portal = null + return + if linked_portal: + linked_portal.linked_portal = null + linked_portal = new_portal + if linked_portal: + if linked_portal.linked_portal != self: + linked_portal.linked_portal = self + linked_portal.color = color + queue_redraw() + +## Multiplier to the player's velocity when they travel through the portal. +@export var speed_multiplier: float = 1.25 +## Delay in seconds until an exited portal can be re-entered. +@export var teleport_cooldown: float = 0.1 + +@export_group("Internal References") +@export var sprite: Sprite2D + + +var check_for_player: bool = true + + +func _init() -> void: + set_notify_transform(true) + +func _notification(what: int) -> void: + if what == NOTIFICATION_TRANSFORM_CHANGED: + queue_redraw() + if linked_portal: + linked_portal.queue_redraw() + +func _draw() -> void: + if Engine.is_editor_hint(): + if linked_portal: + draw_line(Vector2.ZERO, to_local(linked_portal.global_position), color, 1.5) + + +func _on_player_detector_body_entered(body: Node2D) -> void: + if check_for_player and body is Player and linked_portal: + body.global_position = linked_portal.global_position + body.launch(body.velocity * speed_multiplier) + linked_portal.check_for_player = false + create_tween().tween_property( + linked_portal, ^"check_for_player", true, 0.0 + ).set_delay(teleport_cooldown) + + +func _on_player_detector_body_exited(body: Node2D) -> void: + var tween = create_tween().set_process_mode(Tween.TWEEN_PROCESS_PHYSICS) + tween.tween_property(self, ^"check_for_player", true, 0.0).set_delay(teleport_cooldown) diff --git a/objects/portal/portal.gd.uid b/objects/portal/portal.gd.uid new file mode 100644 index 0000000..9fbb1be --- /dev/null +++ b/objects/portal/portal.gd.uid @@ -0,0 +1 @@ +uid://dbrblyk7xttpj diff --git a/objects/portal/portal.tscn b/objects/portal/portal.tscn new file mode 100644 index 0000000..233fe53 --- /dev/null +++ b/objects/portal/portal.tscn @@ -0,0 +1,112 @@ +[gd_scene load_steps=10 format=3 uid="uid://cypj35yv5auuc"] + +[ext_resource type="Script" uid="uid://dbrblyk7xttpj" path="res://objects/portal/portal.gd" id="1_v7atq"] +[ext_resource type="Texture2D" uid="uid://dtwp3ohanw2sn" path="res://assets/textures/portal/portal.png" id="2_ah4id"] +[ext_resource type="Texture2D" uid="uid://cv7rv8wlhpbg1" path="res://assets/textures/portal/portal_normal.png" id="3_ah4id"] +[ext_resource type="Texture2D" uid="uid://h45qkvmrh0ey" path="res://assets/textures/portal/portal_light.png" id="4_xxtm7"] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_v7atq"] +size = Vector2(16, 16) + +[sub_resource type="Animation" id="Animation_0po8f"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("LightPivot:rotation") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} + +[sub_resource type="Animation" id="Animation_xxtm7"] +resource_name = "spin" +loop_mode = 1 +step = 0.25 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 1), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.0, 12.5664] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("LightPivot:rotation") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 1), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.0, -6.28319] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_6y8yo"] +_data = { +&"RESET": SubResource("Animation_0po8f"), +&"spin": SubResource("Animation_xxtm7") +} + +[sub_resource type="CanvasTexture" id="CanvasTexture_xxtm7"] +diffuse_texture = ExtResource("2_ah4id") +normal_texture = ExtResource("3_ah4id") + +[node name="Portal" type="Node2D" node_paths=PackedStringArray("sprite")] +script = ExtResource("1_v7atq") +sprite = NodePath("Sprite2D") + +[node name="PlayerDetector" type="Area2D" parent="."] +collision_layer = 0 +collision_mask = 16 +monitorable = false + +[node name="CollisionShape2D" type="CollisionShape2D" parent="PlayerDetector"] +shape = SubResource("RectangleShape2D_v7atq") + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +&"": SubResource("AnimationLibrary_6y8yo") +} +autoplay = "spin" + +[node name="Sprite2D" type="Sprite2D" parent="."] +modulate = Color(0.627451, 0.12549, 0.941176, 1) +self_modulate = Color(1, 1, 1, 0.75) +light_mask = 32 +texture = SubResource("CanvasTexture_xxtm7") + +[node name="LightPivot" type="Node2D" parent="."] +position = Vector2(-4, 4) + +[node name="PointLight2D" type="PointLight2D" parent="LightPivot"] +position = Vector2(4, 0) +range_item_cull_mask = 32 +texture = ExtResource("4_xxtm7") +texture_scale = 2.0 +height = 4.0 + +[connection signal="body_entered" from="PlayerDetector" to="." method="_on_player_detector_body_entered"] +[connection signal="body_exited" from="PlayerDetector" to="." method="_on_player_detector_body_exited"] diff --git a/objects/rotoboy/roto_boy.gd b/objects/rotoboy/roto_boy.gd new file mode 100644 index 0000000..e48630a --- /dev/null +++ b/objects/rotoboy/roto_boy.gd @@ -0,0 +1,37 @@ +extends Node2D + + +@export var speed: float = 0.0 +@export_custom(0, "radians_as_degrees") var rotation_speed: float +@export var launch_speed: float + +@export_group("Internal References") +@export var rotation_pivot: Node2D +@export var collision_shape: CollisionShape2D + + +var _player: Player = null + + +func _physics_process(delta: float) -> void: + if is_zero_approx(speed): + %Head.play("normal") + collision_shape.disabled = false + rotation_pivot.rotation = 0.0 + else: + %Head.play("happy") + collision_shape.disabled = true + rotation_pivot.rotation += rotation_speed * delta + if _player: + var dir = -to_local(_player.global_position).orthogonal() + _player.launch(_player.velocity + dir * launch_speed * speed * delta) + + +func _on_player_detector_body_entered(body: Node2D) -> void: + if body is Player: + _player = body + + +func _on_player_detector_body_exited(body: Node2D) -> void: + if body is Player: + _player = null diff --git a/objects/rotoboy/roto_boy.gd.uid b/objects/rotoboy/roto_boy.gd.uid new file mode 100644 index 0000000..9052f77 --- /dev/null +++ b/objects/rotoboy/roto_boy.gd.uid @@ -0,0 +1 @@ +uid://doitxsfhjpfh0 diff --git a/objects/rotoboy/roto_boy.tscn b/objects/rotoboy/roto_boy.tscn index 2c76dd1..f3d00a8 100644 --- a/objects/rotoboy/roto_boy.tscn +++ b/objects/rotoboy/roto_boy.tscn @@ -1,20 +1,42 @@ -[gd_scene load_steps=9 format=3 uid="uid://bwtjfpfkykfdr"] +[gd_scene load_steps=12 format=3 uid="uid://bwtjfpfkykfdr"] [ext_resource type="Script" uid="uid://bt4bdjyekgh53" path="res://scripts/ball_snake/ball_snake.gd" id="1_7ck2q"] +[ext_resource type="Script" uid="uid://doitxsfhjpfh0" path="res://objects/rotoboy/roto_boy.gd" id="1_pwab3"] [ext_resource type="Texture2D" uid="uid://cvgdwf28yr7fw" path="res://assets/textures/rotoboy/rotoboy.png" id="2_3s2uc"] [ext_resource type="Texture2D" uid="uid://ckfu1u3qxssrj" path="res://assets/textures/rotoboy/rotoboy_face.png" id="3_gp51k"] +[ext_resource type="Texture2D" uid="uid://bmohkn7gmnptg" path="res://assets/textures/rotoboy/rotoboy_smile.png" id="4_qes26"] -[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_sc2kd"] +[sub_resource type="CircleShape2D" id="CircleShape2D_pwab3"] +radius = 24.0 [sub_resource type="RectangleShape2D" id="RectangleShape2D_8o2cr"] size = Vector2(48, 8) -[sub_resource type="Animation" id="Animation_bsslc"] +[sub_resource type="SpriteFrames" id="SpriteFrames_5ig0v"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": ExtResource("4_qes26") +}], +"loop": true, +"name": &"happy", +"speed": 5.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": ExtResource("3_gp51k") +}], +"loop": true, +"name": &"normal", +"speed": 5.0 +}] + +[sub_resource type="Animation" id="Animation_qes26"] length = 0.001 tracks/0/type = "value" tracks/0/imported = false tracks/0/enabled = true -tracks/0/path = NodePath("RotatingPiece:rotation") +tracks/0/path = NodePath(".:speed") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/keys = { @@ -24,30 +46,44 @@ tracks/0/keys = { "values": [0.0] } -[sub_resource type="Animation" id="Animation_eby5m"] -resource_name = "spin" -length = 5.0 +[sub_resource type="Animation" id="Animation_pwab3"] +resource_name = "on_off" +length = 3.0 loop_mode = 1 +step = 0.1 tracks/0/type = "value" tracks/0/imported = false tracks/0/enabled = true -tracks/0/path = NodePath("RotatingPiece:rotation") +tracks/0/path = NodePath(".:speed") tracks/0/interp = 1 -tracks/0/loop_wrap = false +tracks/0/loop_wrap = true tracks/0/keys = { -"times": PackedFloat32Array(-0.0333333, 3, 4.2), -"transitions": PackedFloat32Array(1, 1, 1), +"times": PackedFloat32Array(0, 1, 1.1, 2.9, 3), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1), "update": 0, -"values": [0.0, 0.0, 12.5664] +"values": [0.0, 0.0, 1.0, 1.0, 1.0] } -[sub_resource type="AnimationLibrary" id="AnimationLibrary_l3464"] +[sub_resource type="AnimationLibrary" id="AnimationLibrary_5ig0v"] _data = { -&"RESET": SubResource("Animation_bsslc"), -&"spin": SubResource("Animation_eby5m") +&"RESET": SubResource("Animation_qes26"), +&"on_off": SubResource("Animation_pwab3") } -[node name="RotoBoy" type="Node2D"] +[node name="RotoBoy" type="Node2D" node_paths=PackedStringArray("rotation_pivot", "collision_shape")] +script = ExtResource("1_pwab3") +rotation_speed = 18.8496 +launch_speed = 50.0 +rotation_pivot = NodePath("RotatingPiece") +collision_shape = NodePath("RotatingPiece/AnimatableBody2D/CollisionShape2D") + +[node name="PlayerDetector" type="Area2D" parent="."] +collision_layer = 0 +collision_mask = 16 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="PlayerDetector"] +shape = SubResource("CircleShape2D_pwab3") +debug_color = Color(0.752941, 0.196078, 1, 0.25098) [node name="RotatingPiece" type="Node2D" parent="."] @@ -58,7 +94,6 @@ position = Vector2(-20, 0) position = Vector2(20, 0) [node name="AnimatableBody2D" type="AnimatableBody2D" parent="RotatingPiece"] -physics_material_override = SubResource("PhysicsMaterial_sc2kd") [node name="CollisionShape2D" type="CollisionShape2D" parent="RotatingPiece/AnimatableBody2D"] shape = SubResource("RectangleShape2D_8o2cr") @@ -81,11 +116,16 @@ tail_segment = false auto_density = true pixels_per_segment = 6.0 -[node name="Sprite2D" type="Sprite2D" parent="."] -texture = ExtResource("3_gp51k") +[node name="Head" type="AnimatedSprite2D" parent="."] +unique_name_in_owner = true +sprite_frames = SubResource("SpriteFrames_5ig0v") +animation = &"happy" [node name="AnimationPlayer" type="AnimationPlayer" parent="."] libraries = { -"": SubResource("AnimationLibrary_l3464") +&"": SubResource("AnimationLibrary_5ig0v") } -autoplay = "spin" +autoplay = "on_off" + +[connection signal="body_entered" from="PlayerDetector" to="." method="_on_player_detector_body_entered"] +[connection signal="body_exited" from="PlayerDetector" to="." method="_on_player_detector_body_exited"] diff --git a/objects/spikes/spikes.tscn b/objects/spikes/spikes.tscn index 57ed737..5023c2b 100644 --- a/objects/spikes/spikes.tscn +++ b/objects/spikes/spikes.tscn @@ -53,7 +53,7 @@ hframes = 5 [node name="AnimationPlayer" type="AnimationPlayer" parent="."] libraries = { -"": SubResource("AnimationLibrary_7km18") +&"": SubResource("AnimationLibrary_7km18") } autoplay = "spike" diff --git a/project.godot b/project.godot index 592be74..e38a8ef 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,8 @@ config/icon="res://icon.svg" SceneManager="*res://autoloads/scene_manager.tscn" Levels="*res://autoloads/levels.tscn" +GlobalSounds="*res://autoloads/global_sounds.tscn" +Music="*res://autoloads/music.tscn" [display] @@ -27,7 +29,7 @@ window/size/viewport_height=216 [editor_plugins] -enabled=PackedStringArray("res://addons/godot_state_charts/plugin.cfg") +enabled=PackedStringArray("res://addons/capri_tools/plugin.cfg", "res://addons/godot_state_charts/plugin.cfg") [file_customization] @@ -71,6 +73,11 @@ jump={ "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":90,"key_label":0,"unicode":122,"location":0,"echo":false,"script":null) ] } +grab={ +"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":88,"key_label":0,"unicode":120,"location":0,"echo":false,"script":null) +] +} [layer_names] diff --git a/scripts/global_sound_player/global_sound_player.gd b/scripts/global_sound_player/global_sound_player.gd new file mode 100644 index 0000000..ecb6a61 --- /dev/null +++ b/scripts/global_sound_player/global_sound_player.gd @@ -0,0 +1,11 @@ +@tool +@icon("global_sound_player.svg") +class_name GlobalSoundPlayer +extends Node + + +@export_custom(0, "global_sound") var sound: StringName + + +func play() -> void: + GlobalSounds.play_sound(sound) diff --git a/scripts/global_sound_player/global_sound_player.gd.uid b/scripts/global_sound_player/global_sound_player.gd.uid new file mode 100644 index 0000000..2455541 --- /dev/null +++ b/scripts/global_sound_player/global_sound_player.gd.uid @@ -0,0 +1 @@ +uid://cg3hwyafaokvs diff --git a/scripts/global_sound_player/global_sound_player.svg b/scripts/global_sound_player/global_sound_player.svg new file mode 100644 index 0000000..d65c569 --- /dev/null +++ b/scripts/global_sound_player/global_sound_player.svg @@ -0,0 +1,50 @@ + + diff --git a/scripts/global_sound_player/global_sound_player.svg.import b/scripts/global_sound_player/global_sound_player.svg.import new file mode 100644 index 0000000..53ebc8d --- /dev/null +++ b/scripts/global_sound_player/global_sound_player.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d228m7ctf8oxw" +path="res://.godot/imported/global_sound_player.svg-1b6f31c64d0990ab1d53b6cd3019a357.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://scripts/global_sound_player/global_sound_player.svg" +dest_files=["res://.godot/imported/global_sound_player.svg-1b6f31c64d0990ab1d53b6cd3019a357.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/scripts/level/level.gd b/scripts/level/level.gd index e4f6bf7..f3df270 100644 --- a/scripts/level/level.gd +++ b/scripts/level/level.gd @@ -5,3 +5,8 @@ extends Node2D @export var title: String @export var id: String @export_range(0,1,1,"or_greater") var order: int +@export_custom(0, "global_music") var music: StringName + + +func _ready() -> void: + Music.play_song(music) diff --git a/scripts/level/level_info.gd b/scripts/level/level_info.gd index 3ffe0f2..5395dbd 100644 --- a/scripts/level/level_info.gd +++ b/scripts/level/level_info.gd @@ -17,4 +17,5 @@ static func from_level(level: Level) -> LevelInfo: info.title = level.title info.id = level.id info.order = level.order + info.scene_path = level.scene_file_path return info diff --git a/scripts/level/level_set.gd b/scripts/level/level_set.gd index 25d9432..65bdf8b 100644 --- a/scripts/level/level_set.gd +++ b/scripts/level/level_set.gd @@ -8,18 +8,21 @@ extends Resource title = value resource_name = title @export var id: String +@export var start_scene: PackedScene +@export var end_scene: PackedScene + @export_dir var levels_dir: String: set(value): levels_dir = value if Engine.is_editor_hint(): update_levels() - +@export_tool_button("Update Levels") var _update_levels_action = update_levels @export var levels: Array[LevelInfo] = [] -func has_id(id: String) -> bool: +func has_id(level_id: String) -> bool: for info in levels: - if info.id == id: + if info.id == level_id: return true return false @@ -51,6 +54,8 @@ func update_levels() -> void: file = dir.get_next() # sort levels by level order levels.sort_custom(func(a, b): return a.order < b.order) + emit_changed() + notify_property_list_changed() func _popup_alert(message: String) -> void: