You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
5.1 KiB

using System;
2 years ago
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.Netcode;
using Unity.VisualScripting;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace Game {
public class GameManager : NetworkBehaviour {
[Serializable]
public struct SpawnRatesValue {
public SpawnRate spawnRate;
public float baseSeconds;
}
[Serializable]
public struct SpawnableSpawnRates {
public Spawnable spawnable;
public SpawnRatesValue[] values;
}
public SpawnableSpawnRates[] spawnRates;
public Object ballPrefab;
public Object playerPrefab;
public Object borderZonePrefab;
public Object modificationPrefab;
public ModificationProperties[] modifications;
public Object wormholePrefab;
public Object newBallPrefab;
2 years ago
public static GameManager Singleton { get; private set; }
2 years ago
public List<Ball> Balls { get; } = new();
public Player Player1 { get; private set; }
public Player Player2 { get; private set; }
2 years ago
private void Awake() {
SetupPlayers();
}
private void OnEnable() {
Singleton = this;
// Move this to settings
Application.targetFrameRate = 144;
QualitySettings.vSyncCount = 0;
}
private IEnumerator SpawnLoop(Spawnable spawnable) {
SpawnRate required = RoomSettings.SpawnRates[spawnable];
if (required == SpawnRate.Never)
yield break;
float baseSeconds = spawnRates.First(s => s.spawnable == spawnable).values.First(v => v.spawnRate == required).baseSeconds;
while (Application.isPlaying) {
yield return new WaitForSeconds(baseSeconds);
switch (spawnable) {
case Spawnable.NewBallTemporary:
SpawnNewBall(false);
break;
case Spawnable.NewBallPermanent:
SpawnNewBall(true);
break;
case Spawnable.Modification:
SpawnModification();
break;
case Spawnable.Wormhole:
SpawnWormhole();
break;
}
}
}
private void Start() {
SpawnBall(Player1, true);
StartCoroutine(SpawnLoop(Spawnable.NewBallTemporary));
StartCoroutine(SpawnLoop(Spawnable.NewBallPermanent));
StartCoroutine(SpawnLoop(Spawnable.Modification));
StartCoroutine(SpawnLoop(Spawnable.Wormhole));
}
private void SetupPlayers() {
2 years ago
var p1Obj = Instantiate(playerPrefab);
var p2Obj = Instantiate(playerPrefab);
Player p1, p2;
switch (RoomSettings.Type) {
case Type.AI:
p1 = p1Obj.AddComponent<AIPlayer>();
p2 = p2Obj.AddComponent<AIPlayer>();
((AIPlayer) p1).Difficulty = RoomSettings.AIDifficulty;
((AIPlayer) p2).Difficulty = RoomSettings.AIDifficulty;
break;
case Type.RealOnline:
p1 = p1Obj.AddComponent<RealPlayer>();
p2 = p2Obj.AddComponent<RealPlayer>();
((RealPlayer) p1).isThisClient = true;
break;
case Type.RealOffline:
p1 = p1Obj.AddComponent<RealPlayer>();
p2 = p2Obj.AddComponent<RealPlayer>();
((RealPlayer) p1).isThisClient = true;
((RealPlayer) p2).isThisClient = true;
break;
case Type.Hybrid:
p1 = p1Obj.AddComponent<RealPlayer>();
p2 = p2Obj.AddComponent<AIPlayer>();
((RealPlayer) p1).isThisClient = true;
((AIPlayer) p2).Difficulty = RoomSettings.AIDifficulty;
break;
default:
throw new ArgumentOutOfRangeException();
}
2 years ago
p1.Side = Side.Bottom;
p2.Side = Side.Top;
2 years ago
Player1 = p1;
Player2 = p2;
p1.borderZonePrefab = p2.borderZonePrefab = borderZonePrefab;
}
private void SpawnNewBall(bool permanent) {
var pos = new Vector2(Random.Range(0, Dimensions.Singleton.PlaySize.x) - Dimensions.Singleton.PlaySize.x / 2, Random.Range(-5, 5));
Instantiate(newBallPrefab, pos, Quaternion.identity).GetComponent<NewBall>().IsPermanent = permanent;
}
2 years ago
private void SpawnWormhole() {
var pos = new Vector2(Random.Range(0, Dimensions.Singleton.PlaySize.x) - Dimensions.Singleton.PlaySize.x / 2, Random.Range(-5, 5));
Instantiate(wormholePrefab, pos, Quaternion.identity);
}
private void SpawnModification() {
var pos = new Vector2(Random.Range(0, Dimensions.Singleton.PlaySize.x) - Dimensions.Singleton.PlaySize.x / 2, Random.Range(-2, 2));
var properties = modifications[Random.Range(0, modifications.Length)];
var mod = Instantiate(modificationPrefab, pos, Quaternion.identity).GetComponent<Modification>();
mod.Properties = properties;
}
public void SpawnBall(Player towards, bool isPermanent) {
const float startSpeed = 15;
var position = new Vector2(0, -towards.transform.position.y * 0.5f);
var ball = Instantiate(ballPrefab, position, Quaternion.identity).GetComponent<Ball>();
ball.Rb.velocity = RandomDirectionTowards(towards) * startSpeed;
ball.IsPermanent = isPermanent;
ball.Radius = 0.5f;
Balls.Add(ball);
}
private static Vector2 RandomDirectionTowards(Player player) {
const float maxAngle = 45;
var radians = Random.Range(-maxAngle, maxAngle) * Mathf.PI / 180;
var x = Mathf.Sin(radians);
var y = Mathf.Cos(radians) * player.Side switch {
Side.Top => 1,
Side.Bottom => -1,
_ => throw new ArgumentOutOfRangeException()
};
return new Vector2(x, y);
}
public void RemoveBall(Ball ball) {
Balls.Remove(ball);
Destroy(ball.gameObject);
2 years ago
}
}
}