Big refactor in place: Organize nodes in line with dependency injection expectations, use state machine flow more

This commit is contained in:
2024-09-11 15:33:36 -07:00
parent 6a4eb81529
commit 4d47a7586e
63 changed files with 1123 additions and 469 deletions

View File

@@ -1,4 +1,4 @@
<Project Sdk="Godot.NET.Sdk/4.4.0-dev.1">
<Project Sdk="Godot.NET.Sdk/4.4.0-dev.2">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net8.0</TargetFramework>
@@ -7,10 +7,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.3.0" />
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.2.22" />
<PackageReference Include="Chickensoft.Introspection.Generator" Version="1.5.0" />
<PackageReference Include="Chickensoft.LogicBlocks" Version="5.4.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.4.0" />
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.2.23" />
<PackageReference Include="Chickensoft.Introspection.Generator" Version="1.7.0" />
<PackageReference Include="Chickensoft.LogicBlocks" Version="5.6.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.6.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.4.0" />
<PackageReference Include="SSH.NET" Version="2024.1.0" />
@@ -25,4 +25,13 @@
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Godot.SourceGenerators" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharp" Version="4.4.0-dev.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="GodotSharpEditor" Version="4.4.0-dev.2" />
</ItemGroup>
</Project>

View File

@@ -1,26 +0,0 @@
<Project Sdk="Godot.NET.Sdk/4.3.0">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net8.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.3.0" />
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.2.22" />
<PackageReference Include="Chickensoft.Introspection.Generator" Version="1.5.0" />
<PackageReference Include="Chickensoft.LogicBlocks" Version="5.4.0" />
<PackageReference Include="Chickensoft.LogicBlocks.DiagramGenerator" Version="5.4.0" />
<PackageReference Include="Chickensoft.SaveFileBuilder" Version="1.1.0" />
<PackageReference Include="GodotSharp.SourceGenerators" Version="2.4.0" />
<PackageReference Include="SSH.NET" Version="2024.1.0" />
<PackageReference Include="System.IO.Abstractions" Version="21.0.29" />
<PackageReference Include="Zeroconf" Version="3.6.11" />
</ItemGroup>
<ItemGroup>
<Folder Include="src\map\dungeon\corridor\" />
</ItemGroup>
<ItemGroup>
<None Include=".editorconfig" />
</ItemGroup>
</Project>

View File

@@ -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:

View File

@@ -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=""

View File

@@ -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

View File

@@ -0,0 +1,58 @@
namespace GameJamDungeon;
using Chickensoft.GodotNodeInterfaces;
using Godot;
public interface IDimmableAudioStreamPlayer : IAudioStreamPlayer
{
/// <summary>Fade this dimmable audio stream track in.</summary>
public void FadeIn();
/// <summary>Fade this dimmable audio stream track out.</summary>
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<ITween>(CreateTween());
FadeTween.TweenProperty(
this,
"volume_db",
volumeDb,
FADE_DURATION
).SetTrans(Tween.TransitionType.Circ).SetEase(ease);
}
}

21
src/audio/InGameAudio.cs Normal file
View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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]

View File

@@ -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

View File

@@ -8,7 +8,7 @@ namespace GameJamDungeon
public partial record State
{
[Meta, Id("enemy_logic_state_alive")]
public abstract partial record Alive : State, IGet<Input.HitByPlayer>, IGet<Input.Killed>, IGet<Input.AttackTimer>
public abstract partial record Alive : State, IGet<Input.HitByPlayer>, IGet<Input.AttackTimer>
{
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<Idle>();
}
public Transition On(in Input.AttackTimer input)
{
return To<Attack>();

View File

@@ -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<IAppRepo>();
[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<IDungeonFloor> 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<IDungeonFloor> { 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<Resource>("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<Marker3D>();
Teleport.GlobalPosition = spawnPoints.Last().GlobalPosition;
GameRepo.CurrentFloor++;
}
public override void _UnhandledInput(InputEvent @event)
{
if (@event.IsActionPressed(GameInputs.Inventory))

View File

@@ -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")

View File

@@ -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; }
}
}

View File

@@ -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;
}
}
}

View File

@@ -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<IInventoryItem> 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;
}
}
}

36
src/game/GameLogic.g.puml Normal file
View File

@@ -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

View File

@@ -7,6 +7,8 @@ namespace GameJamDungeon;
public interface IGameRepo : IDisposable
{
public void OnGameEnded();
event Action? Ended;
AutoProp<List<IInventoryItem>> InventoryItems { get; }

View File

@@ -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<IGameRepo>().Pause(); Output(new Output.ShowFloorClearMenu()); });
this.OnExit(() => { Output(new Output.HideFloorClearMenu()); });
}
}
}
}
}

View File

@@ -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<IGameRepo>().Pause());
this.OnExit(() => Output(new Output.ExitPauseMenu()));
}
public virtual Transition On(in Input.PauseButtonPressed input) => To<Resuming>();
}
}
}
}

View File

@@ -8,7 +8,11 @@ namespace GameJamDungeon
public partial record State
{
[Meta]
public partial record Playing : State, IGet<Input.InventoryMenuToggle>, IGet<Input.MiniMapButtonPressed>, IGet<Input.GameOver>, IGet<Input.LoadNextFloor>
public partial record Playing : State,
IGet<Input.InventoryMenuToggle>,
IGet<Input.MiniMapButtonPressed>,
IGet<Input.GameOver>,
IGet<Input.FloorExitReached>
{
public Playing()
{
@@ -24,16 +28,9 @@ namespace GameJamDungeon
public Transition On(in Input.MiniMapButtonPressed input) => To<MinimapOpen>();
public Transition On(in Input.GameOver input)
{
return To<Quit>();
}
public Transition On(in Input.GameOver input) => To<Quit>();
public Transition On(in Input.LoadNextFloor input)
{
Output(new Output.LoadNextFloor());
return ToSelf();
}
public Transition On(in Input.FloorExitReached input) => To<FloorCleared>();
}
}
}

View File

@@ -12,7 +12,7 @@ namespace GameJamDungeon
{
public Quit()
{
this.OnEnter(() => Output(new Output.GameOver()));
this.OnEnter(() => Output(new Output.ShowLostScreen()));
}
}
}

View File

@@ -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<Input.PauseMenuTransitioned>
{
public Resuming()
{
this.OnEnter(() => Get<IGameRepo>().Resume());
this.OnExit(() => Output(new Output.HidePauseMenu()));
}
public Transition On(in Input.PauseMenuTransitioned input) =>
To<Playing>();
}
}
}

View File

@@ -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<Input.InventoryMenuToggle>, IGet<Input.MiniMapButtonReleased>
{
public Paused()
{
this.OnEnter(() => Get<IGameRepo>().Pause());
this.OnExit(() => Output(new Output.SetPauseMode(false)));
}
public virtual Transition On(in Input.InventoryMenuToggle input) => To<Playing>();
public virtual Transition On(in Input.MiniMapButtonReleased input) => To<Playing>();
}
}
}
}

56
src/map/Map.cs Normal file
View File

@@ -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<IDungeonFloor> 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<IDungeonFloor> 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<Resource>("res://src/ui/dialogue/FloorExit.dialogue");
DialogueController.ShowDialogue(dialogueResource, "floor_exit");
}
}

33
src/map/Map.tscn Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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"]

View File

@@ -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}";

View File

@@ -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="."]

View File

@@ -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; }
}
}

View File

@@ -7,6 +7,8 @@
public float MoveSpeed { get; set; }
public float RotationSpeed { get; set; }
public float Acceleration { get; set; }
}
}
}

View File

@@ -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

View File

@@ -12,6 +12,7 @@ namespace GameJamDungeon
{
public virtual Transition On(in Input.PhysicsTick input)
{
var delta = input.Delta;
var player = Get<IPlayer>();
var settings = Get<Settings>();
@@ -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<Disabled>();
return To<Dead>();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

7
src/traits/IKillable.cs Normal file
View File

@@ -0,0 +1,7 @@
namespace GameJamDungeon
{
public interface IKillable
{
public void Kill();
}
}

View File

@@ -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");
}

View File

@@ -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")
}

View File

@@ -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<IGameRepo>();
[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<Marker3D>();
GameRepo.CurrentFloor++;
}
}

View File

@@ -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")
}

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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)