Engine-Pong/Shared/Behaviours/PongGameStarter.cs
2025-07-27 18:58:20 +03:00

108 lines
3.7 KiB
C#

using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Debug;
using Syntriax.Engine.Integration.MonoGame;
using Syntriax.Engine.Network;
using Syntriax.Engine.Systems.Input;
using Syntriax.Engine.Systems.Time;
using Syntriax.Engine.Systems.Tween;
namespace Pong.Behaviours;
public class PongGameStarter : Behaviour, INetworkEntity, IFirstFrameUpdate, ILoadContent,
IPacketListenerServer<PongGameStarter.RequestStartPacket>,
IPacketListenerClient<PongGameStarter.RequestStartPacket>
{
private const float START_COUNTDOWN = 3f;
private INetworkCommunicatorServer? networkServer = null;
private INetworkCommunicatorClient? networkClient = null;
private ITweenManager? tweenManager = null;
private PongManager pongManager = null!;
private ILogger? logger = null;
private Label? label = null;
private TickerTimer timer = null!;
private SoundEffectInstance? tickSoundEffect = null;
private SoundEffectInstance? startSoundEffect = null;
public void FirstActiveFrame()
{
IButtonInputs<Keys>? buttonInputs = Universe.FindBehaviour<IButtonInputs<Keys>>();
buttonInputs?.RegisterOnRelease(Keys.Space, (_, _1) => networkClient?.SendToServer(new RequestStartPacket()));
networkClient = Universe.FindBehaviour<INetworkCommunicatorClient>();
networkServer = Universe.FindBehaviour<INetworkCommunicatorServer>();
tweenManager = Universe.FindBehaviour<ITweenManager>();
pongManager = BehaviourController.GetRequiredBehaviourInParent<PongManager>();
label = BehaviourController.GetRequiredBehaviour<Label>();
logger = Universe.FindBehaviour<ILogger>();
if (!BehaviourController.TryGetBehaviour(out timer!))
{
timer = BehaviourController.AddBehaviour<TickerTimer>();
timer.OnStarted.AddListener(OnCountdownStart);
timer.OnTick.AddListener(DisplayCountdown);
timer.OnStopped.AddListener(StartPong);
}
}
public void LoadContent(ContentManager content)
{
tickSoundEffect = content.Load<SoundEffect>("Audio/TimerTick").CreateInstance();
startSoundEffect = content.Load<SoundEffect>("Audio/TimerEnd").CreateInstance();
}
private void OnCountdownStart(IReadOnlyTimer sender)
{
pongManager.Reset();
DisplayCountdown(timer);
}
private void DisplayCountdown(ITicker sender)
{
tickSoundEffect?.Play();
if (label != null)
{
label.Text = $"{START_COUNTDOWN - timer.TickCounter}";
label.Color = new ColorRGBA(255, 255, 255, 255);
if (tweenManager is not null)
label.Color.TweenColor(tweenManager, 1f, new ColorRGBA(255, 255, 255, 0), (x) => label.Color = x);
}
}
private void StartPong(IReadOnlyTimer sender)
{
startSoundEffect?.Play();
pongManager.Start();
}
void IPacketListenerServer<RequestStartPacket>.OnServerPacketArrived(IConnection sender, RequestStartPacket packet)
{
logger?.Log(this, $"{sender} requested start");
if (pongManager.IsGameInProgress)
{
logger?.Log(this, $"The game is already in progress");
return;
}
timer.Start(START_COUNTDOWN);
networkServer?.SendToAll(packet);
}
void IPacketListenerClient<RequestStartPacket>.OnClientPacketArrived(IConnection sender, RequestStartPacket packet)
{
logger?.Log(this, $"Server is starting the game");
timer.Start(START_COUNTDOWN - sender.Ping);
}
private class RequestStartPacket : INetworkPacket;
}