232 lines
6.7 KiB
C#
232 lines
6.7 KiB
C#
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using DonkeysAndDroids;
|
|
using Godot;
|
|
using RobotAndDonkey.Game;
|
|
using RobotAndDonkey.Game.Execution;
|
|
using RobotAndDonkey.Game.Execution.Commands;
|
|
using RobotAndDonkey.Game.Execution.Requests;
|
|
using RobotAndDonkey.Game.Execution.Results;
|
|
using RobotAndDonkey.Game.GameState;
|
|
using RobotAndDonkey.Game.Utils;
|
|
|
|
public partial class Main : CanvasLayer
|
|
{
|
|
public enum EScreenId
|
|
{
|
|
Logo,
|
|
MetaGame,
|
|
CoreLoop,
|
|
Victory
|
|
}
|
|
|
|
public override void _Ready()
|
|
{
|
|
#if DEBUG
|
|
if (!Trace.Listeners.OfType<DefaultTraceListener>().Any())
|
|
Trace.Listeners.Add(new DefaultTraceListener());
|
|
#endif
|
|
Instance = this;
|
|
|
|
m_Runtime = new();
|
|
m_Runtime.Published += (_, e) => OnGameEvent(e);
|
|
|
|
m_Background = GetNode<Background>("Background");
|
|
m_LogoScreen = GetNode<LogoScreen>("LogoScreen");
|
|
m_MetaGameScreen = GetNode<MetaGameScreen>("MetaGameScreen");
|
|
m_CoreLoopScreen = GetNode<CoreLoopScreen>("CoreLoopScreen");
|
|
m_VictoryScreen = GetNode<VictoryScreen>("VictoryScreen");
|
|
OptionsMenu = GetNode<OptionsMenu>("OptionsMenu");
|
|
m_CurrentScreen = m_LogoScreen;
|
|
|
|
Music.Init(this);
|
|
Music.PlaySong(MusicManager.ESong.MetaGame);
|
|
}
|
|
|
|
public void StartMetaGame()
|
|
{
|
|
Music.PlaySong(MusicManager.ESong.MetaGame);
|
|
var tween = GetTree().CreateTween();
|
|
TransitionScreen(m_MetaGameScreen, tween);
|
|
}
|
|
|
|
public void TransitionScreen<T>(T newScreen, Tween tween) where T : Control, IScreen
|
|
{
|
|
newScreen.EnableInputs();
|
|
if (m_CurrentScreen == newScreen)
|
|
return;
|
|
|
|
MoveChild(newScreen, 1);
|
|
var oldControl = (Control)m_CurrentScreen;
|
|
var oldScreen = m_CurrentScreen;
|
|
m_CurrentScreen = newScreen;
|
|
newScreen.Modulate = new(1, 1, 1);
|
|
newScreen.Visible = true;
|
|
newScreen.Activate();
|
|
tween.TweenProperty(oldControl, "modulate", new Color(0, 0, 0, 0), 0.25);
|
|
tween.TweenCallback(Callable.From(() =>
|
|
{
|
|
oldScreen.Deactivate();
|
|
oldControl.Visible = false;
|
|
oldControl.Modulate = new(1, 1, 1);
|
|
}));
|
|
}
|
|
|
|
public void StartCoreLoop(int seed, EDifficulty difficulty, ERobotType selectedRobot)
|
|
{
|
|
Seed = seed;
|
|
CoreLoop = new(new((ulong)seed), new(selectedRobot, difficulty, seed));
|
|
m_Runtime.Start(CoreLoop);
|
|
}
|
|
|
|
private void OnGameEvent(GameEvent gameEvent)
|
|
{
|
|
switch (gameEvent.Payload)
|
|
{
|
|
case NextStepIssued { Step: { } request }:
|
|
{
|
|
m_NextRequest = request;
|
|
if (m_Tween != null)
|
|
break;
|
|
|
|
ProcessNextRequest();
|
|
break;
|
|
}
|
|
|
|
case StepApplied { Results: var results }:
|
|
{
|
|
GD.Print("Results available");
|
|
foreach (var result in results)
|
|
{
|
|
Results.Enqueue(result);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case StateChanged:
|
|
{
|
|
GD.Print("State changed");
|
|
m_Tween = GetTree().CreateTween();
|
|
while (Results.TryDequeue(out var result))
|
|
{
|
|
GD.Print(result.ToString());
|
|
if (m_CurrentScreen.HandleResult(result, m_Tween))
|
|
m_Tween.SetParallel(false);
|
|
else
|
|
GD.Print("> Unhandled result!");
|
|
}
|
|
|
|
m_Tween.TweenCallback(Callable.From(() =>
|
|
{
|
|
m_Tween = null;
|
|
ProcessNextRequest();
|
|
}));
|
|
|
|
break;
|
|
}
|
|
|
|
case StepRejected r:
|
|
{
|
|
GD.Print($"Invalid action: {r.Reason}");
|
|
break;
|
|
}
|
|
|
|
case GameOver:
|
|
{
|
|
GD.Print("Game over");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ProcessNextRequest()
|
|
{
|
|
m_CurrentScreen.DisableInputs();
|
|
CurrentRequest = m_NextRequest;
|
|
m_NextRequest = null;
|
|
GD.Print($"Next step: {CurrentRequest}");
|
|
m_Tween = GetTree().CreateTween();
|
|
var tween = m_Tween;
|
|
switch (CurrentRequest)
|
|
{
|
|
case DrawGlitchRequest drawCardRequest:
|
|
{
|
|
Music.PlaySong(MusicManager.ESong.Shop);
|
|
TransitionScreen(m_CoreLoopScreen, tween);
|
|
m_CoreLoopScreen.DrawGlitch(drawCardRequest.Card, tween);
|
|
break;
|
|
}
|
|
case ImproveRequest:
|
|
{
|
|
TransitionScreen(m_CoreLoopScreen, tween);
|
|
m_CoreLoopScreen.Improve(tween);
|
|
break;
|
|
}
|
|
case GambleRequest:
|
|
{
|
|
TransitionScreen(m_CoreLoopScreen, tween);
|
|
m_CoreLoopScreen.CosmicRays(CoreLoop.BoosterPack, tween);
|
|
break;
|
|
}
|
|
case BufferOverflowRequest:
|
|
{
|
|
TransitionScreen(m_CoreLoopScreen, tween);
|
|
m_CoreLoopScreen.BufferOverflow(tween);
|
|
break;
|
|
}
|
|
case ExecuteProgramRequest:
|
|
{
|
|
Music.PlaySong(MusicManager.ESong.CoreLoop);
|
|
TransitionScreen(m_CoreLoopScreen, tween);
|
|
m_CoreLoopScreen.ExecuteProgram(tween);
|
|
break;
|
|
}
|
|
case ScoringRequest:
|
|
{
|
|
Music.PlaySong(MusicManager.ESong.Scoring);
|
|
TransitionScreen(m_VictoryScreen, tween);
|
|
m_VictoryScreen.Configure(CoreLoop, tween);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Execute(Command command)
|
|
{
|
|
if (command == null)
|
|
return;
|
|
|
|
GD.Print($"Execute {command}");
|
|
m_Runtime.Submit(command);
|
|
}
|
|
|
|
public static Main Instance { get; set; }
|
|
|
|
public Request CurrentRequest { get; private set; } = Request.s_Empty;
|
|
|
|
public Queue<Result> Results { get; } = [];
|
|
|
|
public CoreLoop CoreLoop { get; private set; }
|
|
|
|
public int Seed { get; private set; }
|
|
|
|
public string StringSeed => SeedString.ToString(Seed);
|
|
|
|
public MusicManager Music { get; } = new();
|
|
|
|
public OptionsMenu OptionsMenu { get; private set; }
|
|
|
|
private Background m_Background;
|
|
private CoreLoopScreen m_CoreLoopScreen;
|
|
private IScreen m_CurrentScreen;
|
|
private LogoScreen m_LogoScreen;
|
|
private MetaGameScreen m_MetaGameScreen;
|
|
private Request m_NextRequest;
|
|
|
|
private GameRuntime m_Runtime;
|
|
|
|
private Tween m_Tween;
|
|
private VictoryScreen m_VictoryScreen;
|
|
} |