Engine-Pong/Shared/Behaviours/PongManagerBehaviour.cs

102 lines
3.0 KiB
C#

using System;
using Microsoft.Xna.Framework.Input;
using Syntriax.Engine.Core;
using Syntriax.Engine.Network;
using Syntriax.Engine.Systems.Input;
namespace Pong.Behaviours;
public class PongManagerBehaviour : Behaviour, INetworkEntity, IFirstFrameUpdate,
IPacketListenerServer<PongManagerBehaviour.RequestStartPacket>
{
public Action<PongManagerBehaviour>? OnReset { get; set; } = null;
public Action<PongManagerBehaviour>? OnFinished { get; set; } = null;
public Action<PongManagerBehaviour>? OnScored { get; set; } = null;
private Random random = new();
private BallBehaviour ball = null!;
private INetworkCommunicatorClient? networkClient = null!;
private INetworkCommunicatorServer? networkServer = null;
public int ScoreLeft { get; private set; } = 0;
public int ScoreRight { get; private set; } = 0;
public int ScoreSum => ScoreLeft + ScoreRight;
public int WinScore { get; } = 5;
public PongManagerBehaviour() => WinScore = 5;
public PongManagerBehaviour(int winScore) => WinScore = winScore;
public void FirstActiveFrame()
{
IButtonInputs<Keys> buttonInputs = Universe.FindRequired<IButtonInputs<Keys>>();
buttonInputs.RegisterOnRelease(Keys.Space, (_, _1) => networkClient?.SendToServer(new RequestStartPacket()));
ball = Universe.FindRequiredBehaviour<BallBehaviour>();
networkClient = Universe.FindBehaviour<INetworkCommunicatorClient>();
networkServer = Universe.FindBehaviour<INetworkCommunicatorServer>();
}
public void ScoreToLeft()
{
ScoreLeft++;
OnScored?.Invoke(this);
CheckFinish();
}
public void ScoreToRight()
{
ScoreRight++;
OnScored?.Invoke(this);
CheckFinish();
}
public void Reset()
{
ScoreLeft = ScoreRight = 0;
ball.ResetBall();
ball.LaunchBall(GetBallLaunchDirection());
OnReset?.Invoke(this);
}
private void CheckFinish()
{
int halfwayScore = (int)(WinScore * .5f);
ball.ResetBall();
if (ScoreLeft > halfwayScore || ScoreRight > halfwayScore)
{
OnFinished?.Invoke(this);
return;
}
ball.ResetBall();
ball.LaunchBall(GetBallLaunchDirection());
}
private Vector2D GetBallLaunchDirection()
{
const float AllowedRadians = 45f * Syntriax.Engine.Core.Math.DegreeToRadian;
float rotation = (float)random.NextDouble() * 2f * AllowedRadians - AllowedRadians;
bool isBackwards = (random.Next() % 2) == 1;
return Vector2D.Right.Rotate(isBackwards ? rotation + Syntriax.Engine.Core.Math.PI : rotation);
}
void IPacketListenerServer<RequestStartPacket>.OnServerPacketArrived(string sender, RequestStartPacket packet)
{
if (ball.RigidBody.Velocity.MagnitudeSquared > 0.01f)
return;
ball.LaunchBall(GetBallLaunchDirection());
}
private class RequestStartPacket : INetworkPacket;
}