Re-introduce prototype code

This commit is contained in:
2024-08-23 00:39:15 -07:00
parent 8b3d1bed8a
commit 2fb0c364ca
62 changed files with 1685 additions and 187 deletions

77
src/game/Game.cs Normal file
View File

@@ -0,0 +1,77 @@
namespace GameJamDungeon;
using Chickensoft.AutoInject;
using Chickensoft.GodotNodeInterfaces;
using Chickensoft.Introspection;
using Godot;
public interface IGame : IProvide<IGameRepo>, INode3D
{
}
[Meta(typeof(IAutoNode))]
public partial class Game : Node3D, IGame
{
public override void _Notification(int what) => this.Notify(what);
IGameRepo IProvide<IGameRepo>.Value() => GameRepo;
public IGameLogic GameLogic { get; set; } = default!;
public IGameRepo GameRepo { get; set; } = default!;
public GameLogic.IBinding GameBinding { get; set; } = default!;
[Dependency] public IAppRepo AppRepo => this.DependOn<IAppRepo>();
public void Setup()
{
GameRepo = new GameRepo();
GameLogic = new GameLogic();
GameLogic.Set(GameRepo);
GameLogic.Set(AppRepo);
}
public void OnResolved()
{
GameBinding = GameLogic.Bind();
GameBinding
.Handle((in GameLogic.Output.StartGame _) => { GameRepo.Resume(); })
.Handle((in GameLogic.Output.SetPauseMode output) => { CallDeferred(nameof(SetPauseMode), output.IsPaused); })
.Handle((in GameLogic.Output.GameOver _) => { AppRepo.OnGameOver(); });
GameLogic.Input(new GameLogic.Input.Initialize());
this.Provide();
GameLogic.Start();
}
public override void _Input(InputEvent @event)
{
if (Input.IsActionJustPressed(GameInputs.Inventory))
{
GD.Print("Inventory button pressed");
GameLogic.Input(new GameLogic.Input.InventoryMenuButtonPressed());
}
if (Input.IsActionJustPressed(GameInputs.MiniMap))
{
GD.Print("MiniMap button pressed");
GameLogic.Input(new GameLogic.Input.MiniMapButtonPressed());
}
if (Input.IsActionJustReleased(GameInputs.MiniMap))
{
GD.Print("MiniMap button released");
GameLogic.Input(new GameLogic.Input.MiniMapButtonReleased());
}
}
private void SetPauseMode(bool isPaused)
{
if (GetTree() != null)
GetTree().Paused = isPaused;
}
public void OnStart() => GameLogic.Input(new GameLogic.Input.Start());
}

83
src/game/Game.tscn Normal file
View File

@@ -0,0 +1,83 @@
[gd_scene load_steps=8 format=3 uid="uid://33ek675mfb5n"]
[ext_resource type="Script" path="res://src/game/Game.cs" id="1_ytcii"]
[ext_resource type="PackedScene" uid="uid://wg25dg65ksgg" path="res://src/map/dungeon/DungeonGenerator.tscn" id="2_cgboj"]
[ext_resource type="PackedScene" uid="uid://cfecvvav8kkp6" path="res://src/player/Player.tscn" id="3_kk6ly"]
[ext_resource type="PackedScene" uid="uid://dhpwwqow1ahrc" path="res://src/map/dungeon/rooms/Room1.tscn" id="4_56rmd"]
[ext_resource type="Script" path="res://addons/SimpleDungeons/DungeonRoom3D.gd" id="5_5i8m5"]
[ext_resource type="PackedScene" uid="uid://bn4gslp2gk8ds" path="res://src/map/dungeon/corridor/Corridor.tscn" id="6_5fcqc"]
[sub_resource type="Environment" id="Environment_fke5g"]
[node name="Game" type="Node3D"]
script = ExtResource("1_ytcii")
[node name="DungeonGenerator3D" parent="." instance=ExtResource("2_cgboj")]
[node name="WorldEnvironment" type="WorldEnvironment" parent="DungeonGenerator3D"]
environment = SubResource("Environment_fke5g")
[node name="Player" parent="DungeonGenerator3D" instance=ExtResource("3_kk6ly")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.55927, -4.70883, 25.1515)
[node name="RoomsContainer" type="Node3D" parent="DungeonGenerator3D"]
[node name="DungeonRoom3D_0" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("4_56rmd")]
transform = Transform3D(1.19249e-08, 0, -1, 0, 1, 0, 1, 0, 1.19249e-08, 5, 0, 15)
script = ExtResource("5_5i8m5")
[node name="DungeonRoom3D_1" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("4_56rmd")]
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -25, 0, -25)
script = ExtResource("5_5i8m5")
[node name="Corridor_2" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, 15)
script = ExtResource("5_5i8m5")
[node name="Corridor_3" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, 5)
script = ExtResource("5_5i8m5")
[node name="Corridor_4" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, -5)
script = ExtResource("5_5i8m5")
[node name="Corridor_5" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, -15)
script = ExtResource("5_5i8m5")
[node name="Corridor_6" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -15)
script = ExtResource("5_5i8m5")
[node name="Corridor_7" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -25)
script = ExtResource("5_5i8m5")
[node name="Corridor_8" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0, 15)
script = ExtResource("5_5i8m5")
[node name="Corridor_9" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0, 5)
script = ExtResource("5_5i8m5")
[node name="Corridor_10" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0, 5)
script = ExtResource("5_5i8m5")
[node name="Corridor_11" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -35, 0, -25)
script = ExtResource("5_5i8m5")
[node name="Corridor_12" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -35, 0, -15)
script = ExtResource("5_5i8m5")
[node name="Corridor_13" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -25, 0, -15)
script = ExtResource("5_5i8m5")
[node name="Corridor_14" type="Node3D" parent="DungeonGenerator3D/RoomsContainer" instance=ExtResource("6_5fcqc")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, -5)
script = ExtResource("5_5i8m5")

10
src/game/GameData.cs Normal file
View File

@@ -0,0 +1,10 @@
using Chickensoft.Introspection;
namespace GameJamDungeon
{
[Meta, Id("game_data")]
public partial record GameData
{
public required PlayerData PlayerData { get; init; }
}
}

View File

@@ -0,0 +1,20 @@
namespace GameJamDungeon
{
public partial class GameLogic
{
public static class Input
{
public readonly record struct Start;
public readonly record struct Initialize;
public readonly record struct InventoryMenuButtonPressed;
public readonly record struct MiniMapButtonPressed;
public readonly record struct MiniMapButtonReleased;
public readonly record struct GameOver;
}
}
}

View File

@@ -0,0 +1,24 @@
using System.Collections.Generic;
namespace GameJamDungeon
{
public partial class GameLogic
{
public static class Output
{
public readonly record struct StartGame();
public readonly record struct SetInventoryMode(List<InventoryItem> Inventory);
public readonly record struct HideInventory();
public readonly record struct SetPauseMode(bool IsPaused);
public readonly record struct ShowMiniMap();
public readonly record struct HideMiniMap();
public readonly record struct GameOver();
}
}
}

View File

@@ -0,0 +1,28 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace GameJamDungeon
{
public partial class GameLogic
{
[Meta]
public abstract partial record State : StateLogic<State>
{
protected State()
{
OnAttach(() =>
{
var gameRepo = Get<IGameRepo>();
gameRepo.IsPaused.Sync += OnIsPaused;
});
OnDetach(() =>
{
var gameRepo = Get<IGameRepo>();
gameRepo.IsPaused.Sync -= OnIsPaused;
});
}
public void OnIsPaused(bool isPaused) => Output(new Output.SetPauseMode(isPaused));
}
}
}

14
src/game/GameLogic.cs Normal file
View File

@@ -0,0 +1,14 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace GameJamDungeon
{
public interface IGameLogic : ILogicBlock<GameLogic.State>;
[Meta]
[LogicBlock(typeof(State), Diagram = true)]
public partial class GameLogic : LogicBlock<GameLogic.State>, IGameLogic
{
public override Transition GetInitialState() => To<State.MenuBackdrop>();
}
}

98
src/game/IGameRepo.cs Normal file
View File

@@ -0,0 +1,98 @@
using Chickensoft.Collections;
using Godot;
using System;
using System.Collections.Generic;
namespace GameJamDungeon
{
public interface IGameRepo : IDisposable
{
event Action? Ended;
IAutoProp<List<InventoryItem>> InventoryItems { get; }
IAutoProp<bool> IsInventoryScreenOpened { get; }
IAutoProp<bool> IsPaused { get; }
void Pause();
void Resume();
IAutoProp<Vector3> PlayerGlobalPosition { get; }
void SetPlayerGlobalPosition(Vector3 playerGlobalPosition);
}
public class GameRepo : IGameRepo
{
public event Action? Ended;
private readonly AutoProp<List<InventoryItem>> _inventoryItems;
private readonly AutoProp<bool> _isInventoryScreenOpened;
public IAutoProp<List<InventoryItem>> InventoryItems => _inventoryItems;
public IAutoProp<bool> IsInventoryScreenOpened => _isInventoryScreenOpened;
public IAutoProp<Vector3> PlayerGlobalPosition => _playerGlobalPosition;
private readonly AutoProp<Vector3> _playerGlobalPosition;
public IAutoProp<bool> IsPaused => _isPaused;
private readonly AutoProp<bool> _isPaused;
private bool _disposedValue;
public GameRepo()
{
_inventoryItems = new AutoProp<List<InventoryItem>>([]);
_isInventoryScreenOpened = new AutoProp<bool>(false);
_isPaused = new AutoProp<bool>(false);
_playerGlobalPosition = new AutoProp<Vector3>(Vector3.Zero);
}
public void Pause()
{
_isPaused.OnNext(true);
GD.Print("Paused");
}
public void Resume()
{
_isPaused.OnNext(false);
GD.Print("Resume");
}
public void SetPlayerGlobalPosition(Vector3 playerGlobalPosition) => _playerGlobalPosition.OnNext(playerGlobalPosition);
public void OnGameEnded()
{
Pause();
Ended?.Invoke();
}
protected void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
_playerGlobalPosition.OnCompleted();
_playerGlobalPosition.Dispose();
_inventoryItems.OnCompleted();
_inventoryItems.Dispose();
_isInventoryScreenOpened.OnCompleted();
_isInventoryScreenOpened.Dispose();
}
_disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}

View File

@@ -0,0 +1,20 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace GameJamDungeon
{
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record Quit : State
{
public Quit()
{
this.OnEnter(() => Output(new Output.GameOver()));
}
}
}
}
}

View File

@@ -0,0 +1,22 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace GameJamDungeon
{
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record InventoryOpened : State, IGet<Input.InventoryMenuButtonPressed>
{
public InventoryOpened()
{
this.OnEnter(() => { Get<IGameRepo>().Pause(); Output(new Output.SetInventoryMode(Get<IGameRepo>().InventoryItems.Value)); });
this.OnExit(() => { Output(new Output.HideInventory()); });
}
public Transition On(in Input.InventoryMenuButtonPressed input) => To<Playing>();
}
}
}
}

View File

@@ -0,0 +1,29 @@
using Chickensoft.Introspection;
namespace GameJamDungeon
{
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record MenuBackdrop : State, IGet<Input.Start>, IGet<Input.Initialize>
{
public MenuBackdrop()
{
OnAttach(() => Get<IAppRepo>().GameEntered += OnGameEntered);
OnDetach(() => Get<IAppRepo>().GameEntered -= OnGameEntered);
}
public void OnGameEntered() => Input(new Input.Start());
public Transition On(in Input.Start input) => To<Playing>();
public Transition On(in Input.Initialize input)
{
return ToSelf();
}
}
}
}
}

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 MinimapOpen : State, IGet<Input.MiniMapButtonReleased>
{
public MinimapOpen()
{
this.OnEnter(() => { Get<IGameRepo>().Pause(); Output(new Output.ShowMiniMap()); });
this.OnExit(() => { Output(new Output.HideMiniMap()); });
}
public Transition On(in Input.MiniMapButtonReleased input) => To<Playing>();
}
}
}
}

View File

@@ -0,0 +1,26 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace GameJamDungeon
{
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record Paused : State, IGet<Input.InventoryMenuButtonPressed>, IGet<Input.MiniMapButtonReleased>
{
public Paused()
{
this.OnEnter(() => Get<IGameRepo>().Pause());
this.OnExit(() => Output(new Output.SetPauseMode(false)));
}
public virtual Transition On(in Input.InventoryMenuButtonPressed input) => To<Playing>();
public virtual Transition On(in Input.MiniMapButtonReleased input) => To<Playing>();
}
}
}
}

View File

@@ -0,0 +1,34 @@
using Chickensoft.Introspection;
using Chickensoft.LogicBlocks;
namespace GameJamDungeon
{
public partial class GameLogic
{
public partial record State
{
[Meta]
public partial record Playing : State, IGet<Input.InventoryMenuButtonPressed>, IGet<Input.MiniMapButtonPressed>, IGet<Input.GameOver>
{
public Playing()
{
this.OnEnter(() => { Output(new Output.StartGame()); Get<IGameRepo>().Resume(); });
OnAttach(() => Get<IGameRepo>().Ended += OnEnded);
OnDetach(() => Get<IGameRepo>().Ended -= OnEnded);
}
public void OnEnded() => Input(new Input.GameOver());
public Transition On(in Input.InventoryMenuButtonPressed input) => To<InventoryOpened>();
public Transition On(in Input.MiniMapButtonPressed input) => To<MinimapOpen>();
public Transition On(in Input.GameOver input)
{
return To<Quit>();
}
}
}
}
}