|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using Unity.Netcode;
|
|
|
|
using Unity.VisualScripting;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
|
|
|
|
namespace Game {
|
|
|
|
|
|
|
|
public enum Side { Top, Bottom }
|
|
|
|
|
|
|
|
public class Player : NetworkBehaviour {
|
|
|
|
|
|
|
|
public UnityEngine.Object borderZonePrefab;
|
|
|
|
|
|
|
|
private Transform borderZoneLeft, borderZoneRight;
|
|
|
|
|
|
|
|
private float BaseSpeed { get; } = GameManager.BalanceValues.playerSpeed;
|
|
|
|
private float SpeedMultiplier { get; } = GameManager.Singleton.balanceValues.playerSpeedMultiplier;
|
|
|
|
|
|
|
|
// Unit distance from zero
|
|
|
|
private float BaseBorder { get; } = Dimensions.Singleton.PlaySize.x / 2 * GameManager.BalanceValues.playerBorder;
|
|
|
|
private float BorderSummand { get; } = Dimensions.Singleton.PlaySize.x / 2 * GameManager.BalanceValues.playerBorderSummand;
|
|
|
|
|
|
|
|
private float BaseWidth { get; } = GameManager.BalanceValues.playerWidth;
|
|
|
|
private float WidthMultiplier { get; } = GameManager.BalanceValues.playerWidthMultiplier;
|
|
|
|
|
|
|
|
protected bool goingLeftLinear, goingRightLinear;
|
|
|
|
|
|
|
|
public Side Side { get; set; }
|
|
|
|
|
|
|
|
private VisualElement Panel { get; set; }
|
|
|
|
|
|
|
|
private List<ModificationProperties> Modifications { get; } = new();
|
|
|
|
|
|
|
|
private int Score { get; set; }
|
|
|
|
|
|
|
|
private float GetModified(ModEffect effect, float baseValue, float modValue, Func<float, float, float> combineFunc, Func<float, float> invertFunc) {
|
|
|
|
return Modifications.Where(m => m.effect == effect)
|
|
|
|
.Aggregate(baseValue,
|
|
|
|
(current, mod) => combineFunc(current, mod.type switch {
|
|
|
|
ModType.Buff => modValue,
|
|
|
|
ModType.Nerf => invertFunc(modValue),
|
|
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float Speed {
|
|
|
|
get {
|
|
|
|
float value = GetModified(ModEffect.Speed, BaseSpeed, SpeedMultiplier, (f, f1) => f * f1, f => 1 / f);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
protected float Border {
|
|
|
|
get {
|
|
|
|
float value = GetModified(ModEffect.Border, BaseBorder, BorderSummand, (f, f1) => f + f1, f => -f);
|
|
|
|
return Mathf.Clamp(value, Width / 2, Dimensions.Singleton.PlaySize.x / 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected float Width {
|
|
|
|
get {
|
|
|
|
float value = GetModified(ModEffect.Width, BaseWidth, WidthMultiplier, (f, f1) => f * f1, f => 1 / f);
|
|
|
|
return Mathf.Clamp(value, 0.1f, Dimensions.Singleton.PlaySize.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;
|
|
|
|
|
|
|
|
private void Update() {
|
|
|
|
transform.localScale = new Vector3(Width, 1, 1);
|
|
|
|
|
|
|
|
float borderV = Border;
|
|
|
|
float borderZoneScaleX = Dimensions.Singleton.PlaySize.x / 2 - borderV;
|
|
|
|
float pos = borderV + borderZoneScaleX / 2;
|
|
|
|
borderZoneLeft.position = new Vector2(pos, transform.position.y);
|
|
|
|
borderZoneRight.position = new Vector2(-pos, transform.position.y);
|
|
|
|
|
|
|
|
borderZoneLeft.localScale = borderZoneRight.localScale = new Vector3(borderZoneScaleX, 1, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void Start() {
|
|
|
|
var y = Side switch {
|
|
|
|
Side.Bottom => -Dimensions.Singleton.PlaySizeBoards.y / 2,
|
|
|
|
Side.Top => Dimensions.Singleton.PlaySizeBoards.y / 2,
|
|
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
|
|
};
|
|
|
|
transform.position = new Vector2(0, y);
|
|
|
|
if (Side == Side.Top)
|
|
|
|
transform.Rotate(transform.forward, 180);
|
|
|
|
Panel = GameUI.Singleton.PlayerPanel(Side);
|
|
|
|
UpdatePanel();
|
|
|
|
SpawnZones();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void SpawnZones() {
|
|
|
|
borderZoneLeft = Instantiate(borderZonePrefab).GetComponent<Transform>();
|
|
|
|
borderZoneRight = Instantiate(borderZonePrefab).GetComponent<Transform>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void GainScore() {
|
|
|
|
Score++;
|
|
|
|
UpdatePanel();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void UpdatePanel() {
|
|
|
|
Panel.Q<TextElement>("score").text = Score.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public IEnumerator ProcessModification(ModificationProperties properties) {
|
|
|
|
Modifications.Add(properties);
|
|
|
|
var element = GameUI.AddModification(Panel, properties);
|
|
|
|
|
|
|
|
var doNothingTime = properties.activeDuration * 0.7f;
|
|
|
|
var animateTime = properties.activeDuration * 0.3f;
|
|
|
|
|
|
|
|
yield return new WaitForSeconds(doNothingTime);
|
|
|
|
|
|
|
|
float current = 0;
|
|
|
|
while (current < animateTime) {
|
|
|
|
current += Time.deltaTime;
|
|
|
|
element.style.opacity = new StyleFloat(1 - current / animateTime);
|
|
|
|
yield return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
element.RemoveFromHierarchy();
|
|
|
|
Modifications.Remove(properties);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
var trans = new Vector2((goingLeftLinear ? -1 : 0) + (goingRightLinear ? 1 : 0), 0);
|
|
|
|
trans *= Speed * h;
|
|
|
|
transform.Translate(trans, Space.World);
|
|
|
|
ClampInsideBorders();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|