From 2853a6130b1475167a2bd821b4f93242fb2f867e Mon Sep 17 00:00:00 2001 From: Syntriax Date: Wed, 21 May 2025 22:45:21 +0300 Subject: [PATCH] feat: basic pong manager networking added --- Shared/Behaviours/BallBehaviour.cs | 43 +++-------- Shared/Behaviours/PongManagerBehaviour.cs | 93 +++++++++++++++++++++-- Shared/GamePong.cs | 12 --- 3 files changed, 95 insertions(+), 53 deletions(-) diff --git a/Shared/Behaviours/BallBehaviour.cs b/Shared/Behaviours/BallBehaviour.cs index 8758948..866ba6c 100644 --- a/Shared/Behaviours/BallBehaviour.cs +++ b/Shared/Behaviours/BallBehaviour.cs @@ -1,5 +1,3 @@ -using System; - using Syntriax.Engine.Core; using Syntriax.Engine.Physics2D; @@ -7,47 +5,28 @@ namespace Pong.Behaviours; public class BallBehaviour : Behaviour2D { - public Vector2D StartDirection { get; private set; } = Vector2D.Zero; public float Speed { get; set; } = 500f; public float SpeedUpMultiplier { get; set; } = .0125f; - private readonly Random random = new(); - private IRigidBody2D rigidBody = null!; + public IRigidBody2D rigidBody = null!; protected override void OnFirstActiveFrame() { BehaviourController.GetRequiredBehaviour().OnCollisionDetected += OnCollisionDetected; rigidBody = BehaviourController.GetRequiredBehaviour(); - - if (UniverseObject.Universe.TryFindBehaviour(out PongManagerBehaviour? pongManager)) - { - pongManager.OnReset += ResetBall; - pongManager.OnScored += ResetBall; - pongManager.OnFinished += DisableBall; - } } - private void DisableBall(PongManagerBehaviour pongManager) + public void LaunchBall(Vector2D launchDirection) + { + rigidBody.Velocity = launchDirection * Speed; + } + + public void ResetBall() { Transform.Position = Vector2D.Zero; rigidBody.Velocity = Vector2D.Zero; } - private void ResetBall(PongManagerBehaviour pongManager) - { - StateEnable.Enabled = true; - Transform.Position = Vector2D.Zero; - rigidBody.Velocity = GetRandomDirection() * Speed; - } - - private Vector2D GetRandomDirection() - { - 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); - } - protected override void OnUpdate() { if (rigidBody.Velocity.MagnitudeSquared <= 0.01f) @@ -59,16 +38,12 @@ public class BallBehaviour : Behaviour2D private void OnCollisionDetected(ICollider2D collider2D, CollisionDetectionInformation information) { - if (Syntriax.Engine.Core.Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25) + if (Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25) rigidBody.Velocity = information.Detected.Transform.Position.FromTo(information.Detector.Transform.Position).Normalized * rigidBody.Velocity.Magnitude; else rigidBody.Velocity = rigidBody.Velocity.Reflect(information.Normal); } public BallBehaviour() { } - public BallBehaviour(Vector2D startDirection, float speed) - { - StartDirection = Vector2D.Normalize(startDirection); - Speed = speed; - } + public BallBehaviour(float speed) => Speed = speed; } diff --git a/Shared/Behaviours/PongManagerBehaviour.cs b/Shared/Behaviours/PongManagerBehaviour.cs index 65b5706..c256b16 100644 --- a/Shared/Behaviours/PongManagerBehaviour.cs +++ b/Shared/Behaviours/PongManagerBehaviour.cs @@ -3,16 +3,28 @@ 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 +public class PongManagerBehaviour : Behaviour, + IPacketListenerServer, + IPacketListenerServer, + IPacketListenerClient, + IPacketListenerClient, + IPacketListenerClient { public Action? OnReset { get; set; } = null; public Action? OnFinished { get; set; } = null; public Action? OnScored { get; set; } = null; + private readonly 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; @@ -25,22 +37,31 @@ public class PongManagerBehaviour : Behaviour protected override void OnFirstActiveFrame() { var buttonInputs = Universe.FindRequiredBehaviour>(); - buttonInputs.RegisterOnRelease(Keys.Space, (_, _1) => Reset()); - } + buttonInputs.RegisterOnRelease(Keys.Space, (_, _1) => networkClient.SendToServer(new PongResetPacket())); + networkClient = Universe.FindRequiredBehaviour(); + ball = Universe.FindRequiredBehaviour(); + networkServer = Universe.FindBehaviour(); + } public void ScoreToLeft() { - ScoreLeft++; - OnScored?.InvokeSafe(this); + if (networkServer is not null) + { + ScoreLeft++; + OnScored?.InvokeSafe(this); + } CheckFinish(); } public void ScoreToRight() { - ScoreRight++; - OnScored?.InvokeSafe(this); + if (networkServer is not null) + { + ScoreRight++; + OnScored?.InvokeSafe(this); + } CheckFinish(); } @@ -54,8 +75,66 @@ public class PongManagerBehaviour : Behaviour private void CheckFinish() { int halfwayScore = (int)(WinScore * .5f); + ball.ResetBall(); + networkServer?.SendToClient("*", new PongScoreUpdatePacket(this)); if (ScoreLeft > halfwayScore || ScoreRight > halfwayScore) OnFinished?.InvokeSafe(this); + else + networkServer?.SendToClient("*", new PongStartPacket() { BallVelocity = 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); + } + + public void OnClientPacketArrived(PongResetPacket packet) => Reset(); + public void OnClientPacketArrived(PongScoreUpdatePacket packet) + { + ScoreLeft = packet.Left; + ScoreRight = packet.Right; + OnScored?.InvokeSafe(this); + } + + public void OnServerPacketArrived(PongResetPacket packet, string from) + { + Reset(); + networkServer?.SendToClient("*", new PongResetPacket()); + networkServer?.SendToClient("*", new PongStartPacket() { BallVelocity = GetBallLaunchDirection() }); + } + + public void OnServerPacketArrived(PongStartPacket packet, string from) + { + packet = new() { BallVelocity = GetBallLaunchDirection() }; + networkServer?.SendToClient("*", packet); + } + + public void OnClientPacketArrived(PongStartPacket packet) + { + ball.LaunchBall(packet.BallVelocity); + } + + public class PongStartPacket : INetworkPacket + { + public Vector2D BallVelocity { get; set; } = Vector2D.Zero; + } + + public class PongResetPacket : INetworkPacket; + + public class PongScoreUpdatePacket : INetworkPacket + { + public int Left { get; set; } = 0; + public int Right { get; set; } = 0; + + public PongScoreUpdatePacket() { } + public PongScoreUpdatePacket(PongManagerBehaviour pongManagerBehaviour) + { + Left = pongManagerBehaviour.ScoreLeft; + Right = pongManagerBehaviour.ScoreRight; + } } } diff --git a/Shared/GamePong.cs b/Shared/GamePong.cs index 2821093..ea2b2a9 100644 --- a/Shared/GamePong.cs +++ b/Shared/GamePong.cs @@ -16,18 +16,6 @@ using Syntriax.Engine.Physics2D; namespace Pong; -[System.Serializable] -public class TestMessagePacket : INetworkPacket, LiteNetLib.Utils.INetSerializable -{ - public string Message { get; set; } - - public void Deserialize(LiteNetLib.Utils.NetDataReader reader) => Message = reader.GetString(); - public void Serialize(LiteNetLib.Utils.NetDataWriter writer) => writer.Put(Message); - - public TestMessagePacket() => Message = "Default Message"; - public TestMessagePacket(string Message) => this.Message = Message; -} - public class GamePong : Game { private readonly IUniverseObject platformSpecificUniverseObject = null!;