mirror of
https://github.com/kuhyx/praca_magisterska.git
synced 2026-07-04 15:03:07 +02:00
139 lines
4.4 KiB
C#
139 lines
4.4 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Magisterka.BulletHell
|
|
{
|
|
/// <summary>
|
|
/// Lightweight visual feedback hub for hits, explosions, and screen-clears.
|
|
/// </summary>
|
|
public class EffectManager : MonoBehaviour
|
|
{
|
|
public static EffectManager Instance { get; private set; }
|
|
|
|
[SerializeField] private int warmCount = 64;
|
|
[SerializeField] private Color playerColor = new Color(0.35f, 0.85f, 1f, 1f);
|
|
[SerializeField] private Color enemyColor = new Color(1f, 0.45f, 0.25f, 1f);
|
|
|
|
private readonly Queue<EffectPulse> _pool = new Queue<EffectPulse>();
|
|
private Transform _poolRoot;
|
|
private CameraShaker _cameraShaker;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance != null && Instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
Instance = this;
|
|
}
|
|
|
|
public void Initialize(Transform parent)
|
|
{
|
|
if (parent != null)
|
|
{
|
|
transform.SetParent(parent, false);
|
|
}
|
|
|
|
_cameraShaker = FindFirstObjectByType<CameraShaker>();
|
|
if (_cameraShaker == null && Camera.main != null)
|
|
{
|
|
_cameraShaker = Camera.main.gameObject.AddComponent<CameraShaker>();
|
|
}
|
|
|
|
_poolRoot = new GameObject("FX_Pool").transform;
|
|
_poolRoot.SetParent(transform, false);
|
|
|
|
Warmup(warmCount);
|
|
}
|
|
|
|
public void SpawnHitEffect(Vector2 position, Faction hitFaction, float intensity)
|
|
{
|
|
var color = hitFaction == Faction.Player ? playerColor : enemyColor;
|
|
var endSize = Mathf.Lerp(0.6f, 1.8f, Mathf.Clamp01(intensity + 0.2f));
|
|
PlayPulse(position, color, 0.25f, endSize, 0.18f);
|
|
|
|
if (hitFaction == Faction.Player)
|
|
{
|
|
float boosted = Mathf.Clamp01(intensity + 0.3f);
|
|
PlayPulse(position, Color.white, 0.18f, Mathf.Lerp(1.4f, 2.8f, boosted), 0.24f);
|
|
PlayPulse(position, playerColor, 0.45f, Mathf.Lerp(1.8f, 3.4f, boosted), 0.32f);
|
|
}
|
|
}
|
|
|
|
public void SpawnExplosion(Vector2 position, Faction faction, float size = 2.5f)
|
|
{
|
|
var color = faction == Faction.Player ? playerColor : enemyColor;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
float start = 0.4f + i * 0.1f;
|
|
float end = size + i * 0.35f;
|
|
float duration = 0.22f + i * 0.06f;
|
|
PlayPulse(position, color, start, end, duration);
|
|
}
|
|
}
|
|
|
|
public void SpawnScreenClear(Vector2 position, float radius)
|
|
{
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
float start = 0.8f + i * 0.5f;
|
|
float end = radius + i * 1.2f;
|
|
float duration = 0.35f + i * 0.12f;
|
|
var blend = Mathf.Clamp01(i / 5f);
|
|
var color = Color.Lerp(playerColor, enemyColor, blend);
|
|
PlayPulse(position, color, start, end, duration);
|
|
}
|
|
|
|
if (_cameraShaker != null)
|
|
{
|
|
_cameraShaker.Shake(0.4f, 1.2f * radius);
|
|
}
|
|
}
|
|
|
|
public void ShakeCamera(float duration, float strength)
|
|
{
|
|
if (_cameraShaker != null)
|
|
{
|
|
_cameraShaker.Shake(duration, strength);
|
|
}
|
|
}
|
|
|
|
private void Warmup(int count)
|
|
{
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
_pool.Enqueue(CreatePulse());
|
|
}
|
|
}
|
|
|
|
private EffectPulse CreatePulse()
|
|
{
|
|
var go = new GameObject("EffectPulse");
|
|
go.transform.SetParent(_poolRoot, false);
|
|
var pulse = go.AddComponent<EffectPulse>();
|
|
go.SetActive(false);
|
|
return pulse;
|
|
}
|
|
|
|
private void PlayPulse(Vector2 position, Color color, float startSize, float endSize, float duration)
|
|
{
|
|
var pulse = _pool.Count > 0 ? _pool.Dequeue() : CreatePulse();
|
|
pulse.transform.SetParent(null, false);
|
|
pulse.Play(position, color, startSize, endSize, duration, Recycle);
|
|
}
|
|
|
|
private void Recycle(EffectPulse pulse)
|
|
{
|
|
if (pulse == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pulse.transform.SetParent(_poolRoot, false);
|
|
_pool.Enqueue(pulse);
|
|
}
|
|
}
|
|
}
|