From 4d47a7586eb5487cd39a529581d3198701b075f1 Mon Sep 17 00:00:00 2001 From: Zenny Date: Wed, 11 Sep 2024 15:33:36 -0700 Subject: [PATCH] Big refactor in place: Organize nodes in line with dependency injection expectations, use state machine flow more --- GameJamDungeon.csproj | 63 ++++--- GameJamDungeon.csproj.old | 26 --- addons/SimpleDungeons/DungeonRoom3D.gd | 2 + project.godot | 12 ++ src/app/state/AppLogic.g.puml | 38 ++--- src/audio/DimmableAudioStreamPlayer.cs | 58 +++++++ src/audio/InGameAudio.cs | 21 +++ src/audio/InGameAudio.tscn | 19 +++ .../music/crossing-the-gate.mp3 | Bin src/audio/music/crossing-the-gate.mp3.import | 19 +++ src/{sound => audio}/music/droney.mp3 | Bin src/audio/music/droney.mp3.import | 19 +++ src/{sound => audio}/music/tar-winds.mp3 | Bin src/audio/music/tar-winds.mp3.import | 19 +++ .../music/useless immune system.wav | Bin .../music/useless immune system.wav.import | 6 +- src/enemy/state/EnemyLogic.g.puml | 25 +++ .../state/states/EnemyLogic.State.Alive.cs | 8 +- src/game/Game.cs | 91 ++++------ src/game/Game.tscn | 143 ++++------------ src/game/GameData.cs | 2 + src/game/GameLogic.Input.cs | 8 + src/game/GameLogic.Output.cs | 22 ++- src/game/GameLogic.g.puml | 36 ++++ src/game/IGameRepo.cs | 2 + .../states/GameLogic.State.FloorCleared.cs | 21 +++ ....cs => GameLogic.State.InventoryOpened.cs} | 0 ...rop.cs => GameLogic.State.MenuBackdrop.cs} | 0 ...Open.cs => GameLogic.State.MiniMapOpen.cs} | 0 .../state/states/GameLogic.State.Paused.cs | 23 +++ ...{Playing.cs => GameLogic.State.Playing.cs} | 17 +- src/game/state/states/GameLogic.State.Quit.cs | 2 +- .../state/states/GameLogic.State.Resuming.cs | 23 +++ src/game/state/states/Paused.cs | 26 --- src/map/Map.cs | 56 ++++++ src/map/Map.tscn | 33 ++++ src/map/dungeon/Room.tscn | 2 - src/map/{ => dungeon}/Teleport.tscn | 0 src/map/dungeon/floors/DungeonFloor.cs | 7 + src/map/dungeon/floors/Overworld.cs | 6 +- src/map/dungeon/rooms/Antechamber.tscn | 160 +++++++++--------- src/map/dungeon/rooms/DungeonRoomLogic.g.puml | 6 + src/map/{ => overworld}/Overworld.tscn | 2 +- src/map/{ => overworld}/water.gdshader | 0 src/player/Player.cs | 19 +-- src/player/Player.tscn | 11 +- src/player/PlayerData.cs | 11 +- src/player/state/PlayerLogic.Settings.cs | 2 + src/player/state/PlayerLogic.g.puml | 28 +-- .../state/states/PlayerLogic.State.Alive.cs | 8 +- .../state/states/PlayerLogic.State.Dead.cs | 12 ++ src/sound/music/crossing-the-gate.mp3.import | 19 --- src/sound/music/droney.mp3.import | 19 --- src/sound/music/tar-winds.mp3.import | 19 --- src/traits/IKillable.cs | 7 + src/ui/death_menu/DeathMenu.cs | 22 +++ src/ui/death_menu/DeathMenu.tscn | 82 +++++++++ src/ui/floor_clear/FloorClearMenu.cs | 36 ++++ src/ui/floor_clear/FloorClearMenu.tscn | 97 +++++++++++ src/ui/in_game_ui/InGameUI.cs | 49 ++++++ src/ui/in_game_ui/InGameUI.tscn | 26 +++ src/ui/pause_menu/PauseMenu.cs | 23 +++ src/ui/pause_menu/PauseMenu.tscn | 79 +++++++++ 63 files changed, 1123 insertions(+), 469 deletions(-) delete mode 100644 GameJamDungeon.csproj.old create mode 100644 src/audio/DimmableAudioStreamPlayer.cs create mode 100644 src/audio/InGameAudio.cs create mode 100644 src/audio/InGameAudio.tscn rename src/{sound => audio}/music/crossing-the-gate.mp3 (100%) create mode 100644 src/audio/music/crossing-the-gate.mp3.import rename src/{sound => audio}/music/droney.mp3 (100%) create mode 100644 src/audio/music/droney.mp3.import rename src/{sound => audio}/music/tar-winds.mp3 (100%) create mode 100644 src/audio/music/tar-winds.mp3.import rename src/{sound => audio}/music/useless immune system.wav (100%) rename src/{sound => audio}/music/useless immune system.wav.import (51%) create mode 100644 src/enemy/state/EnemyLogic.g.puml create mode 100644 src/game/GameLogic.g.puml create mode 100644 src/game/state/states/GameLogic.State.FloorCleared.cs rename src/game/state/states/{InventoryOpened.cs => GameLogic.State.InventoryOpened.cs} (100%) rename src/game/state/states/{MenuBackdrop.cs => GameLogic.State.MenuBackdrop.cs} (100%) rename src/game/state/states/{MiniMapOpen.cs => GameLogic.State.MiniMapOpen.cs} (100%) create mode 100644 src/game/state/states/GameLogic.State.Paused.cs rename src/game/state/states/{Playing.cs => GameLogic.State.Playing.cs} (62%) create mode 100644 src/game/state/states/GameLogic.State.Resuming.cs delete mode 100644 src/game/state/states/Paused.cs create mode 100644 src/map/Map.cs create mode 100644 src/map/Map.tscn rename src/map/{ => dungeon}/Teleport.tscn (100%) create mode 100644 src/map/dungeon/rooms/DungeonRoomLogic.g.puml rename src/map/{ => overworld}/Overworld.tscn (99%) rename src/map/{ => overworld}/water.gdshader (100%) create mode 100644 src/player/state/states/PlayerLogic.State.Dead.cs delete mode 100644 src/sound/music/crossing-the-gate.mp3.import delete mode 100644 src/sound/music/droney.mp3.import delete mode 100644 src/sound/music/tar-winds.mp3.import create mode 100644 src/traits/IKillable.cs create mode 100644 src/ui/death_menu/DeathMenu.cs create mode 100644 src/ui/death_menu/DeathMenu.tscn create mode 100644 src/ui/floor_clear/FloorClearMenu.cs create mode 100644 src/ui/floor_clear/FloorClearMenu.tscn create mode 100644 src/ui/in_game_ui/InGameUI.cs create mode 100644 src/ui/in_game_ui/InGameUI.tscn create mode 100644 src/ui/pause_menu/PauseMenu.cs create mode 100644 src/ui/pause_menu/PauseMenu.tscn diff --git a/GameJamDungeon.csproj b/GameJamDungeon.csproj index 10dcfe8e..fa18b237 100644 --- a/GameJamDungeon.csproj +++ b/GameJamDungeon.csproj @@ -1,28 +1,37 @@ - - - net8.0 - net8.0 - net8.0 - true - - - - - - - - - - - - - - - - - - - - - + + + net8.0 + net8.0 + net8.0 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GameJamDungeon.csproj.old b/GameJamDungeon.csproj.old deleted file mode 100644 index 1ed1fe8c..00000000 --- a/GameJamDungeon.csproj.old +++ /dev/null @@ -1,26 +0,0 @@ - - - net8.0 - net8.0 - net8.0 - true - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/addons/SimpleDungeons/DungeonRoom3D.gd b/addons/SimpleDungeons/DungeonRoom3D.gd index 494ad1c8..e99a5ced 100644 --- a/addons/SimpleDungeons/DungeonRoom3D.gd +++ b/addons/SimpleDungeons/DungeonRoom3D.gd @@ -4,6 +4,8 @@ extends Node3D signal dungeon_done_generating() +var room = %Room; + var dungeon_generator : DungeonGenerator3D : get: if is_inside_tree() and get_parent() is DungeonGenerator3D: diff --git a/project.godot b/project.godot index 4fed9d33..a352a829 100644 --- a/project.godot +++ b/project.godot @@ -39,6 +39,18 @@ project/assembly_name="GameJamDungeon" enabled=PackedStringArray("res://addons/SimpleDungeons/plugin.cfg", "res://addons/dialogue_manager/plugin.cfg") +[file_customization] + +folder_colors={ +"res://src/dialog/": "purple", +"res://src/enemy/": "red", +"res://src/game/": "orange", +"res://src/inventory_menu/": "green", +"res://src/items/": "teal", +"res://src/map/": "gray", +"res://src/player/": "blue" +} + [global_group] Exit="" diff --git a/src/app/state/AppLogic.g.puml b/src/app/state/AppLogic.g.puml index 73eb587c..885c336b 100644 --- a/src/app/state/AppLogic.g.puml +++ b/src/app/state/AppLogic.g.puml @@ -1,25 +1,25 @@ @startuml AppLogic -state "AppLogic State" as GameJam2024Practice_AppLogic_State { - state "InGame" as GameJam2024Practice_AppLogic_State_InGame - state "MainMenu" as GameJam2024Practice_AppLogic_State_MainMenu - state "SplashScreen" as GameJam2024Practice_AppLogic_State_SplashScreen - state "LeavingMenu" as GameJam2024Practice_AppLogic_State_LeavingMenu +state "AppLogic State" as GameJamDungeon_AppLogic_State { + state "SetupGameScene" as GameJamDungeon_AppLogic_State_SetupGameScene + state "InGame" as GameJamDungeon_AppLogic_State_InGame + state "LoadingScreen" as GameJamDungeon_AppLogic_State_LoadingScreen + state "MainMenu" as GameJamDungeon_AppLogic_State_MainMenu } -GameJam2024Practice_AppLogic_State_InGame --> GameJam2024Practice_AppLogic_State_MainMenu : GameOver -GameJam2024Practice_AppLogic_State_LeavingMenu --> GameJam2024Practice_AppLogic_State_InGame : FadeOutFinished -GameJam2024Practice_AppLogic_State_MainMenu --> GameJam2024Practice_AppLogic_State_LeavingMenu : NewGame -GameJam2024Practice_AppLogic_State_MainMenu --> GameJam2024Practice_AppLogic_State_MainMenu : QuitGame -GameJam2024Practice_AppLogic_State_SplashScreen --> GameJam2024Practice_AppLogic_State_MainMenu : FadeOutFinished +GameJamDungeon_AppLogic_State_InGame --> GameJamDungeon_AppLogic_State_MainMenu : GameOver +GameJamDungeon_AppLogic_State_LoadingScreen --> GameJamDungeon_AppLogic_State_InGame : LoadGameFinished +GameJamDungeon_AppLogic_State_MainMenu --> GameJamDungeon_AppLogic_State_LoadingScreen : NewGame +GameJamDungeon_AppLogic_State_MainMenu --> GameJamDungeon_AppLogic_State_MainMenu : QuitGame +GameJamDungeon_AppLogic_State_SetupGameScene --> GameJamDungeon_AppLogic_State_InGame : LoadGameFinished -GameJam2024Practice_AppLogic_State_InGame : OnEnter → ShowGame -GameJam2024Practice_AppLogic_State_InGame : OnExit → HideGame -GameJam2024Practice_AppLogic_State_InGame : OnGameOver → RemoveExistingGame -GameJam2024Practice_AppLogic_State_LeavingMenu : OnEnter → FadeToBlack -GameJam2024Practice_AppLogic_State_MainMenu : OnEnter → SetupGameScene, ShowMainMenu -GameJam2024Practice_AppLogic_State_MainMenu : OnQuitGame → ExitGame -GameJam2024Practice_AppLogic_State_SplashScreen : OnEnter → ShowSplashScreen -GameJam2024Practice_AppLogic_State_SplashScreen : OnSplashScreenSkipped() → HideSplashScreen +GameJamDungeon_AppLogic_State_InGame : OnEnter → ShowGame +GameJamDungeon_AppLogic_State_InGame : OnExit → HideGame +GameJamDungeon_AppLogic_State_InGame : OnGameOver → RemoveExistingGame +GameJamDungeon_AppLogic_State_LoadingScreen : OnEnter → ShowLoadingScreen +GameJamDungeon_AppLogic_State_MainMenu : OnEnter → ShowMainMenu +GameJamDungeon_AppLogic_State_MainMenu : OnNewGame → SetupGameScene +GameJamDungeon_AppLogic_State_MainMenu : OnQuitGame → ExitGame +GameJamDungeon_AppLogic_State_SetupGameScene : OnEnter → SetupGameScene, ShowGame -[*] --> GameJam2024Practice_AppLogic_State_SplashScreen +[*] --> GameJamDungeon_AppLogic_State_SetupGameScene @enduml \ No newline at end of file diff --git a/src/audio/DimmableAudioStreamPlayer.cs b/src/audio/DimmableAudioStreamPlayer.cs new file mode 100644 index 00000000..7df524f1 --- /dev/null +++ b/src/audio/DimmableAudioStreamPlayer.cs @@ -0,0 +1,58 @@ +namespace GameJamDungeon; + +using Chickensoft.GodotNodeInterfaces; +using Godot; + +public interface IDimmableAudioStreamPlayer : IAudioStreamPlayer +{ + /// Fade this dimmable audio stream track in. + public void FadeIn(); + /// Fade this dimmable audio stream track out. + public void FadeOut(); +} + +public partial class DimmableAudioStreamPlayer : + AudioStreamPlayer, IDimmableAudioStreamPlayer +{ + #region Constants + // -60 to -80 is considered inaudible for decibels. + public const float VOLUME_DB_INAUDIBLE = -80f; + public const double FADE_DURATION = 3d; // seconds + #endregion Constants + + public ITween? FadeTween { get; set; } + + public float InitialVolumeDb; + + public override void _Ready() + { + InitialVolumeDb = VolumeDb; + VolumeDb = VOLUME_DB_INAUDIBLE; + } + + public void FadeIn() + { + SetupFade(InitialVolumeDb, Tween.EaseType.Out); + Play(); + } + + public void FadeOut() + { + SetupFade(VOLUME_DB_INAUDIBLE, Tween.EaseType.In); + FadeTween!.TweenCallback(Callable.From(Stop)); + } + + public void SetupFade(float volumeDb, Tween.EaseType ease) + { + FadeTween?.Kill(); + + FadeTween = GodotInterfaces.Adapt(CreateTween()); + + FadeTween.TweenProperty( + this, + "volume_db", + volumeDb, + FADE_DURATION + ).SetTrans(Tween.TransitionType.Circ).SetEase(ease); + } +} diff --git a/src/audio/InGameAudio.cs b/src/audio/InGameAudio.cs new file mode 100644 index 00000000..74f16d7d --- /dev/null +++ b/src/audio/InGameAudio.cs @@ -0,0 +1,21 @@ +using Chickensoft.AutoInject; +using Chickensoft.GodotNodeInterfaces; +using Chickensoft.Introspection; +using Godot; + +namespace GameJamDungeon; + +[Meta(typeof(IAutoNode))] +public partial class InGameAudio : Node +{ + public override void _Notification(int what) => this.Notify(what); + + #region BGM Nodes + [Node] public IDimmableAudioStreamPlayer MenuBGM { get; set; } = default!; + [Node] public IDimmableAudioStreamPlayer OverworldBGM { get; set; } = default!; + #endregion + + #region SFX Nodes + [Node] public IAudioStreamPlayer PlayerAttackSFX { get; set; } = default!; + #endregion +} diff --git a/src/audio/InGameAudio.tscn b/src/audio/InGameAudio.tscn new file mode 100644 index 00000000..a0f2f256 --- /dev/null +++ b/src/audio/InGameAudio.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://b16ejcwanod72"] + +[ext_resource type="Script" path="res://src/audio/InGameAudio.cs" id="1_gpmcr"] +[ext_resource type="Script" path="res://src/audio/DimmableAudioStreamPlayer.cs" id="2_857rw"] + +[node name="InGameAudio" type="Node"] +process_mode = 3 +script = ExtResource("1_gpmcr") + +[node name="MenuBGM" type="AudioStreamPlayer" parent="."] +unique_name_in_owner = true +script = ExtResource("2_857rw") + +[node name="OverworldBGM" type="AudioStreamPlayer" parent="."] +unique_name_in_owner = true +script = ExtResource("2_857rw") + +[node name="PlayerAttackSFX" type="AudioStreamPlayer" parent="."] +unique_name_in_owner = true diff --git a/src/sound/music/crossing-the-gate.mp3 b/src/audio/music/crossing-the-gate.mp3 similarity index 100% rename from src/sound/music/crossing-the-gate.mp3 rename to src/audio/music/crossing-the-gate.mp3 diff --git a/src/audio/music/crossing-the-gate.mp3.import b/src/audio/music/crossing-the-gate.mp3.import new file mode 100644 index 00000000..c5335b08 --- /dev/null +++ b/src/audio/music/crossing-the-gate.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://d2jrktp06xsba" +path="res://.godot/imported/crossing-the-gate.mp3-f062dfcb3f59739ce7e55970f8091d25.mp3str" + +[deps] + +source_file="res://src/audio/music/crossing-the-gate.mp3" +dest_files=["res://.godot/imported/crossing-the-gate.mp3-f062dfcb3f59739ce7e55970f8091d25.mp3str"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/src/sound/music/droney.mp3 b/src/audio/music/droney.mp3 similarity index 100% rename from src/sound/music/droney.mp3 rename to src/audio/music/droney.mp3 diff --git a/src/audio/music/droney.mp3.import b/src/audio/music/droney.mp3.import new file mode 100644 index 00000000..3b0f1dd2 --- /dev/null +++ b/src/audio/music/droney.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://dfu0fksb6slhx" +path="res://.godot/imported/droney.mp3-a35fe85a5df08f09cd4cf965e60dc611.mp3str" + +[deps] + +source_file="res://src/audio/music/droney.mp3" +dest_files=["res://.godot/imported/droney.mp3-a35fe85a5df08f09cd4cf965e60dc611.mp3str"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/src/sound/music/tar-winds.mp3 b/src/audio/music/tar-winds.mp3 similarity index 100% rename from src/sound/music/tar-winds.mp3 rename to src/audio/music/tar-winds.mp3 diff --git a/src/audio/music/tar-winds.mp3.import b/src/audio/music/tar-winds.mp3.import new file mode 100644 index 00000000..4ba41bd3 --- /dev/null +++ b/src/audio/music/tar-winds.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://dn2e2hqujlia1" +path="res://.godot/imported/tar-winds.mp3-7ac6ab80e2c96dfbcd5e5c27c1154ff2.mp3str" + +[deps] + +source_file="res://src/audio/music/tar-winds.mp3" +dest_files=["res://.godot/imported/tar-winds.mp3-7ac6ab80e2c96dfbcd5e5c27c1154ff2.mp3str"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/src/sound/music/useless immune system.wav b/src/audio/music/useless immune system.wav similarity index 100% rename from src/sound/music/useless immune system.wav rename to src/audio/music/useless immune system.wav diff --git a/src/sound/music/useless immune system.wav.import b/src/audio/music/useless immune system.wav.import similarity index 51% rename from src/sound/music/useless immune system.wav.import rename to src/audio/music/useless immune system.wav.import index 46b5f1ae..f40dccf9 100644 --- a/src/sound/music/useless immune system.wav.import +++ b/src/audio/music/useless immune system.wav.import @@ -3,12 +3,12 @@ importer="wav" type="AudioStreamWAV" uid="uid://6002a12ecfo5" -path="res://.godot/imported/useless immune system.wav-782449ff6e435e9bc7c74d1a840494fc.sample" +path="res://.godot/imported/useless immune system.wav-90ff2c5c12784f54b1b15c7a7e4603b8.sample" [deps] -source_file="res://src/sound/music/useless immune system.wav" -dest_files=["res://.godot/imported/useless immune system.wav-782449ff6e435e9bc7c74d1a840494fc.sample"] +source_file="res://src/audio/music/useless immune system.wav" +dest_files=["res://.godot/imported/useless immune system.wav-90ff2c5c12784f54b1b15c7a7e4603b8.sample"] [params] diff --git a/src/enemy/state/EnemyLogic.g.puml b/src/enemy/state/EnemyLogic.g.puml new file mode 100644 index 00000000..c3dbb024 --- /dev/null +++ b/src/enemy/state/EnemyLogic.g.puml @@ -0,0 +1,25 @@ +@startuml EnemyLogic +state "EnemyLogic State" as GameJamDungeon_EnemyLogic_State { + state "Alive" as GameJamDungeon_EnemyLogic_State_Alive { + state "Attack" as GameJamDungeon_EnemyLogic_State_Attack + state "FollowPlayer" as GameJamDungeon_EnemyLogic_State_FollowPlayer + state "Idle" as GameJamDungeon_EnemyLogic_State_Idle + } +} + +GameJamDungeon_EnemyLogic_State_Alive --> GameJamDungeon_EnemyLogic_State_Alive : HitByPlayer +GameJamDungeon_EnemyLogic_State_Alive --> GameJamDungeon_EnemyLogic_State_Attack : AttackTimer +GameJamDungeon_EnemyLogic_State_Attack --> GameJamDungeon_EnemyLogic_State_FollowPlayer : Alerted +GameJamDungeon_EnemyLogic_State_FollowPlayer --> GameJamDungeon_EnemyLogic_State_FollowPlayer : PhysicsTick +GameJamDungeon_EnemyLogic_State_FollowPlayer --> GameJamDungeon_EnemyLogic_State_Idle : LostPlayer +GameJamDungeon_EnemyLogic_State_FollowPlayer --> GameJamDungeon_EnemyLogic_State_Idle : PhysicsTick +GameJamDungeon_EnemyLogic_State_Idle --> GameJamDungeon_EnemyLogic_State_FollowPlayer : Alerted +GameJamDungeon_EnemyLogic_State_Idle --> GameJamDungeon_EnemyLogic_State_Idle : PatrolToRandomSpot +GameJamDungeon_EnemyLogic_State_Idle --> GameJamDungeon_EnemyLogic_State_Idle : PhysicsTick + +GameJamDungeon_EnemyLogic_State_Alive : OnHitByPlayer → HitByPlayer +GameJamDungeon_EnemyLogic_State_FollowPlayer : OnPhysicsTick → MovementComputed +GameJamDungeon_EnemyLogic_State_Idle : OnPhysicsTick → MovementComputed + +[*] --> GameJamDungeon_EnemyLogic_State_Idle +@enduml \ No newline at end of file diff --git a/src/enemy/state/states/EnemyLogic.State.Alive.cs b/src/enemy/state/states/EnemyLogic.State.Alive.cs index 7a4c2fdb..b74aec0d 100644 --- a/src/enemy/state/states/EnemyLogic.State.Alive.cs +++ b/src/enemy/state/states/EnemyLogic.State.Alive.cs @@ -8,7 +8,7 @@ namespace GameJamDungeon public partial record State { [Meta, Id("enemy_logic_state_alive")] - public abstract partial record Alive : State, IGet, IGet, IGet + public abstract partial record Alive : State, IGet, IGet { public Transition On(in Input.HitByPlayer input) { @@ -22,12 +22,6 @@ namespace GameJamDungeon return ToSelf(); } - public Transition On(in Input.Killed input) - { - Output(new Output.Die()); - return To(); - } - public Transition On(in Input.AttackTimer input) { return To(); diff --git a/src/game/Game.cs b/src/game/Game.cs index 2da727a7..69a9665a 100644 --- a/src/game/Game.cs +++ b/src/game/Game.cs @@ -1,3 +1,4 @@ + namespace GameJamDungeon; using Chickensoft.AutoInject; @@ -5,6 +6,7 @@ using Chickensoft.GodotNodeInterfaces; using Chickensoft.Introspection; using DialogueManagerRuntime; using Godot; +using System; using System.Collections.Generic; using System.Linq; @@ -32,25 +34,17 @@ public partial class Game : Node3D, IGame [Dependency] public IAppRepo AppRepo => this.DependOn(); - [Node] public IInventoryMenu InventoryMenu { get; set; } = default!; - - [Node] public Control MiniMap { get; set; } = default!; - - [Node] public Area3D Teleport { get; set; } = default!; - - [Node] public IDungeonFloor Overworld { get; set; } = default!; - - [Node] public IDungeonFloor Floor1 { get; set; } = default!; - - [Node] public IDungeonFloor Floor2 { get; set; } = default!; - - [Node] public IDungeonFloor Floor3 { get; set; } = default!; - - [Node] public AnimationPlayer AnimationPlayer { get; set; } = default!; + [Node] public IMap Map { get; set; } = default!; [Node] public DialogueController DialogueController { get; set; } = default!; - private List Floors; + [Node] public IPauseMenu PauseMenu { get; set; } = default!; + + [Node] public FloorClearMenu FloorClearMenu { get; set; } = default!; + + [Node] public DeathMenu DeathMenu { get; set; } = default!; + + [Node] public InGameUI InGameUI { get; set; } = default!; public void Setup() { @@ -59,17 +53,13 @@ public partial class Game : Node3D, IGame GameLogic.Set(GameRepo); GameLogic.Set(AppRepo); Instantiator = new Instantiator(GetTree()); - Floors = new List { Overworld, Floor1, Floor2, Floor3 }; - Teleport.BodyEntered += OnTeleportEntered; + + FloorClearMenu.TransitionCompleted += OnFloorClearTransitionCompleted; } - private void OnTeleportEntered(Node3D body) + private void OnFloorClearTransitionCompleted() { - GameRepo.Pause(); - DialogueManager.GetCurrentScene = (() => this); - var dialogueResource = GD.Load("res://src/ui/dialogue/FloorExit.dialogue"); - DialogueController.ShowDialogue(dialogueResource, "floor_exit"); - DialogueManager.DialogueEnded += (Resource resource) => { GameRepo.Resume(); }; + GameLogic.Input(new GameLogic.Input.FloorClearTransitioned()); } public void Exit() @@ -84,36 +74,27 @@ public partial class Game : Node3D, IGame GameBinding .Handle((in GameLogic.Output.StartGame _) => { + InGameUI.Show(); + GameRepo.SetPlayerGlobalPosition(Map.GetPlayerSpawnPoint()); }) - .Handle((in GameLogic.Output.LoadNextFloor _) => + .Handle((in GameLogic.Output.SetPauseMode output) => CallDeferred(nameof(SetPauseMode), output.IsPaused)) + .Handle((in GameLogic.Output.ShowPauseMenu _) => { - AnimationPlayer.Play("wait_and_load"); - var currentFloor = Floors.ElementAt(GameRepo.CurrentFloor); - currentFloor.CallDeferred(MethodName.QueueFree, []); - - if (GameRepo.EquippedWeapon.Value.WeaponInfo != null && GameRepo.EquippedWeapon.Value.WeaponInfo.WeaponTags.Contains(WeaponTag.BreaksOnChange)) - { - GameRepo.InventoryItems.Value.Remove(GameRepo.EquippedWeapon.Value); - GameRepo.OnWeaponEquipped(new Weapon()); - } - + PauseMenu.Show(); + PauseMenu.FadeIn(); }) - .Handle((in GameLogic.Output.SetPauseMode output) => - { - CallDeferred(nameof(SetPauseMode), output.IsPaused); - }) - .Handle((in GameLogic.Output.SetInventoryMode _) => { InventoryMenu.RedrawInventory(); InventoryMenu.Show(); }) - .Handle((in GameLogic.Output.HideInventory _) => { InventoryMenu.Hide(); }) - .Handle((in GameLogic.Output.ShowMiniMap _) => { MiniMap.Show(); }) - .Handle((in GameLogic.Output.HideMiniMap _) => { MiniMap.Hide(); }) - .Handle((in GameLogic.Output.GameOver _) => { AppRepo.OnGameOver(); }); + .Handle((in GameLogic.Output.HidePauseMenu _) => { PauseMenu.Hide(); }) + .Handle((in GameLogic.Output.ExitPauseMenu _) => { PauseMenu.FadeOut(); }) + .Handle((in GameLogic.Output.ShowFloorClearMenu _) => { FloorClearMenu.Show(); FloorClearMenu.FadeIn(); }) + .Handle((in GameLogic.Output.SetInventoryMode _) => { InGameUI.ShowInventoryScreen(); }) + .Handle((in GameLogic.Output.HideInventory _) => { InGameUI.HideInventoryScreen(); }) + .Handle((in GameLogic.Output.ShowMiniMap _) => { InGameUI.ShowMiniMap(); }) + .Handle((in GameLogic.Output.HideMiniMap _) => { InGameUI.HideMiniMap(); }) + .Handle((in GameLogic.Output.ShowLostScreen _) => { DeathMenu.Show(); DeathMenu.FadeIn(); }) + .Handle((in GameLogic.Output.ExitLostScreen _) => { DeathMenu.FadeOut(); }); GameLogic.Start(); GameLogic.Input(new GameLogic.Input.Initialize()); - AnimationPlayer.AnimationStarted += AnimationPlayer_AnimationStarted; - AnimationPlayer.AnimationFinished += AnimationPlayer_AnimationFinished; - - AnimationPlayer.Play("wait_and_load"); this.Provide(); } @@ -123,20 +104,6 @@ public partial class Game : Node3D, IGame GameLogic.Input(new GameLogic.Input.InventoryMenuToggle()); } - private void AnimationPlayer_AnimationStarted(StringName animName) - { - var newFloor = Floors.ElementAt(GameRepo.CurrentFloor + 1); - newFloor.CallDeferred(nameof(newFloor.InitializeDungeon), []); - newFloor.Show(); - } - - private void AnimationPlayer_AnimationFinished(StringName animName) - { - var spawnPoints = GetTree().GetNodesInGroup("Exit").OfType(); - Teleport.GlobalPosition = spawnPoints.Last().GlobalPosition; - GameRepo.CurrentFloor++; - } - public override void _UnhandledInput(InputEvent @event) { if (@event.IsActionPressed(GameInputs.Inventory)) diff --git a/src/game/Game.tscn b/src/game/Game.tscn index afd0105e..1d02e6d6 100644 --- a/src/game/Game.tscn +++ b/src/game/Game.tscn @@ -1,131 +1,54 @@ -[gd_scene load_steps=16 format=3 uid="uid://33ek675mfb5n"] +[gd_scene load_steps=12 format=3 uid="uid://33ek675mfb5n"] [ext_resource type="Script" path="res://src/game/Game.cs" id="1_ytcii"] +[ext_resource type="PackedScene" uid="uid://by67pn7fdsg1m" path="res://src/map/Map.tscn" id="3_d8awv"] [ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="3_kk6ly"] -[ext_resource type="PackedScene" uid="uid://dlj8qdg1c5048" path="res://src/inventory_menu/InventoryMenu.tscn" id="4_wk8gw"] -[ext_resource type="PackedScene" uid="uid://dvnc26rebk6o0" path="res://src/map/Overworld.tscn" id="5_4hqe8"] -[ext_resource type="PackedScene" uid="uid://bc1sp6xwe0j65" path="res://src/map/dungeon/floors/Floor1.tscn" id="6_75lk5"] -[ext_resource type="PackedScene" uid="uid://bwbofurcvf3yh" path="res://src/minimap/Minimap.tscn" id="6_owlf4"] -[ext_resource type="PackedScene" path="res://src/map/dungeon/floors/Floor2.tscn" id="7_1sm5s"] -[ext_resource type="PackedScene" path="res://src/map/dungeon/floors/Floor3.tscn" id="8_87yk1"] -[ext_resource type="PackedScene" uid="uid://bjqgl5u05ia04" path="res://src/map/Teleport.tscn" id="9_nwu7r"] +[ext_resource type="Script" path="res://src/map/Map.cs" id="4_f5pye"] +[ext_resource type="PackedScene" uid="uid://b1muxus5qdbeu" path="res://src/ui/in_game_ui/InGameUI.tscn" id="5_lxtnp"] +[ext_resource type="PackedScene" uid="uid://b16ejcwanod72" path="res://src/audio/InGameAudio.tscn" id="6_qc71l"] [ext_resource type="Script" path="res://src/game/DialogueController.cs" id="10_58pbt"] - -[sub_resource type="Environment" id="Environment_fke5g"] - -[sub_resource type="Animation" id="Animation_nc1gg"] -length = 0.001 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("LoadScreen:color") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [Color(1, 1, 1, 0)] -} - -[sub_resource type="Animation" id="Animation_wewlr"] -resource_name = "load" -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("LoadScreen:color") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0, 1), -"transitions": PackedFloat32Array(1, 1), -"update": 0, -"values": [Color(0, 0.486275, 1, 1), Color(0, 0.486275, 1, 0)] -} - -[sub_resource type="Animation" id="Animation_ovny8"] -resource_name = "wait_and_load" -length = 3.0 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("LoadScreen:color") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0, 1.96667, 2.96667), -"transitions": PackedFloat32Array(1, 1, 1), -"update": 0, -"values": [Color(0, 0.486275, 1, 1), Color(0, 0.486275, 1, 1), Color(0, 0.486275, 1, 0)] -} - -[sub_resource type="AnimationLibrary" id="AnimationLibrary_opfbx"] -_data = { -"RESET": SubResource("Animation_nc1gg"), -"load": SubResource("Animation_wewlr"), -"wait_and_load": SubResource("Animation_ovny8") -} +[ext_resource type="Script" path="res://src/ui/pause_menu/PauseMenu.cs" id="11_5ng8c"] +[ext_resource type="PackedScene" uid="uid://pu6gp8de3ck4" path="res://src/ui/floor_clear/FloorClearMenu.tscn" id="11_rya1n"] +[ext_resource type="PackedScene" uid="uid://dbtfgrtgpr4qg" path="res://src/ui/death_menu/DeathMenu.tscn" id="11_wypid"] +[ext_resource type="PackedScene" uid="uid://blbqgw3wosc1w" path="res://src/ui/pause_menu/PauseMenu.tscn" id="12_yev8k"] [node name="Game" type="Node3D"] process_mode = 3 script = ExtResource("1_ytcii") -[node name="Player" parent="." instance=ExtResource("3_kk6ly")] +[node name="PauseContainer" type="Node3D" parent="."] +unique_name_in_owner = true +process_mode = 1 + +[node name="Player" parent="PauseContainer" instance=ExtResource("3_kk6ly")] +unique_name_in_owner = true process_mode = 1 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2.74459, 1.22144) -[node name="WorldEnvironment" type="WorldEnvironment" parent="."] -environment = SubResource("Environment_fke5g") +[node name="Map" parent="PauseContainer" instance=ExtResource("3_d8awv")] +unique_name_in_owner = true +script = ExtResource("4_f5pye") -[node name="MiniMap" parent="." instance=ExtResource("6_owlf4")] +[node name="InGameUI" parent="." instance=ExtResource("5_lxtnp")] unique_name_in_owner = true visible = false -[node name="InventoryMenu" parent="." instance=ExtResource("4_wk8gw")] -unique_name_in_owner = true -process_mode = 3 -visible = false - -[node name="OmniLight3D" type="OmniLight3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 24.5244, 0) -layers = 3 -omni_range = 163.618 -omni_attenuation = -0.183 - -[node name="Overworld" parent="." instance=ExtResource("5_4hqe8")] -unique_name_in_owner = true - -[node name="Floor1" parent="." instance=ExtResource("6_75lk5")] -unique_name_in_owner = true - -[node name="Floor2" parent="." instance=ExtResource("7_1sm5s")] -unique_name_in_owner = true - -[node name="Floor3" parent="." instance=ExtResource("8_87yk1")] -unique_name_in_owner = true - -[node name="AnimationPlayer" type="AnimationPlayer" parent="."] -unique_name_in_owner = true -libraries = { -"": SubResource("AnimationLibrary_opfbx") -} - -[node name="LoadScreen" type="ColorRect" parent="."] -process_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -color = Color(1, 1, 1, 0) - -[node name="Teleport" parent="." instance=ExtResource("9_nwu7r")] -unique_name_in_owner = true -process_mode = 3 -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 900, 900, 900) -disable_mode = 2 +[node name="InGameAudio" parent="." instance=ExtResource("6_qc71l")] [node name="DialogueController" type="Node" parent="."] unique_name_in_owner = true process_mode = 3 script = ExtResource("10_58pbt") + +[node name="DeathMenu" parent="." instance=ExtResource("11_wypid")] +unique_name_in_owner = true +visible = false + +[node name="FloorClearMenu" parent="." instance=ExtResource("11_rya1n")] +unique_name_in_owner = true +visible = false + +[node name="PauseMenu" parent="." instance=ExtResource("12_yev8k")] +unique_name_in_owner = true +visible = false +script = ExtResource("11_5ng8c") diff --git a/src/game/GameData.cs b/src/game/GameData.cs index 8bea4b65..db48e650 100644 --- a/src/game/GameData.cs +++ b/src/game/GameData.cs @@ -1,10 +1,12 @@ using Chickensoft.Introspection; +using Chickensoft.Serialization; namespace GameJamDungeon { [Meta, Id("game_data")] public partial record GameData { + [Save("player_data")] public required PlayerData PlayerData { get; init; } } } diff --git a/src/game/GameLogic.Input.cs b/src/game/GameLogic.Input.cs index b6476434..b2b086c8 100644 --- a/src/game/GameLogic.Input.cs +++ b/src/game/GameLogic.Input.cs @@ -17,6 +17,14 @@ public readonly record struct GameOver; public readonly record struct LoadNextFloor; + + public readonly record struct FloorExitReached; + + public readonly record struct FloorClearTransitioned; + + public readonly record struct PauseButtonPressed; + + public readonly record struct PauseMenuTransitioned; } } } diff --git a/src/game/GameLogic.Output.cs b/src/game/GameLogic.Output.cs index 09646198..6fb701fe 100644 --- a/src/game/GameLogic.Output.cs +++ b/src/game/GameLogic.Output.cs @@ -6,21 +6,33 @@ namespace GameJamDungeon { public static class Output { - public readonly record struct StartGame(); + public readonly record struct StartGame; + + public readonly record struct ShowPauseMenu; + + public readonly record struct HidePauseMenu; + + public readonly record struct ExitPauseMenu; public readonly record struct SetInventoryMode(List Inventory); - public readonly record struct HideInventory(); + public readonly record struct HideInventory; public readonly record struct SetPauseMode(bool IsPaused); - public readonly record struct ShowMiniMap(); + public readonly record struct ShowMiniMap; - public readonly record struct HideMiniMap(); + public readonly record struct HideMiniMap; - public readonly record struct GameOver(); + public readonly record struct ShowLostScreen; + + public readonly record struct ExitLostScreen; public readonly record struct LoadNextFloor; + + public readonly record struct ShowFloorClearMenu; + + public readonly record struct HideFloorClearMenu; } } } diff --git a/src/game/GameLogic.g.puml b/src/game/GameLogic.g.puml new file mode 100644 index 00000000..67a94cb8 --- /dev/null +++ b/src/game/GameLogic.g.puml @@ -0,0 +1,36 @@ +@startuml GameLogic +state "GameLogic State" as GameJamDungeon_GameLogic_State { + state "FloorCleared" as GameJamDungeon_GameLogic_State_FloorCleared + state "InventoryOpened" as GameJamDungeon_GameLogic_State_InventoryOpened + state "MenuBackdrop" as GameJamDungeon_GameLogic_State_MenuBackdrop + state "MinimapOpen" as GameJamDungeon_GameLogic_State_MinimapOpen + state "Paused" as GameJamDungeon_GameLogic_State_Paused + state "Playing" as GameJamDungeon_GameLogic_State_Playing + state "Quit" as GameJamDungeon_GameLogic_State_Quit + state "Resuming" as GameJamDungeon_GameLogic_State_Resuming +} + +GameJamDungeon_GameLogic_State_InventoryOpened --> GameJamDungeon_GameLogic_State_Playing : InventoryMenuToggle +GameJamDungeon_GameLogic_State_MenuBackdrop --> GameJamDungeon_GameLogic_State_MenuBackdrop : Initialize +GameJamDungeon_GameLogic_State_MenuBackdrop --> GameJamDungeon_GameLogic_State_Playing : Start +GameJamDungeon_GameLogic_State_MinimapOpen --> GameJamDungeon_GameLogic_State_Playing : MiniMapButtonReleased +GameJamDungeon_GameLogic_State_Playing --> GameJamDungeon_GameLogic_State_FloorCleared : FloorExitReached +GameJamDungeon_GameLogic_State_Playing --> GameJamDungeon_GameLogic_State_InventoryOpened : InventoryMenuToggle +GameJamDungeon_GameLogic_State_Playing --> GameJamDungeon_GameLogic_State_MinimapOpen : MiniMapButtonPressed +GameJamDungeon_GameLogic_State_Playing --> GameJamDungeon_GameLogic_State_Quit : GameOver +GameJamDungeon_GameLogic_State_Resuming --> GameJamDungeon_GameLogic_State_Playing : PauseMenuTransitioned + +GameJamDungeon_GameLogic_State : OnIsPaused() → SetPauseMode +GameJamDungeon_GameLogic_State_FloorCleared : OnEnter → ShowFloorClearMenu +GameJamDungeon_GameLogic_State_FloorCleared : OnExit → HideFloorClearMenu +GameJamDungeon_GameLogic_State_InventoryOpened : OnEnter → SetInventoryMode +GameJamDungeon_GameLogic_State_InventoryOpened : OnExit → HideInventory +GameJamDungeon_GameLogic_State_MinimapOpen : OnEnter → ShowMiniMap +GameJamDungeon_GameLogic_State_MinimapOpen : OnExit → HideMiniMap +GameJamDungeon_GameLogic_State_Paused : OnExit → ExitPauseMenu +GameJamDungeon_GameLogic_State_Playing : OnEnter → StartGame +GameJamDungeon_GameLogic_State_Quit : OnEnter → ShowLostScreen +GameJamDungeon_GameLogic_State_Resuming : OnExit → HidePauseMenu + +[*] --> GameJamDungeon_GameLogic_State_Playing +@enduml \ No newline at end of file diff --git a/src/game/IGameRepo.cs b/src/game/IGameRepo.cs index ab930672..2598c755 100644 --- a/src/game/IGameRepo.cs +++ b/src/game/IGameRepo.cs @@ -7,6 +7,8 @@ namespace GameJamDungeon; public interface IGameRepo : IDisposable { + public void OnGameEnded(); + event Action? Ended; AutoProp> InventoryItems { get; } diff --git a/src/game/state/states/GameLogic.State.FloorCleared.cs b/src/game/state/states/GameLogic.State.FloorCleared.cs new file mode 100644 index 00000000..3c4079d5 --- /dev/null +++ b/src/game/state/states/GameLogic.State.FloorCleared.cs @@ -0,0 +1,21 @@ +using Chickensoft.Introspection; +using Chickensoft.LogicBlocks; + +namespace GameJamDungeon +{ + public partial class GameLogic + { + public partial record State + { + [Meta] + public partial record FloorCleared : State + { + public FloorCleared() + { + this.OnEnter(() => { Get().Pause(); Output(new Output.ShowFloorClearMenu()); }); + this.OnExit(() => { Output(new Output.HideFloorClearMenu()); }); + } + } + } + } +} diff --git a/src/game/state/states/InventoryOpened.cs b/src/game/state/states/GameLogic.State.InventoryOpened.cs similarity index 100% rename from src/game/state/states/InventoryOpened.cs rename to src/game/state/states/GameLogic.State.InventoryOpened.cs diff --git a/src/game/state/states/MenuBackdrop.cs b/src/game/state/states/GameLogic.State.MenuBackdrop.cs similarity index 100% rename from src/game/state/states/MenuBackdrop.cs rename to src/game/state/states/GameLogic.State.MenuBackdrop.cs diff --git a/src/game/state/states/MiniMapOpen.cs b/src/game/state/states/GameLogic.State.MiniMapOpen.cs similarity index 100% rename from src/game/state/states/MiniMapOpen.cs rename to src/game/state/states/GameLogic.State.MiniMapOpen.cs diff --git a/src/game/state/states/GameLogic.State.Paused.cs b/src/game/state/states/GameLogic.State.Paused.cs new file mode 100644 index 00000000..5dbf8d75 --- /dev/null +++ b/src/game/state/states/GameLogic.State.Paused.cs @@ -0,0 +1,23 @@ +using Chickensoft.Introspection; +using Chickensoft.LogicBlocks; + +namespace GameJamDungeon +{ + public partial class GameLogic + { + public partial record State + { + [Meta] + public partial record Paused : State + { + public Paused() + { + this.OnEnter(() => Get().Pause()); + this.OnExit(() => Output(new Output.ExitPauseMenu())); + } + + public virtual Transition On(in Input.PauseButtonPressed input) => To(); + } + } + } +} diff --git a/src/game/state/states/Playing.cs b/src/game/state/states/GameLogic.State.Playing.cs similarity index 62% rename from src/game/state/states/Playing.cs rename to src/game/state/states/GameLogic.State.Playing.cs index 1c106ee2..83a8f50f 100644 --- a/src/game/state/states/Playing.cs +++ b/src/game/state/states/GameLogic.State.Playing.cs @@ -8,7 +8,11 @@ namespace GameJamDungeon public partial record State { [Meta] - public partial record Playing : State, IGet, IGet, IGet, IGet + public partial record Playing : State, + IGet, + IGet, + IGet, + IGet { public Playing() { @@ -24,16 +28,9 @@ namespace GameJamDungeon public Transition On(in Input.MiniMapButtonPressed input) => To(); - public Transition On(in Input.GameOver input) - { - return To(); - } + public Transition On(in Input.GameOver input) => To(); - public Transition On(in Input.LoadNextFloor input) - { - Output(new Output.LoadNextFloor()); - return ToSelf(); - } + public Transition On(in Input.FloorExitReached input) => To(); } } } diff --git a/src/game/state/states/GameLogic.State.Quit.cs b/src/game/state/states/GameLogic.State.Quit.cs index 098b8339..66e095d4 100644 --- a/src/game/state/states/GameLogic.State.Quit.cs +++ b/src/game/state/states/GameLogic.State.Quit.cs @@ -12,7 +12,7 @@ namespace GameJamDungeon { public Quit() { - this.OnEnter(() => Output(new Output.GameOver())); + this.OnEnter(() => Output(new Output.ShowLostScreen())); } } } diff --git a/src/game/state/states/GameLogic.State.Resuming.cs b/src/game/state/states/GameLogic.State.Resuming.cs new file mode 100644 index 00000000..6daf08ba --- /dev/null +++ b/src/game/state/states/GameLogic.State.Resuming.cs @@ -0,0 +1,23 @@ +namespace GameJamDungeon; + +using Chickensoft.Introspection; +using Chickensoft.LogicBlocks; + +public partial class GameLogic +{ + public partial record State + { + [Meta] + public partial record Resuming : State, IGet + { + public Resuming() + { + this.OnEnter(() => Get().Resume()); + this.OnExit(() => Output(new Output.HidePauseMenu())); + } + + public Transition On(in Input.PauseMenuTransitioned input) => + To(); + } + } +} diff --git a/src/game/state/states/Paused.cs b/src/game/state/states/Paused.cs deleted file mode 100644 index 5232f7dd..00000000 --- a/src/game/state/states/Paused.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Chickensoft.Introspection; -using Chickensoft.LogicBlocks; - -namespace GameJamDungeon -{ - public partial class GameLogic - { - public partial record State - { - [Meta] - public partial record Paused : State, IGet, IGet - { - public Paused() - { - this.OnEnter(() => Get().Pause()); - this.OnExit(() => Output(new Output.SetPauseMode(false))); - } - - - public virtual Transition On(in Input.InventoryMenuToggle input) => To(); - - public virtual Transition On(in Input.MiniMapButtonReleased input) => To(); - } - } - } -} diff --git a/src/map/Map.cs b/src/map/Map.cs new file mode 100644 index 00000000..0281d344 --- /dev/null +++ b/src/map/Map.cs @@ -0,0 +1,56 @@ +using Chickensoft.AutoInject; +using Chickensoft.GodotNodeInterfaces; +using Chickensoft.Introspection; +using DialogueManagerRuntime; +using Godot; +using System.Collections.Generic; +using System.Linq; + +namespace GameJamDungeon; + +public interface IMap : INode3D +{ + public List Floors { get; } + + public Vector3 GetPlayerSpawnPoint(); +} + + +[Meta(typeof(IAutoNode))] +public partial class Map : Node3D, IMap +{ + public override void _Notification(int what) => this.Notify(what); + + [Node] public Area3D Teleport { get; set; } = default!; + + [Node] public IDungeonFloor Overworld { get; set; } = default!; + + [Node] public IDungeonFloor Floor1 { get; set; } = default!; + + [Node] public IDungeonFloor Floor2 { get; set; } = default!; + + [Node] public IDungeonFloor Floor3 { get; set; } = default!; + + public List Floors { get; set; } = default!; + + private IDungeonFloor _currentFloor; + + public void Setup() + { + Floors = [Overworld, Floor1, Floor2, Floor3]; + _currentFloor = Floors.ElementAt(0); + Teleport.BodyEntered += OnTeleportEntered; + } + + public Vector3 GetPlayerSpawnPoint() + { + return _currentFloor.GetPlayerSpawnPoint(); + } + + private void OnTeleportEntered(Node3D body) + { + DialogueManager.GetCurrentScene = (() => this); + var dialogueResource = GD.Load("res://src/ui/dialogue/FloorExit.dialogue"); + DialogueController.ShowDialogue(dialogueResource, "floor_exit"); + } +} diff --git a/src/map/Map.tscn b/src/map/Map.tscn new file mode 100644 index 00000000..a292201b --- /dev/null +++ b/src/map/Map.tscn @@ -0,0 +1,33 @@ +[gd_scene load_steps=6 format=3 uid="uid://by67pn7fdsg1m"] + +[ext_resource type="PackedScene" uid="uid://dvnc26rebk6o0" path="res://src/map/overworld/Overworld.tscn" id="1_ope1x"] +[ext_resource type="PackedScene" uid="uid://bc1sp6xwe0j65" path="res://src/map/dungeon/floors/Floor1.tscn" id="2_merfv"] +[ext_resource type="PackedScene" uid="uid://b3r0r22kc67bl" path="res://src/map/dungeon/floors/Floor2.tscn" id="3_kqqo3"] +[ext_resource type="PackedScene" uid="uid://b40sstnic41dw" path="res://src/map/dungeon/floors/Floor3.tscn" id="4_1shir"] +[ext_resource type="PackedScene" uid="uid://bjqgl5u05ia04" path="res://src/map/dungeon/Teleport.tscn" id="5_jiohg"] + +[node name="Map" type="Node3D"] + +[node name="OmniLight3D" type="OmniLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 24.5244, 0) +layers = 3 +omni_range = 163.618 +omni_attenuation = -0.183 + +[node name="Overworld" parent="." instance=ExtResource("1_ope1x")] +unique_name_in_owner = true + +[node name="Floor1" parent="." instance=ExtResource("2_merfv")] +unique_name_in_owner = true + +[node name="Floor2" parent="." instance=ExtResource("3_kqqo3")] +unique_name_in_owner = true + +[node name="Floor3" parent="." instance=ExtResource("4_1shir")] +unique_name_in_owner = true + +[node name="Teleport" parent="." instance=ExtResource("5_jiohg")] +unique_name_in_owner = true +process_mode = 3 +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 900, 900, 900) +disable_mode = 2 diff --git a/src/map/dungeon/Room.tscn b/src/map/dungeon/Room.tscn index 59e99c4f..bc8d4e88 100644 --- a/src/map/dungeon/Room.tscn +++ b/src/map/dungeon/Room.tscn @@ -27,8 +27,6 @@ unique_name_in_owner = true [node name="ItemDatabase" parent="." instance=ExtResource("2_ibf0a")] unique_name_in_owner = true -ItemScene = Array[PackedScene]([]) -DropRate = PackedFloat32Array() [node name="EnemyDatabase" parent="." instance=ExtResource("3_ha7vd")] unique_name_in_owner = true diff --git a/src/map/Teleport.tscn b/src/map/dungeon/Teleport.tscn similarity index 100% rename from src/map/Teleport.tscn rename to src/map/dungeon/Teleport.tscn diff --git a/src/map/dungeon/floors/DungeonFloor.cs b/src/map/dungeon/floors/DungeonFloor.cs index ca1800cc..56cb6f79 100644 --- a/src/map/dungeon/floors/DungeonFloor.cs +++ b/src/map/dungeon/floors/DungeonFloor.cs @@ -6,6 +6,8 @@ using Godot; public interface IDungeonFloor : INode3D { void InitializeDungeon(); + + public Vector3 GetPlayerSpawnPoint(); } [Meta(typeof(IAutoNode))] @@ -19,4 +21,9 @@ public partial class DungeonFloor : Node3D, IDungeonFloor { DungeonGenerator.Call("generate"); } + + public Vector3 GetPlayerSpawnPoint() + { + return Vector3.Zero; + } } diff --git a/src/map/dungeon/floors/Overworld.cs b/src/map/dungeon/floors/Overworld.cs index a3b79926..0fa56bee 100644 --- a/src/map/dungeon/floors/Overworld.cs +++ b/src/map/dungeon/floors/Overworld.cs @@ -1,6 +1,5 @@ using Chickensoft.AutoInject; using Chickensoft.Introspection; -using DialogueManagerRuntime; using GameJamDungeon; using Godot; @@ -18,4 +17,9 @@ public partial class Overworld : Node3D, IDungeonFloor { GameRepo.SetPlayerGlobalPosition(PlayerSpawnPoint.GlobalPosition); } + + public Vector3 GetPlayerSpawnPoint() + { + return PlayerSpawnPoint.GlobalPosition; + } } diff --git a/src/map/dungeon/rooms/Antechamber.tscn b/src/map/dungeon/rooms/Antechamber.tscn index 77074871..914f5f15 100644 --- a/src/map/dungeon/rooms/Antechamber.tscn +++ b/src/map/dungeon/rooms/Antechamber.tscn @@ -1099,295 +1099,295 @@ size = Vector2(35, 30) [node name="Antechamber" type="Node3D"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.73082, 0, -1.86841) script = ExtResource("1_tdydv") -size_in_voxels = Vector3i(5, 2, 4) -voxel_scale = Vector3(12.955, 13.01, 12.945) -[node name="NavigationRegion3D" type="NavigationRegion3D" parent="."] +[node name="Room" type="Node3D" parent="."] +unique_name_in_owner = true +script = ExtResource("16_osbes") + +[node name="NavigationRegion3D" type="NavigationRegion3D" parent="Room"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.04836, 3.10489, 12.6166) navigation_mesh = SubResource("NavigationMesh_2x5qh") -[node name="ANTECHAMBER" type="Node3D" parent="NavigationRegion3D"] +[node name="ANTECHAMBER" type="Node3D" parent="Room/NavigationRegion3D"] transform = Transform3D(0.93, 0, 0, 0, 0.93, 0, 0, 0, 0.93, -122.383, -16.3014, -66.1084) -[node name="StaticBody3D7" type="StaticBody3D" parent="NavigationRegion3D/ANTECHAMBER"] +[node name="StaticBody3D7" type="StaticBody3D" parent="Room/NavigationRegion3D/ANTECHAMBER"] transform = Transform3D(0, 0, -0.515006, 0, 0.54653, 0, 0.593558, 0, 0, 116.446, 7.82144, 86.6174) -[node name="Cube_016" type="MeshInstance3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D7"] +[node name="Cube_016" type="MeshInstance3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D7"] transform = Transform3D(0, 0, 0.835538, 0, 0.713892, 0, -0.794927, 0, 0, -0.594563, 5.69153, -0.0170364) mesh = SubResource("ArrayMesh_t87ci") skeleton = NodePath("") -[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D7"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D7"] transform = Transform3D(0, 0, 0.835538, 0, 0.713892, 0, -0.794927, 0, 0, -0.594563, 5.69153, -0.0170364) shape = SubResource("ConcavePolygonShape3D_bjpni") -[node name="StaticBody3D" type="StaticBody3D" parent="NavigationRegion3D/ANTECHAMBER"] +[node name="StaticBody3D" type="StaticBody3D" parent="Room/NavigationRegion3D/ANTECHAMBER"] -[node name="Cube_001" type="MeshInstance3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D"] +[node name="Cube_001" type="MeshInstance3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D"] transform = Transform3D(0, 0, 13.9165, 0, 13.9165, 0, -13.9165, 0, 0, 134.9, 14.2365, 22.742) mesh = SubResource("ArrayMesh_caq81") skeleton = NodePath("") -[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D"] transform = Transform3D(0, 0, 13.9165, 0, 13.9165, 0, -13.9165, 0, 0, 134.9, 14.2365, 22.742) shape = SubResource("ConcavePolygonShape3D_038td") -[node name="StaticBody3D2" type="StaticBody3D" parent="NavigationRegion3D/ANTECHAMBER"] +[node name="StaticBody3D2" type="StaticBody3D" parent="Room/NavigationRegion3D/ANTECHAMBER"] -[node name="Plane_005" type="MeshInstance3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D2"] +[node name="Plane_005" type="MeshInstance3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D2"] transform = Transform3D(3.843e-06, 0, -7.17802, 0, 1, 0, 2.22327, 0, 1.24075e-05, 148.895, 0.320863, 27.5919) mesh = SubResource("ArrayMesh_4awqv") skeleton = NodePath("") -[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D2"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D2"] transform = Transform3D(3.843e-06, 0, -7.17802, 0, 1, 0, 2.22327, 0, 1.24075e-05, 148.895, 0.320863, 27.5919) shape = SubResource("ConcavePolygonShape3D_740qy") -[node name="StaticBody3D3" type="StaticBody3D" parent="NavigationRegion3D/ANTECHAMBER"] +[node name="StaticBody3D3" type="StaticBody3D" parent="Room/NavigationRegion3D/ANTECHAMBER"] -[node name="Plane_004" type="MeshInstance3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D3"] +[node name="Plane_004" type="MeshInstance3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D3"] transform = Transform3D(-1.85524e-06, 0, 7.17802, 0, 1, 0, -2.22327, 0, -5.98981e-06, 120.895, 0.320863, 87.5919) mesh = SubResource("ArrayMesh_vu1fd") skeleton = NodePath("") -[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D3"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D3"] transform = Transform3D(-1.85524e-06, 0, 7.17802, 0, 1, 0, -2.22327, 0, -5.98981e-06, 120.895, 0.320863, 87.5919) shape = SubResource("ConcavePolygonShape3D_1ngn2") -[node name="StaticBody3D4" type="StaticBody3D" parent="NavigationRegion3D/ANTECHAMBER"] +[node name="StaticBody3D4" type="StaticBody3D" parent="Room/NavigationRegion3D/ANTECHAMBER"] -[node name="Cylinder_005" type="MeshInstance3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D4"] +[node name="Cylinder_005" type="MeshInstance3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D4"] transform = Transform3D(4.07023, 0, 0, 0, 0, -4.07023, 0, 4.07023, 0, 163.045, 13.4492, 78.5838) mesh = SubResource("ArrayMesh_rleii") skeleton = NodePath("") -[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D4"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D4"] transform = Transform3D(4.07023, 0, 0, 0, 0, -4.07023, 0, 4.07023, 0, 163.045, 13.4492, 78.5838) shape = SubResource("ConcavePolygonShape3D_1ty8l") -[node name="StaticBody3D5" type="StaticBody3D" parent="NavigationRegion3D/ANTECHAMBER"] +[node name="StaticBody3D5" type="StaticBody3D" parent="Room/NavigationRegion3D/ANTECHAMBER"] -[node name="Cylinder_010" type="MeshInstance3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D5"] +[node name="Cylinder_010" type="MeshInstance3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D5"] transform = Transform3D(0, 0, 0.553656, 0, 2.80124, 0, -0.423736, 0, 0, 153.394, 7.82472, 28.6819) mesh = SubResource("ArrayMesh_w861l") skeleton = NodePath("") -[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D5"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D5"] transform = Transform3D(0, 0, 0.553656, 0, 2.80124, 0, -0.423736, 0, 0, 153.394, 7.82472, 28.6819) shape = SubResource("ConcavePolygonShape3D_dlkak") -[node name="StaticBody3D6" type="StaticBody3D" parent="NavigationRegion3D/ANTECHAMBER"] +[node name="StaticBody3D6" type="StaticBody3D" parent="Room/NavigationRegion3D/ANTECHAMBER"] -[node name="Cylinder_009" type="MeshInstance3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D6"] +[node name="Cylinder_009" type="MeshInstance3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D6"] transform = Transform3D(0, 0, -0.553656, 0, 2.80124, 0, 0.423736, 0, 0, 116.447, 7.82472, 86.7122) mesh = SubResource("ArrayMesh_w861l") skeleton = NodePath("") -[node name="StaticBody3D8" type="StaticBody3D" parent="NavigationRegion3D/ANTECHAMBER"] +[node name="StaticBody3D8" type="StaticBody3D" parent="Room/NavigationRegion3D/ANTECHAMBER"] -[node name="Cube_017" type="MeshInstance3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D8"] +[node name="Cube_017" type="MeshInstance3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D8"] transform = Transform3D(0, 0, -0.515006, 0, 0.54653, 0, 0.593558, 0, 0, 116.446, 7.82144, 86.6174) mesh = SubResource("ArrayMesh_wn5ym") skeleton = NodePath("") -[node name="CollisionShape3D" type="CollisionShape3D" parent="NavigationRegion3D/ANTECHAMBER/StaticBody3D8"] +[node name="CollisionShape3D" type="CollisionShape3D" parent="Room/NavigationRegion3D/ANTECHAMBER/StaticBody3D8"] transform = Transform3D(0, 0, -0.515006, 0, 0.54653, 0, 0.593558, 0, 0, 116.446, 7.82144, 86.6174) shape = SubResource("ConcavePolygonShape3D_cnvi5") -[node name="DOOR" type="Marker3D" parent="."] +[node name="DOOR" type="Marker3D" parent="Room"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13.1142, -8.45784, 32.0232) -[node name="DOOR2" type="Marker3D" parent="."] +[node name="DOOR2" type="Marker3D" parent="Room"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.92078, -8.62051, -27.067) -[node name="Room" type="Node3D" parent="."] -script = ExtResource("16_osbes") - -[node name="PlayerSpawn" type="Marker3D" parent="."] +[node name="PlayerSpawn" type="Marker3D" parent="Room"] unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -11.8813, 0) -[node name="Minimap Texture" type="MeshInstance3D" parent="."] +[node name="Minimap Texture" type="MeshInstance3D" parent="Room"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00325966, -7.7801, 0) visible = false layers = 2 mesh = SubResource("PlaneMesh_bbi7v") +skeleton = NodePath("../..") -[node name="ItemSpawnPoints" type="Node3D" parent="."] +[node name="ItemSpawnPoints" type="Node3D" parent="Room"] unique_name_in_owner = true -[node name="ItemSpawn1" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn1" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.83448, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn2" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn2" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -7.44186, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn3" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn3" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.09183, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn4" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn4" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.83448, -11.8091, -5.86665) gizmo_extents = 1.0 -[node name="ItemSpawn5" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn5" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.21845, -11.8091, -5.59059) gizmo_extents = 1.0 -[node name="ItemSpawn6" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn6" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn7" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn7" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn8" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn8" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn9" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn9" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn10" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn10" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn11" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn11" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn12" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn12" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn13" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn13" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn14" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn14" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn15" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn15" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn16" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn16" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn17" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn17" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn18" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn18" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn19" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn19" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn20" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn20" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn21" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn21" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn22" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn22" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn23" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn23" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn24" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn24" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn25" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn25" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn26" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn26" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn27" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn27" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn28" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn28" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn29" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn29" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn30" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn30" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn31" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn31" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn32" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn32" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn33" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn33" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn34" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn34" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn35" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn35" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn36" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn36" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn37" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn37" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn38" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn38" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn39" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn39" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="ItemSpawn40" type="Marker3D" parent="ItemSpawnPoints"] +[node name="ItemSpawn40" type="Marker3D" parent="Room/ItemSpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10.8145, -11.8091, -2.92704) gizmo_extents = 1.0 -[node name="EnemySpawnPoints" type="Node3D" parent="."] +[node name="EnemySpawnPoints" type="Node3D" parent="Room"] unique_name_in_owner = true -[node name="EnemySpawn1" type="Marker3D" parent="EnemySpawnPoints"] +[node name="EnemySpawn1" type="Marker3D" parent="Room/EnemySpawnPoints"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.71409, -11.0741, 0) -[node name="ItemDatabase" parent="." instance=ExtResource("17_50pl8")] +[node name="ItemDatabase" parent="Room" instance=ExtResource("17_50pl8")] unique_name_in_owner = true -[node name="EnemyDatabase" parent="." instance=ExtResource("18_3twov")] +[node name="EnemyDatabase" parent="Room" instance=ExtResource("18_3twov")] unique_name_in_owner = true SpawnRate = PackedFloat32Array(1) -[node name="ExitSpawnLocation" type="Marker3D" parent="." groups=["Exit"]] +[node name="ExitSpawnLocation" type="Marker3D" parent="Room" groups=["Exit"]] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.06499, -11.8837, -9.52855) diff --git a/src/map/dungeon/rooms/DungeonRoomLogic.g.puml b/src/map/dungeon/rooms/DungeonRoomLogic.g.puml new file mode 100644 index 00000000..ef06fc7b --- /dev/null +++ b/src/map/dungeon/rooms/DungeonRoomLogic.g.puml @@ -0,0 +1,6 @@ +@startuml DungeonRoomLogic +state "DungeonRoomLogic State" as GameJamDungeon_DungeonRoomLogic_State { + state "Idle" as GameJamDungeon_DungeonRoomLogic_State_Idle +} +[*] --> GameJamDungeon_DungeonRoomLogic_State_Idle +@enduml \ No newline at end of file diff --git a/src/map/Overworld.tscn b/src/map/overworld/Overworld.tscn similarity index 99% rename from src/map/Overworld.tscn rename to src/map/overworld/Overworld.tscn index 104e6d9a..bbe4b3d9 100644 --- a/src/map/Overworld.tscn +++ b/src/map/overworld/Overworld.tscn @@ -8,7 +8,7 @@ [ext_resource type="Texture2D" uid="uid://b1crojyrqmhql" path="res://src/map/overworld/Textures/kenney_prototype-textures/stick.jpeg" id="7_6df1n"] [ext_resource type="ArrayMesh" uid="uid://df5fykeos37m1" path="res://src/map/overworld/Models/raft.obj" id="8_a4vos"] [ext_resource type="Material" uid="uid://6pu2bdointq4" path="res://src/map/overworld/Textures/premade.tres" id="9_th6qc"] -[ext_resource type="Shader" path="res://src/map/water.gdshader" id="10_ntrgc"] +[ext_resource type="Shader" path="res://src/map/overworld/water.gdshader" id="10_ntrgc"] [ext_resource type="Texture2D" uid="uid://bxodl26dnwrkc" path="res://src/map/overworld/Textures/SMALLER1/others_0020_color_1k.jpg" id="11_kf3by"] [ext_resource type="Texture2D" uid="uid://c4iqttgjb0kq3" path="res://src/map/overworld/Textures/kenney_prototype-textures/treetexture.png" id="12_i7q8i"] [ext_resource type="ArrayMesh" uid="uid://bb46flkajcbtd" path="res://src/map/overworld/Models/tree.obj" id="13_uvfqy"] diff --git a/src/map/water.gdshader b/src/map/overworld/water.gdshader similarity index 100% rename from src/map/water.gdshader rename to src/map/overworld/water.gdshader diff --git a/src/player/Player.cs b/src/player/Player.cs index d443504a..d1bcc687 100644 --- a/src/player/Player.cs +++ b/src/player/Player.cs @@ -7,7 +7,7 @@ using Godot; namespace GameJamDungeon { - public interface IPlayer : ICharacterBody3D + public interface IPlayer : ICharacterBody3D, IKillable { PlayerStatInfo PlayerStatInfo { get; } @@ -84,7 +84,7 @@ namespace GameJamDungeon public void Setup() { - Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed }; + Settings = new PlayerLogic.Settings() { RotationSpeed = RotationSpeed, MoveSpeed = MoveSpeed, Acceleration = Acceleration }; PlayerLogic = new PlayerLogic(); PlayerLogic.Set(this as IPlayer); @@ -92,14 +92,6 @@ namespace GameJamDungeon PlayerLogic.Set(AppRepo); PlayerLogic.Set(GameRepo); PlayerLogic.Set(PlayerData); - - GameRepo.SetPlayerGlobalPosition(GlobalPosition); - GameRepo.PlayerGlobalPosition.Sync += OnPlayerPositionUpdated; - - GameRepo.SetPlayerStatInfo(PlayerStatInfo); - - HealthTimer.Timeout += OnHealthTimerTimeout; - CollisionDetector.AreaEntered += OnEnemyHitBoxEntered; } public void OnResolved() @@ -127,6 +119,11 @@ namespace GameJamDungeon PlayerLogic.Start(); SwordSlashAnimation.Position = GetViewport().GetVisibleRect().Size / 2; + GlobalPosition = GameRepo.PlayerGlobalPosition.Value; + GameRepo.SetPlayerStatInfo(PlayerStatInfo); + + HealthTimer.Timeout += OnHealthTimerTimeout; + CollisionDetector.AreaEntered += OnEnemyHitBoxEntered; } public void OnReady() @@ -227,6 +224,8 @@ namespace GameJamDungeon AnimationPlayer.AnimationFinished -= OnAnimationFinished; } + public void Kill() => PlayerLogic.Input(new PlayerLogic.Input.Killed()); + private void OnHPChanged(double newHP) { HPNumber.Text = $"{Mathf.RoundToInt(newHP)}/{PlayerStatInfo.MaximumHP}"; diff --git a/src/player/Player.tscn b/src/player/Player.tscn index c0640cd7..4a6c6091 100644 --- a/src/player/Player.tscn +++ b/src/player/Player.tscn @@ -98,8 +98,8 @@ tracks/1/keys = { [sub_resource type="AnimationLibrary" id="AnimationLibrary_w8l8m"] _data = { -"RESET": SubResource("Animation_hcjph"), -"attack": SubResource("Animation_0jjwv") +&"attack": SubResource("Animation_0jjwv"), +&"RESET": SubResource("Animation_hcjph") } [sub_resource type="SpriteFrames" id="SpriteFrames_ywvvo"] @@ -139,8 +139,9 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.381018, 0) collision_layer = 38 collision_mask = 7 script = ExtResource("1_xcol5") -RotationSpeed = 0.025 -MoveSpeed = 2.0 +RotationSpeed = 3.0 +MoveSpeed = 4.0 +Acceleration = 1.0 PlayerStatInfo = SubResource("Resource_up0v1") [node name="Hitbox" type="Area3D" parent="."] @@ -182,7 +183,7 @@ omni_range = 83.659 [node name="AnimationPlayer" type="AnimationPlayer" parent="."] unique_name_in_owner = true libraries = { -"": SubResource("AnimationLibrary_w8l8m") +&"": SubResource("AnimationLibrary_w8l8m") } [node name="SwordSlashAnimation" type="AnimatedSprite2D" parent="."] diff --git a/src/player/PlayerData.cs b/src/player/PlayerData.cs index 7f728389..9c04b55b 100644 --- a/src/player/PlayerData.cs +++ b/src/player/PlayerData.cs @@ -1,7 +1,16 @@ -namespace GameJamDungeon +using Chickensoft.Serialization; +using Godot; + +namespace GameJamDungeon { public partial record PlayerData { // TODO: Implement save system + [Save("global_transform")] + public required Transform3D GlobalTransform { get; init; } + [Save("state_machine")] + public required PlayerLogic StateMachine { get; init; } + [Save("velocity")] + public required Vector3 Velocity { get; init; } } } diff --git a/src/player/state/PlayerLogic.Settings.cs b/src/player/state/PlayerLogic.Settings.cs index e14c20e8..eb43197d 100644 --- a/src/player/state/PlayerLogic.Settings.cs +++ b/src/player/state/PlayerLogic.Settings.cs @@ -7,6 +7,8 @@ public float MoveSpeed { get; set; } public float RotationSpeed { get; set; } + + public float Acceleration { get; set; } } } } diff --git a/src/player/state/PlayerLogic.g.puml b/src/player/state/PlayerLogic.g.puml index 47e30ecf..b83413f5 100644 --- a/src/player/state/PlayerLogic.g.puml +++ b/src/player/state/PlayerLogic.g.puml @@ -1,20 +1,22 @@ @startuml PlayerLogic -state "PlayerLogic State" as GameJam2024Practice_PlayerLogic_State { - state "Alive" as GameJam2024Practice_PlayerLogic_State_Alive { - state "Idle" as GameJam2024Practice_PlayerLogic_State_Idle - state "Attacking" as GameJam2024Practice_PlayerLogic_State_Attacking +state "PlayerLogic State" as GameJamDungeon_PlayerLogic_State { + state "Alive" as GameJamDungeon_PlayerLogic_State_Alive { + state "Attacking" as GameJamDungeon_PlayerLogic_State_Attacking + state "Idle" as GameJamDungeon_PlayerLogic_State_Idle } - state "Disabled" as GameJam2024Practice_PlayerLogic_State_Disabled + state "Dead" as GameJamDungeon_PlayerLogic_State_Dead + state "Disabled" as GameJamDungeon_PlayerLogic_State_Disabled } -GameJam2024Practice_PlayerLogic_State_Alive --> GameJam2024Practice_PlayerLogic_State_Alive : Moved -GameJam2024Practice_PlayerLogic_State_Alive --> GameJam2024Practice_PlayerLogic_State_Alive : PhysicsTick -GameJam2024Practice_PlayerLogic_State_Attacking --> GameJam2024Practice_PlayerLogic_State_Idle : AttackAnimationFinished -GameJam2024Practice_PlayerLogic_State_Disabled --> GameJam2024Practice_PlayerLogic_State_Idle : Enable -GameJam2024Practice_PlayerLogic_State_Idle --> GameJam2024Practice_PlayerLogic_State_Attacking : Attack +GameJamDungeon_PlayerLogic_State_Alive --> GameJamDungeon_PlayerLogic_State_Alive : Moved +GameJamDungeon_PlayerLogic_State_Alive --> GameJamDungeon_PlayerLogic_State_Alive : PhysicsTick +GameJamDungeon_PlayerLogic_State_Alive --> GameJamDungeon_PlayerLogic_State_Dead : Killed +GameJamDungeon_PlayerLogic_State_Attacking --> GameJamDungeon_PlayerLogic_State_Idle : AttackAnimationFinished +GameJamDungeon_PlayerLogic_State_Disabled --> GameJamDungeon_PlayerLogic_State_Idle : Enable +GameJamDungeon_PlayerLogic_State_Idle --> GameJamDungeon_PlayerLogic_State_Attacking : Attack -GameJam2024Practice_PlayerLogic_State_Alive : OnPhysicsTick → MovementComputed -GameJam2024Practice_PlayerLogic_State_Idle : OnAttack → Attack +GameJamDungeon_PlayerLogic_State_Alive : OnPhysicsTick → MovementComputed +GameJamDungeon_PlayerLogic_State_Idle : OnAttack → Attack -[*] --> GameJam2024Practice_PlayerLogic_State_Disabled +[*] --> GameJamDungeon_PlayerLogic_State_Idle @enduml \ No newline at end of file diff --git a/src/player/state/states/PlayerLogic.State.Alive.cs b/src/player/state/states/PlayerLogic.State.Alive.cs index 94c7fcbb..5728af8e 100644 --- a/src/player/state/states/PlayerLogic.State.Alive.cs +++ b/src/player/state/states/PlayerLogic.State.Alive.cs @@ -12,6 +12,7 @@ namespace GameJamDungeon { public virtual Transition On(in Input.PhysicsTick input) { + var delta = input.Delta; var player = Get(); var settings = Get(); @@ -20,8 +21,9 @@ namespace GameJamDungeon var strafeRightInput = player.GetRightStrafeInputVector(); var transform = player.Transform; - transform.Basis = new Basis(Vector3.Up, settings.RotationSpeed * -rawInput.X) * transform.Basis; - var velocity = player.Basis * new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z) * settings.MoveSpeed; + transform.Basis = new Basis(Vector3.Up, settings.RotationSpeed * -rawInput.X * (float)delta) * transform.Basis; + var moveDirection = new Vector3(strafeRightInput - strafeLeftInput, 0, rawInput.Z); + var velocity = player.Basis * moveDirection * settings.MoveSpeed * settings.Acceleration; Output(new Output.MovementComputed(transform.Basis, velocity)); @@ -38,7 +40,7 @@ namespace GameJamDungeon public Transition On(in Input.Killed input) { GD.Print("Player died"); - return To(); + return To(); } } } diff --git a/src/player/state/states/PlayerLogic.State.Dead.cs b/src/player/state/states/PlayerLogic.State.Dead.cs new file mode 100644 index 00000000..cd32055a --- /dev/null +++ b/src/player/state/states/PlayerLogic.State.Dead.cs @@ -0,0 +1,12 @@ +using Chickensoft.Introspection; + +namespace GameJamDungeon; + +public partial class PlayerLogic +{ + public abstract partial record State + { + [Meta, Id("player_logic_state_dead")] + public partial record Dead : State; + } +} diff --git a/src/sound/music/crossing-the-gate.mp3.import b/src/sound/music/crossing-the-gate.mp3.import deleted file mode 100644 index 2011513e..00000000 --- a/src/sound/music/crossing-the-gate.mp3.import +++ /dev/null @@ -1,19 +0,0 @@ -[remap] - -importer="mp3" -type="AudioStreamMP3" -uid="uid://d2jrktp06xsba" -path="res://.godot/imported/crossing-the-gate.mp3-77e9ee5ef6cc348e3d96e4d008be918a.mp3str" - -[deps] - -source_file="res://src/sound/music/crossing-the-gate.mp3" -dest_files=["res://.godot/imported/crossing-the-gate.mp3-77e9ee5ef6cc348e3d96e4d008be918a.mp3str"] - -[params] - -loop=false -loop_offset=0 -bpm=0 -beat_count=0 -bar_beats=4 diff --git a/src/sound/music/droney.mp3.import b/src/sound/music/droney.mp3.import deleted file mode 100644 index b38e6f48..00000000 --- a/src/sound/music/droney.mp3.import +++ /dev/null @@ -1,19 +0,0 @@ -[remap] - -importer="mp3" -type="AudioStreamMP3" -uid="uid://dfu0fksb6slhx" -path="res://.godot/imported/droney.mp3-7dd594403d939d2237ca85424564e2e7.mp3str" - -[deps] - -source_file="res://src/sound/music/droney.mp3" -dest_files=["res://.godot/imported/droney.mp3-7dd594403d939d2237ca85424564e2e7.mp3str"] - -[params] - -loop=false -loop_offset=0 -bpm=0 -beat_count=0 -bar_beats=4 diff --git a/src/sound/music/tar-winds.mp3.import b/src/sound/music/tar-winds.mp3.import deleted file mode 100644 index a2b1f617..00000000 --- a/src/sound/music/tar-winds.mp3.import +++ /dev/null @@ -1,19 +0,0 @@ -[remap] - -importer="mp3" -type="AudioStreamMP3" -uid="uid://dn2e2hqujlia1" -path="res://.godot/imported/tar-winds.mp3-11fa5d301629f3f4e35607686a62e68e.mp3str" - -[deps] - -source_file="res://src/sound/music/tar-winds.mp3" -dest_files=["res://.godot/imported/tar-winds.mp3-11fa5d301629f3f4e35607686a62e68e.mp3str"] - -[params] - -loop=false -loop_offset=0 -bpm=0 -beat_count=0 -bar_beats=4 diff --git a/src/traits/IKillable.cs b/src/traits/IKillable.cs new file mode 100644 index 00000000..865c16d3 --- /dev/null +++ b/src/traits/IKillable.cs @@ -0,0 +1,7 @@ +namespace GameJamDungeon +{ + public interface IKillable + { + public void Kill(); + } +} diff --git a/src/ui/death_menu/DeathMenu.cs b/src/ui/death_menu/DeathMenu.cs new file mode 100644 index 00000000..a2c2ee2e --- /dev/null +++ b/src/ui/death_menu/DeathMenu.cs @@ -0,0 +1,22 @@ +using Chickensoft.AutoInject; +using Chickensoft.GodotNodeInterfaces; +using Chickensoft.Introspection; +using Godot; + +public interface IDeathMenu : IControl +{ + void FadeIn(); + void FadeOut(); +} + +[Meta(typeof(IAutoNode))] +public partial class DeathMenu : Control, IDeathMenu +{ + public override void _Notification(int what) => this.Notify(what); + + [Node] public IAnimationPlayer AnimationPlayer { get; set; } = default!; + + public void FadeIn() => AnimationPlayer.Play("fade_in"); + + public void FadeOut() => AnimationPlayer.Play("fade_out"); +} diff --git a/src/ui/death_menu/DeathMenu.tscn b/src/ui/death_menu/DeathMenu.tscn new file mode 100644 index 00000000..a04e45ba --- /dev/null +++ b/src/ui/death_menu/DeathMenu.tscn @@ -0,0 +1,82 @@ +[gd_scene load_steps=6 format=3 uid="uid://dbtfgrtgpr4qg"] + +[ext_resource type="Script" path="res://src/ui/death_menu/DeathMenu.cs" id="1_megey"] + +[sub_resource type="Animation" id="Animation_6ji3u"] +resource_name = "fade_out" +length = 0.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.5), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)] +} + +[sub_resource type="Animation" id="Animation_q2nvr"] +resource_name = "fade_in" +length = 0.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.5), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1)] +} + +[sub_resource type="Animation" id="Animation_qmlrq"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 1, 1)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_ek7oy"] +_data = { +&"fade_out": SubResource("Animation_6ji3u"), +&"fade_in": SubResource("Animation_q2nvr"), +&"RESET": SubResource("Animation_qmlrq") +} + +[node name="DeathMenu" type="Control"] +process_mode = 3 +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_megey") + +[node name="ColorRect" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.137255, 0.121569, 0.12549, 1) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +unique_name_in_owner = true +libraries = { +&"": SubResource("AnimationLibrary_ek7oy") +} diff --git a/src/ui/floor_clear/FloorClearMenu.cs b/src/ui/floor_clear/FloorClearMenu.cs new file mode 100644 index 00000000..1d7e669f --- /dev/null +++ b/src/ui/floor_clear/FloorClearMenu.cs @@ -0,0 +1,36 @@ +using Chickensoft.AutoInject; +using Chickensoft.GodotNodeInterfaces; +using Chickensoft.Introspection; +using GameJamDungeon; +using Godot; +using System; +using System.Linq; + +[Meta(typeof(IAutoNode))] +public partial class FloorClearMenu : Control +{ + public override void _Notification(int what) => this.Notify(what); + + [Dependency] + public IGameRepo GameRepo => this.DependOn(); + + [Node] public IAnimationPlayer AnimationPlayer { get; set; } = default!; + + public void FadeIn() => AnimationPlayer.Play("fade_in"); + + public void FadeOut() => AnimationPlayer.Play("fade_out"); + + [Signal] + public delegate void TransitionCompletedEventHandler(); + + private void AnimationPlayer_AnimationStarted(StringName animName) + { + EmitSignal(SignalName.TransitionCompleted); + } + + private void AnimationPlayer_AnimationFinished(StringName animName) + { + var spawnPoints = GetTree().GetNodesInGroup("Exit").OfType(); + GameRepo.CurrentFloor++; + } +} diff --git a/src/ui/floor_clear/FloorClearMenu.tscn b/src/ui/floor_clear/FloorClearMenu.tscn new file mode 100644 index 00000000..ced94dfe --- /dev/null +++ b/src/ui/floor_clear/FloorClearMenu.tscn @@ -0,0 +1,97 @@ +[gd_scene load_steps=6 format=3 uid="uid://pu6gp8de3ck4"] + +[ext_resource type="Script" path="res://src/ui/floor_clear/FloorClearMenu.cs" id="1_q65kq"] + +[sub_resource type="Animation" id="Animation_nc1gg"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("FloorClearMenu/LoadScreen:color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 1, 0)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("FloorClearMenu:modulate") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 1, 1)] +} + +[sub_resource type="Animation" id="Animation_p616x"] +resource_name = "fade_in" +length = 0.3 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("FloorClearMenu:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1)] +} + +[sub_resource type="Animation" id="Animation_dhyvw"] +resource_name = "fade_out" +length = 0.3 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("FloorClearMenu:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_opfbx"] +_data = { +&"fade_out": SubResource("Animation_dhyvw"), +&"fade_in": SubResource("Animation_p616x"), +&"RESET": SubResource("Animation_nc1gg") +} + +[node name="FloorClearMenu" type="Control"] +process_mode = 3 +modulate = Color(1, 1, 1, 0) +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_q65kq") + +[node name="LoadScreen" type="ColorRect" parent="."] +process_mode = 3 +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0.137255, 0.121569, 0.12549, 1) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +unique_name_in_owner = true +root_node = NodePath("../..") +libraries = { +&"": SubResource("AnimationLibrary_opfbx") +} diff --git a/src/ui/in_game_ui/InGameUI.cs b/src/ui/in_game_ui/InGameUI.cs new file mode 100644 index 00000000..4e76309b --- /dev/null +++ b/src/ui/in_game_ui/InGameUI.cs @@ -0,0 +1,49 @@ +using Chickensoft.AutoInject; +using Chickensoft.GodotNodeInterfaces; +using Chickensoft.Introspection; +using Godot; +using System.Threading.Tasks; + +namespace GameJamDungeon; + +public interface IInGameUI : IControl +{ + public Task ShowInventoryScreen(); + + public void HideInventoryScreen(); + + public void ShowMiniMap(); + + public void HideMiniMap(); +} + +[Meta(typeof(IAutoNode))] +public partial class InGameUI : Control, IInGameUI +{ + public override void _Notification(int what) => this.Notify(what); + + [Node] public Control MiniMap { get; set; } = default!; + + [Node] public IInventoryMenu InventoryMenu { get; set; } = default!; + + public void HideInventoryScreen() + { + InventoryMenu.Hide(); + } + + public void HideMiniMap() + { + MiniMap.Hide(); + } + + public async Task ShowInventoryScreen() + { + await InventoryMenu.RedrawInventory(); + InventoryMenu.Show(); + } + + public void ShowMiniMap() + { + MiniMap.Hide(); + } +} diff --git a/src/ui/in_game_ui/InGameUI.tscn b/src/ui/in_game_ui/InGameUI.tscn new file mode 100644 index 00000000..446cff5c --- /dev/null +++ b/src/ui/in_game_ui/InGameUI.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=4 format=3 uid="uid://b1muxus5qdbeu"] + +[ext_resource type="Script" path="res://src/ui/in_game_ui/InGameUI.cs" id="1_sc13i"] +[ext_resource type="PackedScene" uid="uid://bwbofurcvf3yh" path="res://src/minimap/Minimap.tscn" id="2_6sfje"] +[ext_resource type="PackedScene" uid="uid://dlj8qdg1c5048" path="res://src/inventory_menu/InventoryMenu.tscn" id="3_4vcdl"] + +[node name="InGameUI" type="Control"] +process_mode = 3 +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_sc13i") + +[node name="MiniMap" parent="." instance=ExtResource("2_6sfje")] +unique_name_in_owner = true +visible = false +layout_mode = 1 + +[node name="InventoryMenu" parent="." instance=ExtResource("3_4vcdl")] +unique_name_in_owner = true +process_mode = 3 +visible = false +layout_mode = 1 diff --git a/src/ui/pause_menu/PauseMenu.cs b/src/ui/pause_menu/PauseMenu.cs new file mode 100644 index 00000000..a962a0ee --- /dev/null +++ b/src/ui/pause_menu/PauseMenu.cs @@ -0,0 +1,23 @@ +using Chickensoft.AutoInject; +using Chickensoft.GodotNodeInterfaces; +using Chickensoft.Introspection; +using Godot; +using System; + +public interface IPauseMenu : IControl +{ + void FadeIn(); + void FadeOut(); +} + +[Meta(typeof(IAutoNode))] +public partial class PauseMenu : Control, IPauseMenu +{ + public override void _Notification(int what) => this.Notify(what); + + [Node] public IAnimationPlayer AnimationPlayer { get; set; } = default!; + + public void FadeIn() => AnimationPlayer.Play("fade_in"); + + public void FadeOut() => AnimationPlayer.Play("fade_out"); +} diff --git a/src/ui/pause_menu/PauseMenu.tscn b/src/ui/pause_menu/PauseMenu.tscn new file mode 100644 index 00000000..08b74a52 --- /dev/null +++ b/src/ui/pause_menu/PauseMenu.tscn @@ -0,0 +1,79 @@ +[gd_scene load_steps=5 format=3 uid="uid://blbqgw3wosc1w"] + +[sub_resource type="Animation" id="Animation_bium7"] +resource_name = "fade_in" +length = 0.3 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1)] +} + +[sub_resource type="Animation" id="Animation_ccrq3"] +resource_name = "fade_out" +length = 0.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.3), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)] +} + +[sub_resource type="Animation" id="Animation_f1eqn"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:modulate") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Color(1, 1, 1, 1)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_pmp7u"] +_data = { +&"fade_out": SubResource("Animation_ccrq3"), +&"fade_in": SubResource("Animation_bium7"), +&"RESET": SubResource("Animation_f1eqn") +} + +[node name="PauseMenu" type="Control"] +process_mode = 3 +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +unique_name_in_owner = true +libraries = { +&"": SubResource("AnimationLibrary_pmp7u") +} + +[node name="ColorRect" type="ColorRect" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +color = Color(0, 0, 0, 1)