Files
TheriapolisV3/Theriapolis.Game/Screens/DefeatedScreen.cs
T
Christopher Wiebe b451f83174 Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback
anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md).
All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:40:51 -07:00

99 lines
3.5 KiB
C#

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Myra.Graphics2D;
using Myra.Graphics2D.Brushes;
using Myra.Graphics2D.UI;
using Theriapolis.Core;
using Theriapolis.Game.Platform;
namespace Theriapolis.Game.Screens;
/// <summary>
/// Phase 5 M6: shown when the player's death-save loop fails (3 cumulative
/// failures). Permadeath per the §9 resolved decision — the only option is
/// "Return to Title". The autosave_combat slot persists, so the player can
/// load it from the title screen and retry.
/// </summary>
public sealed class DefeatedScreen : IScreen
{
private readonly string _causeOfDeath;
private Game1 _game = null!;
private Desktop _desktop = null!;
private bool _enterWas = true;
private bool _escWas = true;
public DefeatedScreen(string causeOfDeath = "")
{
_causeOfDeath = causeOfDeath ?? "";
}
public void Initialize(Game1 game)
{
_game = game;
var root = new VerticalStackPanel
{
Spacing = 14,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Padding = new Thickness(50, 40, 50, 40),
Background = new SolidBrush(new Color(20, 0, 0, 230)),
};
root.Widgets.Add(new Label { Text = "YOU HAVE DIED", HorizontalAlignment = HorizontalAlignment.Center });
root.Widgets.Add(new Label { Text = " " });
if (!string.IsNullOrEmpty(_causeOfDeath))
{
root.Widgets.Add(new Label { Text = _causeOfDeath, HorizontalAlignment = HorizontalAlignment.Center });
root.Widgets.Add(new Label { Text = " " });
}
root.Widgets.Add(new Label
{
Text = $"Your last autosave is at slot \"{C.SAVE_SLOT_AUTOSAVE_COMBAT}\".",
HorizontalAlignment = HorizontalAlignment.Center,
});
root.Widgets.Add(new Label
{
Text = "Load from the title to retry the encounter.",
HorizontalAlignment = HorizontalAlignment.Center,
});
root.Widgets.Add(new Label { Text = " " });
var ret = new TextButton { Text = "Return to Title (ENTER)", Width = 280, HorizontalAlignment = HorizontalAlignment.Center };
ret.Click += (_, _) => ReturnToTitle();
root.Widgets.Add(ret);
_desktop = new Desktop { Root = root };
}
private void ReturnToTitle()
{
// Pop everything above the TitleScreen. Stack at this point is:
// Title → CharacterCreation (popped) → WorldGenProgress (popped) →
// PlayScreen → CombatHUD (popped earlier) → DefeatedScreen.
// So we need to pop DefeatedScreen + PlayScreen = 2 pops.
// ScreenManager.Pop is queue-based now, so multiple calls all apply.
_game.Screens.Pop();
_game.Screens.Pop();
}
public void Update(GameTime gt)
{
var ks = Keyboard.GetState();
bool enter = ks.IsKeyDown(Keys.Enter);
bool esc = ks.IsKeyDown(Keys.Escape);
bool enterPressed = enter && !_enterWas;
bool escPressed = esc && !_escWas;
_enterWas = enter; _escWas = esc;
if (enterPressed || escPressed) ReturnToTitle();
}
public void Draw(GameTime gt, SpriteBatch sb)
{
// Don't clear — leave the play-screen's last frame underneath.
_desktop.Render();
}
public void Deactivate() { }
public void Reactivate() { }
}