2024-01-30 12:43:30 +03:00
|
|
|
using System;
|
2024-02-05 12:31:41 +03:00
|
|
|
|
|
|
|
using Microsoft.Xna.Framework.Content;
|
|
|
|
|
2024-02-02 12:53:25 +03:00
|
|
|
using LiteNetLib;
|
2024-02-05 12:31:41 +03:00
|
|
|
|
2024-02-02 12:53:25 +03:00
|
|
|
using Pong.Network;
|
2024-02-05 12:31:41 +03:00
|
|
|
|
2024-01-30 12:43:30 +03:00
|
|
|
using Syntriax.Engine.Core;
|
|
|
|
using Syntriax.Engine.Physics2D;
|
|
|
|
using Syntriax.Engine.Physics2D.Abstract;
|
2024-02-05 12:31:41 +03:00
|
|
|
using Microsoft.Xna.Framework.Audio;
|
2024-01-30 12:43:30 +03:00
|
|
|
|
|
|
|
namespace Pong.Behaviours;
|
|
|
|
|
2024-02-05 12:31:41 +03:00
|
|
|
public class BallBehaviour : BehaviourOverride, IMonoGameContentLoader
|
2024-01-30 12:43:30 +03:00
|
|
|
{
|
|
|
|
public Vector2D StartDirection { get; private set; } = Vector2D.Zero;
|
|
|
|
public float Speed { get; set; } = 500f;
|
|
|
|
public float SpeedUpMultiplier { get; set; } = .0125f;
|
|
|
|
|
2024-01-31 12:45:54 +03:00
|
|
|
private readonly Random random = new();
|
2024-01-30 12:43:30 +03:00
|
|
|
private IRigidBody2D rigidBody = null!;
|
2024-02-02 12:53:25 +03:00
|
|
|
private INetworkCommunicator communicator = null!;
|
2024-02-05 12:31:41 +03:00
|
|
|
private SoundEffect soundEffect = null!;
|
|
|
|
|
|
|
|
public void LoadContent(ContentManager content)
|
|
|
|
{
|
|
|
|
soundEffect = content.Load<SoundEffect>("Hit");
|
|
|
|
}
|
2024-01-30 12:43:30 +03:00
|
|
|
|
|
|
|
protected override void OnFirstActiveFrame()
|
|
|
|
{
|
|
|
|
if (!BehaviourController.TryGetBehaviour(out IRigidBody2D? foundRigidBody))
|
|
|
|
throw new Exception($"{nameof(IRigidBody2D)} is missing on {GameObject.Name}.");
|
|
|
|
if (!BehaviourController.TryGetBehaviour(out ICollider2D? foundCollider))
|
|
|
|
throw new Exception($"{nameof(ICollider2D)} is missing on {GameObject.Name}.");
|
2024-02-02 12:53:25 +03:00
|
|
|
if (!GameObject.GameManager.TryFindBehaviour(out INetworkCommunicator? foundCommunicator))
|
|
|
|
throw new Exception($"{nameof(INetworkCommunicator)} is missing on GameManager.");
|
2024-01-30 12:43:30 +03:00
|
|
|
|
|
|
|
foundCollider.OnCollisionDetected += OnCollisionDetected;
|
|
|
|
|
|
|
|
rigidBody = foundRigidBody;
|
2024-02-02 12:53:25 +03:00
|
|
|
communicator = foundCommunicator;
|
|
|
|
communicator.RegisterEntityListener(this, OnDataReceived);
|
2024-01-31 12:17:43 +03:00
|
|
|
if (GameObject.GameManager.TryFindBehaviour(out PongManagerBehaviour? pongManager))
|
2024-01-30 12:43:30 +03:00
|
|
|
{
|
|
|
|
pongManager.OnReset += ResetBall;
|
|
|
|
pongManager.OnScored += ResetBall;
|
|
|
|
pongManager.OnFinished += DisableBall;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 12:53:25 +03:00
|
|
|
private void OnDataReceived(NetPacketReader reader)
|
|
|
|
{
|
|
|
|
rigidBody.Transform.Position = reader.GetVector2D();
|
|
|
|
rigidBody.Velocity = reader.GetVector2D();
|
|
|
|
}
|
|
|
|
|
2024-01-31 12:17:43 +03:00
|
|
|
private void DisableBall(PongManagerBehaviour pongManager)
|
2024-01-30 12:43:30 +03:00
|
|
|
{
|
|
|
|
BehaviourController.GameObject.Transform.Position = Vector2D.Zero;
|
|
|
|
rigidBody.Velocity = Vector2D.Zero;
|
|
|
|
}
|
|
|
|
|
2024-01-31 12:17:43 +03:00
|
|
|
private void ResetBall(PongManagerBehaviour pongManager)
|
2024-01-30 12:43:30 +03:00
|
|
|
{
|
|
|
|
StateEnable.Enabled = true;
|
|
|
|
BehaviourController.GameObject.Transform.Position = Vector2D.Zero;
|
2024-01-31 12:45:54 +03:00
|
|
|
rigidBody.Velocity = GetRandomDirection() * Speed;
|
2024-02-02 12:53:25 +03:00
|
|
|
|
|
|
|
SendBallData();
|
2024-01-31 12:45:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2024-01-30 12:43:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override void OnUpdate()
|
|
|
|
{
|
|
|
|
if (rigidBody.Velocity.MagnitudeSquared <= 0.01f)
|
|
|
|
return;
|
|
|
|
|
2024-02-01 18:47:27 +03:00
|
|
|
Vector2D speedUp = rigidBody.Velocity.Normalized * Time.DeltaTimeFrame;
|
2024-01-30 12:43:30 +03:00
|
|
|
rigidBody.Velocity += speedUp * SpeedUpMultiplier;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnCollisionDetected(ICollider2D collider2D, CollisionDetectionInformation information)
|
|
|
|
{
|
|
|
|
if (Syntriax.Engine.Core.Math.Abs(information.Normal.Dot(Vector2D.Right)) > .25)
|
|
|
|
rigidBody.Velocity = information.Left.Transform.Position.FromTo(information.Right.Transform.Position).Normalized * rigidBody.Velocity.Magnitude;
|
|
|
|
else
|
|
|
|
rigidBody.Velocity = rigidBody.Velocity.Reflect(information.Normal);
|
2024-02-02 12:53:25 +03:00
|
|
|
|
2024-02-05 12:31:41 +03:00
|
|
|
soundEffect.Play();
|
|
|
|
|
2024-02-02 12:53:25 +03:00
|
|
|
SendBallData();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void SendBallData()
|
|
|
|
{
|
|
|
|
if (communicator is not INetworkServer server)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LiteNetLib.Utils.NetDataWriter dataWriter = communicator.GetEntityWriter(this);
|
|
|
|
dataWriter.Put(rigidBody.Transform.Position);
|
|
|
|
dataWriter.Put(rigidBody.Velocity);
|
|
|
|
server.Manager.SendToAll(dataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered);
|
2024-01-30 12:43:30 +03:00
|
|
|
}
|
2024-01-31 12:51:23 +03:00
|
|
|
|
|
|
|
public BallBehaviour() { }
|
|
|
|
public BallBehaviour(Vector2D startDirection, float speed)
|
|
|
|
{
|
|
|
|
StartDirection = Vector2D.Normalize(startDirection);
|
|
|
|
Speed = speed;
|
|
|
|
}
|
2024-01-30 12:43:30 +03:00
|
|
|
}
|