using System; using System.Collections.Generic; using System.Linq; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UIElements; namespace Game { public enum Side {Top, Bottom} public class Player : NetworkBehaviour { public Side Side { get; set; } protected bool goingLeft, goingRight; public VisualElement Panel { get; private set; } public List Modifications { get; } = new(); private int Score { get; set; } // Units per second private const float BaseSpeed = 15; private const float SpeedMultiplier = 1.5f; protected float Speed { get { return Modifications.Where(m => m.Properties.effect == ModEffect.Speed) .Aggregate(BaseSpeed, (current, speedMod) => current * speedMod.Properties.type switch { ModType.Buff => SpeedMultiplier, ModType.Nerf => 1 / SpeedMultiplier, _ => throw new ArgumentOutOfRangeException() }); } } // Unit distance from zero private readonly float baseBorder = Dimensions.Singleton.Width / 2 * 0.9f; private readonly float borderSummand = Dimensions.Singleton.Width / 2 * 0.1f; protected float Border { get { return Mathf.Min(Modifications.Where(m => m.Properties.effect == ModEffect.Border) .Aggregate(baseBorder, (current, borderMod) => current + borderMod.Properties.type switch { ModType.Buff => borderSummand, ModType.Nerf => -borderSummand, _ => throw new ArgumentOutOfRangeException() }), Dimensions.Singleton.Width / 2 ); } } protected float Width => transform.localScale.x; private float LeftEdge => X - Width / 2; private float RightEdge => X + Width / 2; protected float X => transform.position.x; protected float Y => transform.position.y; public void GainScore() { Score++; UpdatePanel(); } private void UpdatePanel() { Panel.Q("score").text = Score.ToString(); } protected void ClampInsideBorders() { if (LeftEdge < -Border) transform.Translate(Vector2.right * (-Border - LeftEdge), Space.World); if (RightEdge > Border) transform.Translate(Vector2.left * (RightEdge - Border), Space.World); } protected void TryLinearMove(float h) { Vector2 trans = new Vector2((goingLeft ? -1 : 0) + (goingRight ? 1 : 0), 0); trans *= Speed * h; transform.Translate(trans, Space.World); ClampInsideBorders(); } private void Start() { float y = Side switch { Side.Bottom => Dimensions.Singleton.boardBottom, Side.Top => Dimensions.Singleton.boardTop, _ => throw new ArgumentOutOfRangeException() }; transform.position = new Vector2(0, y); if (Side == Side.Top) transform.Rotate(transform.forward, 180); Panel = GameUI.Singleton.PlayerPanel(Side); UpdatePanel(); GameUI.Singleton.buttonDown += (side, direction) => { if (!side.Equals(Side)) return; if (direction == "left") goingLeft = true; else goingRight = true; }; GameUI.Singleton.buttonUp += (side, direction) => { if (!side.Equals(Side)) return; if (direction == "left") goingLeft = false; else goingRight = false; }; } } public class RealPlayer : Player { public bool isThisClient; private void FixedUpdate() { if (!isThisClient) return; if (Application.isEditor) { var keyboard = Keyboard.current; goingLeft = keyboard.aKey.isPressed; goingRight = keyboard.dKey.isPressed; } TryLinearMove(Time.fixedDeltaTime); } } }