feat: game start countdown added
This commit is contained in:
parent
863c3a8d7a
commit
a781d92996
@ -1,11 +1,15 @@
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Integration.MonoGame;
|
||||
using Syntriax.Engine.Network;
|
||||
using Syntriax.Engine.Physics2D;
|
||||
using Syntriax.Engine.Systems.Tween;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class Ball : Behaviour2D, IFirstFrameUpdate, IPhysicsUpdate, INetworkEntity,
|
||||
public class Ball : Behaviour2D, IFirstFrameUpdate, ILoadContent, IPhysicsUpdate, INetworkEntity,
|
||||
IPacketListenerClient<Ball.BallUpdatePacket>,
|
||||
IPacketListenerClient<Ball.BallResetPacket>
|
||||
{
|
||||
@ -19,6 +23,8 @@ public class Ball : Behaviour2D, IFirstFrameUpdate, IPhysicsUpdate, INetworkEnti
|
||||
private INetworkCommunicatorServer? networkServer = null;
|
||||
private ITween? networkTween = null;
|
||||
|
||||
private SoundEffect? bounceSoundEffect = null;
|
||||
|
||||
public void FirstActiveFrame()
|
||||
{
|
||||
BehaviourController.GetRequiredBehaviour<ICollider2D>().OnCollisionDetected.AddListener(OnCollisionDetected);
|
||||
@ -28,6 +34,11 @@ public class Ball : Behaviour2D, IFirstFrameUpdate, IPhysicsUpdate, INetworkEnti
|
||||
networkServer = Universe.FindBehaviour<INetworkCommunicatorServer>();
|
||||
}
|
||||
|
||||
public void LoadContent(ContentManager content)
|
||||
{
|
||||
bounceSoundEffect = content.Load<SoundEffect>("Audio/Bounce");
|
||||
}
|
||||
|
||||
public void LaunchBall(Vector2D launchDirection)
|
||||
{
|
||||
ResetBall();
|
||||
@ -74,6 +85,9 @@ public class Ball : Behaviour2D, IFirstFrameUpdate, IPhysicsUpdate, INetworkEnti
|
||||
else
|
||||
Transform.Position = packet.Position;
|
||||
|
||||
if (RigidBody.Velocity.MagnitudeSquared >= .01f)
|
||||
bounceSoundEffect?.Play();
|
||||
|
||||
RigidBody.Velocity = packet.Velocity;
|
||||
physicsEngine2D.StepIndividual(RigidBody, sender.Ping);
|
||||
}
|
||||
|
96
Shared/Behaviours/PongGameStarter.cs
Normal file
96
Shared/Behaviours/PongGameStarter.cs
Normal file
@ -0,0 +1,96 @@
|
||||
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.Core.Exceptions;
|
||||
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,
|
||||
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!;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCountdownStart(IReadOnlyTimer sender)
|
||||
{
|
||||
pongManager.Reset();
|
||||
DisplayCountdown(timer);
|
||||
}
|
||||
|
||||
private void DisplayCountdown(ITicker sender)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
@ -1,16 +1,12 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Core.Debug;
|
||||
using Syntriax.Engine.Network;
|
||||
using Syntriax.Engine.Systems.Input;
|
||||
|
||||
namespace Pong.Behaviours;
|
||||
|
||||
public class PongManager : Behaviour, INetworkEntity, IFirstFrameUpdate,
|
||||
IPacketListenerServer<PongManager.RequestStartPacket>,
|
||||
IPacketListenerClient<PongManager.ScorePacket>
|
||||
{
|
||||
public Action<PongManager>? OnReset { get; set; } = null;
|
||||
@ -18,9 +14,7 @@ public class PongManager : Behaviour, INetworkEntity, IFirstFrameUpdate,
|
||||
public Action<PongManager>? OnScoreUpdated { get; set; } = null;
|
||||
|
||||
private Random random = new();
|
||||
private Ball ball = null!;
|
||||
|
||||
private INetworkCommunicatorClient? networkClient = null!;
|
||||
private INetworkCommunicatorServer? networkServer = null;
|
||||
private ILogger? logger = null;
|
||||
|
||||
@ -29,17 +23,16 @@ public class PongManager : Behaviour, INetworkEntity, IFirstFrameUpdate,
|
||||
public int ScoreSum => ScoreLeft + ScoreRight;
|
||||
|
||||
public int WinScore { get; } = 5;
|
||||
public Ball Ball { get; private set; } = null!;
|
||||
|
||||
public bool IsGameInProgress { get; private set; } = false;
|
||||
|
||||
public PongManager() => WinScore = 5;
|
||||
public PongManager(int winScore) => WinScore = winScore;
|
||||
|
||||
public void FirstActiveFrame()
|
||||
{
|
||||
IButtonInputs<Keys>? buttonInputs = Universe.FindBehaviour<IButtonInputs<Keys>>();
|
||||
buttonInputs?.RegisterOnRelease(Keys.Space, (_, _1) => networkClient?.SendToServer(new RequestStartPacket()));
|
||||
|
||||
ball = Universe.FindRequiredBehaviour<Ball>();
|
||||
networkClient = Universe.FindBehaviour<INetworkCommunicatorClient>();
|
||||
Ball = Universe.FindRequiredBehaviour<Ball>();
|
||||
networkServer = Universe.FindBehaviour<INetworkCommunicatorServer>();
|
||||
logger = Universe.FindBehaviour<ILogger>();
|
||||
}
|
||||
@ -60,18 +53,34 @@ public class PongManager : Behaviour, INetworkEntity, IFirstFrameUpdate,
|
||||
PostScoreUpdate();
|
||||
}
|
||||
|
||||
public bool Start()
|
||||
{
|
||||
if (networkServer is null)
|
||||
return false;
|
||||
|
||||
if (Ball.RigidBody.Velocity.MagnitudeSquared > 0.01f)
|
||||
return false;
|
||||
|
||||
Reset();
|
||||
IsGameInProgress = true;
|
||||
PostScoreUpdate();
|
||||
logger?.Log(this, $"Game started");
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ScoreLeft = ScoreRight = 0;
|
||||
IsGameInProgress = false;
|
||||
|
||||
PostScoreUpdate();
|
||||
Ball.ResetBall();
|
||||
|
||||
OnReset?.Invoke(this);
|
||||
}
|
||||
|
||||
private void PostScoreUpdate()
|
||||
{
|
||||
ball.ResetBall();
|
||||
Ball.ResetBall();
|
||||
|
||||
if (networkServer is not null)
|
||||
{
|
||||
@ -82,12 +91,13 @@ public class PongManager : Behaviour, INetworkEntity, IFirstFrameUpdate,
|
||||
int halfwayScore = (int)(WinScore * .5f);
|
||||
if (ScoreLeft > halfwayScore || ScoreRight > halfwayScore)
|
||||
{
|
||||
IsGameInProgress = false;
|
||||
OnFinished?.Invoke(this);
|
||||
logger?.Log(this, $"Game finished");
|
||||
return;
|
||||
}
|
||||
|
||||
ball.LaunchBall(GetBallLaunchDirection());
|
||||
Ball.LaunchBall(GetBallLaunchDirection());
|
||||
}
|
||||
|
||||
private Vector2D GetBallLaunchDirection()
|
||||
@ -107,18 +117,6 @@ public class PongManager : Behaviour, INetworkEntity, IFirstFrameUpdate,
|
||||
logger?.Log(this, $"Client score update packet arrived: {packet.Left} - {packet.Right}");
|
||||
}
|
||||
|
||||
void IPacketListenerServer<RequestStartPacket>.OnServerPacketArrived(IConnection sender, RequestStartPacket packet)
|
||||
{
|
||||
logger?.Log(this, $"{sender} requested start");
|
||||
if (ball.RigidBody.Velocity.MagnitudeSquared > 0.01f)
|
||||
return;
|
||||
|
||||
Reset();
|
||||
ball.LaunchBall(GetBallLaunchDirection());
|
||||
logger?.Log(this, $"Game started");
|
||||
}
|
||||
|
||||
private class RequestStartPacket : INetworkPacket;
|
||||
private class ScorePacket : INetworkPacket
|
||||
{
|
||||
public int Left { get; set; }
|
||||
|
@ -66,6 +66,11 @@ public static class PongUniverse
|
||||
PongManager pongManager = universe.InstantiateUniverseObject().SetUniverseObject("Pong Game Manager")
|
||||
.BehaviourController.AddBehaviour<PongManager>(5);
|
||||
|
||||
universe.InstantiateUniverseObject().SetUniverseObject("Pong Game Starter", parent: pongManager.UniverseObject)
|
||||
.BehaviourController.AddBehaviour<PongGameStarter>()
|
||||
.BehaviourController.AddBehaviour<Transform2D>().SetTransform(position: new Vector2D(-24, 250f), scale: Vector2D.One * .5f)
|
||||
.BehaviourController.AddBehaviour<Label>();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
universe.InstantiateUniverseObject().SetUniverseObject("Ball")
|
||||
|
Loading…
x
Reference in New Issue
Block a user