251 lines
8.9 KiB
C#
251 lines
8.9 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public partial class OrbitalBehaviour
|
|
{
|
|
public class BehaviourManager : MonoBehaviour
|
|
{
|
|
private static BehaviourManager Instance;
|
|
|
|
private Vector3[] m_PrecalculatedPositions;
|
|
|
|
private bool m_CurrentRingAllowsSpawning;
|
|
private bool m_IsSimulationRunning;
|
|
private bool m_AllowPlayerInput;
|
|
|
|
public static bool IsSimulationRunning => Instance.m_IsSimulationRunning;
|
|
public static bool AllowPlayerInput => Instance.m_AllowPlayerInput;
|
|
|
|
private float m_LocalDeltaTimeScale = 1f;
|
|
private float m_TimeOfLastRingSpawn;
|
|
|
|
private int m_LastGeneratedRing;
|
|
|
|
private readonly Dictionary<int, float> m_Distances = new();
|
|
private readonly List<OrbitalBehaviour> m_ObjectInstances = new();
|
|
private readonly List<Ring> m_Rings = new();
|
|
|
|
private OrbitalBehaviour m_PlayerInstance;
|
|
|
|
private GameObject m_ModiferParent;
|
|
private GameObject m_EnemyParent;
|
|
private GameObject m_RingParent;
|
|
|
|
private const int CirclePoints = 100;
|
|
|
|
public static IEnumerator StartPlayerSpeedupModifier()
|
|
{
|
|
Instance.m_LocalDeltaTimeScale *= 1.5f;
|
|
|
|
yield return new WaitForSeconds(10f);
|
|
|
|
Instance.m_LocalDeltaTimeScale /= 1.5f;
|
|
Instance.m_LocalDeltaTimeScale *= 2f;
|
|
|
|
yield return new WaitForSeconds(5f);
|
|
|
|
Instance.m_LocalDeltaTimeScale /= 2f;
|
|
}
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
|
private static void OnApplicationStart()
|
|
{
|
|
GameObject manager = new("OrbitalManager");
|
|
DontDestroyOnLoad(manager);
|
|
Instance = manager.AddComponent<BehaviourManager>();
|
|
|
|
Instance.PrecalculatePositions();
|
|
Instance.StartCoroutine(RestartSimulation());
|
|
|
|
Instance.m_ModiferParent = new GameObject("ModifierParent");
|
|
Instance.m_EnemyParent = new GameObject("EnemyHolder");
|
|
Instance.m_RingParent = new GameObject("RingHolder");
|
|
}
|
|
|
|
private void PrecalculatePositions()
|
|
{
|
|
m_PrecalculatedPositions = new Vector3[CirclePoints];
|
|
for (int idx = 0; idx < m_PrecalculatedPositions.Length; idx++)
|
|
{
|
|
m_PrecalculatedPositions[idx] = new Vector3
|
|
(
|
|
x: Mathf.Cos(Mathf.Deg2Rad * (359f / CirclePoints * idx)),
|
|
y: Mathf.Sin(Mathf.Deg2Rad * (359f / CirclePoints * idx)),
|
|
z: 0
|
|
);
|
|
}
|
|
}
|
|
|
|
public static IEnumerator RestartSimulation()
|
|
{
|
|
Instance.m_IsSimulationRunning = false;
|
|
Instance.m_AllowPlayerInput = false;
|
|
|
|
Instance.m_LocalDeltaTimeScale = 7f;
|
|
|
|
for (int idx = 0; idx < 100; idx++) // 100 = 5 seconds of fixed updates
|
|
{
|
|
if (Instance.m_PlayerInstance != null)
|
|
{
|
|
Instance.m_PlayerInstance.m_AttachedRing = Instance.m_LastGeneratedRing;
|
|
}
|
|
|
|
yield return new WaitForFixedUpdate();
|
|
}
|
|
|
|
PlayerController.AttachPlayer();
|
|
|
|
foreach (OrbitalBehaviour behaviour in Instance.m_ObjectInstances)
|
|
{
|
|
behaviour.OnSimulationRestart();
|
|
}
|
|
|
|
yield return new WaitForSeconds(1.3f);
|
|
|
|
Instance.m_IsSimulationRunning = true;
|
|
Instance.m_AllowPlayerInput = true;
|
|
|
|
Instance.m_LocalDeltaTimeScale = 1f;
|
|
}
|
|
|
|
private void SpawnNewRing()
|
|
{
|
|
GameObject newRing = Instantiate(Settings.Instance.RingPrefab, m_RingParent.transform);
|
|
newRing.transform.localScale = new Vector3(12f, 12f, 1f);
|
|
|
|
Ring ring = newRing.AddComponent<Ring>();
|
|
ring.m_ID = m_LastGeneratedRing + 1;
|
|
m_Rings.Add(ring);
|
|
|
|
LineRenderer lineRenderer = newRing.GetComponentInChildren<LineRenderer>();
|
|
lineRenderer.loop = true;
|
|
lineRenderer.positionCount = CirclePoints;
|
|
lineRenderer.startWidth = 0.1f;
|
|
lineRenderer.endWidth = 0.1f;
|
|
lineRenderer.material = new Material(Shader.Find("Sprites/Default"));
|
|
|
|
m_LastGeneratedRing = ring.m_ID;
|
|
m_TimeOfLastRingSpawn = Time.time;
|
|
|
|
m_CurrentRingAllowsSpawning = Random.Range(0, 25) != 0;
|
|
if (!m_CurrentRingAllowsSpawning && m_AllowPlayerInput)
|
|
{
|
|
Instantiate(Settings.Instance.ModifierPrefab, m_ModiferParent.transform);
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (Time.time - m_TimeOfLastRingSpawn > Settings.Instance.GapDistance / m_LocalDeltaTimeScale)
|
|
{
|
|
SpawnNewRing();
|
|
}
|
|
|
|
List<Ring> toRemove = new();
|
|
m_Distances.Clear();
|
|
|
|
foreach (Ring ring in m_Rings)
|
|
{
|
|
float diff = (m_LocalDeltaTimeScale * Time.deltaTime) * Settings.Instance.DistanceSpeed;
|
|
ring.transform.localScale -= new Vector3(diff, diff, 0f);
|
|
|
|
LineRenderer lineRenderer = ring.GetComponentInChildren<LineRenderer>();
|
|
for (int vert = 0; vert < CirclePoints; vert++)
|
|
{
|
|
lineRenderer.SetPosition(vert, new Vector3
|
|
(
|
|
x: m_PrecalculatedPositions[vert].x * ring.transform.localScale.x,
|
|
y: m_PrecalculatedPositions[vert].y * ring.transform.localScale.y,
|
|
z: 10
|
|
));
|
|
}
|
|
|
|
float lerp = (ring.transform.localScale.x - 0.5f) / 4f;
|
|
Color c = Color.Lerp(Color.black, Color.white, Mathf.Clamp01(lerp));
|
|
if (ring.transform.localScale.x < 0.5f)
|
|
{
|
|
if (m_IsSimulationRunning)
|
|
PlayerController.s_PlayerScore++;
|
|
|
|
toRemove.Add(ring);
|
|
}
|
|
|
|
lineRenderer.startColor = c;
|
|
lineRenderer.endColor = c;
|
|
|
|
m_Distances[ring.m_ID] = ring.transform.localScale.x;
|
|
}
|
|
|
|
foreach (Ring ring in toRemove)
|
|
{
|
|
m_Rings.Remove(ring);
|
|
Destroy(ring.gameObject);
|
|
}
|
|
|
|
foreach (OrbitalBehaviour orbitalPosition in m_ObjectInstances)
|
|
{
|
|
if (!orbitalPosition.IsAttachedToRings)
|
|
continue;
|
|
|
|
if (!m_Distances.TryGetValue(orbitalPosition.m_AttachedRing, out float distance))
|
|
{
|
|
orbitalPosition.m_AttachedRing = m_LastGeneratedRing;
|
|
orbitalPosition.OnReachCentre();
|
|
continue;
|
|
}
|
|
|
|
orbitalPosition.m_DistanceFromCentre = distance;
|
|
|
|
float deltaTime = Time.deltaTime * m_LocalDeltaTimeScale;
|
|
float movement = deltaTime * Settings.Instance.RadiusSpeed * orbitalPosition.m_SpinSpeed;
|
|
orbitalPosition.m_DistanceAlongCircumference += movement;
|
|
orbitalPosition.m_DistanceAlongCircumference %= Mathf.PI * 2;
|
|
orbitalPosition.transform.position = orbitalPosition.TranslateToVector3();
|
|
}
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
foreach (OrbitalBehaviour orbital in m_ObjectInstances)
|
|
{
|
|
if (orbital == m_PlayerInstance)
|
|
continue;
|
|
|
|
Vector2 a = orbital.TranslateToVector3();
|
|
Vector2 b = m_PlayerInstance.TranslateToVector3();
|
|
float d = (a - b).magnitude;
|
|
|
|
float r1 = m_PlayerInstance.m_ObjectRadius * m_PlayerInstance.ObjectRadiusMultiplier;
|
|
float r2 = orbital.m_ObjectRadius * orbital.ObjectRadiusMultiplier;
|
|
if (d > (r1 + r2))
|
|
continue;
|
|
|
|
m_PlayerInstance.OnOrbitalCollision(orbital);
|
|
orbital.OnOrbitalCollision(m_PlayerInstance);
|
|
}
|
|
|
|
if (Random.Range(0, 15) == 0 && m_AllowPlayerInput && m_CurrentRingAllowsSpawning)
|
|
{
|
|
Instantiate(Settings.Instance.EnemyPrefab, m_EnemyParent.transform);
|
|
}
|
|
}
|
|
|
|
public static void UnregisterOrbitalInstance(OrbitalBehaviour instance)
|
|
{
|
|
Instance.m_ObjectInstances.Remove(instance);
|
|
}
|
|
|
|
public static void RegisterOrbitalInstance(OrbitalBehaviour instance)
|
|
{
|
|
instance.m_AttachedRing = Instance.m_LastGeneratedRing; // Connects it to last generated ring
|
|
Instance.m_ObjectInstances.Add(instance);
|
|
}
|
|
|
|
public static void SetPlayer(OrbitalBehaviour player)
|
|
{
|
|
Instance.m_PlayerInstance = player;
|
|
}
|
|
}
|
|
}
|