140 lines
4.0 KiB
C#
140 lines
4.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using FlappyBird.Core;
|
|
using UnityEngine;
|
|
using Zenject;
|
|
|
|
namespace FlappyBird.Pipes
|
|
{
|
|
public class PipeSpawner : IInitializable, ITickable, IDisposable
|
|
{
|
|
private readonly IObjectPoolManager _objectPoolManager;
|
|
private readonly IGameManager _gameManager;
|
|
private readonly PipeSettings _settings;
|
|
private readonly GameObject _pipePrefab;
|
|
|
|
private readonly List<PipeView> _activePipes = new List<PipeView>();
|
|
|
|
private bool _isRunning;
|
|
private float _spawnTimer;
|
|
|
|
[Inject]
|
|
public PipeSpawner(
|
|
IObjectPoolManager objectPoolManager,
|
|
IGameManager gameManager,
|
|
PipeSettings settings,
|
|
[Inject(Id = "PipePrefab")] GameObject pipePrefab)
|
|
{
|
|
_objectPoolManager = objectPoolManager;
|
|
_gameManager = gameManager;
|
|
_settings = settings;
|
|
_pipePrefab = pipePrefab;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes the spawner by registering the Pipe pool, subscribing to game state changes,
|
|
/// and setting the initial spawn timer based on settings.
|
|
/// </summary>
|
|
public void Initialize()
|
|
{
|
|
// Register the pool with the new generic ObjectPoolManager
|
|
_objectPoolManager.RegisterPool<PipeView>(_pipePrefab, _settings.initialPoolSize);
|
|
|
|
_gameManager.OnGameStateChanged += HandleGameStateChanged;
|
|
ApplyState(_gameManager.CurrentState);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_gameManager.OnGameStateChanged -= HandleGameStateChanged;
|
|
}
|
|
|
|
public void Tick()
|
|
{
|
|
if (!_isRunning)
|
|
{
|
|
return;
|
|
}
|
|
|
|
MoveActivePipes();
|
|
UpdateSpawnTimer();
|
|
}
|
|
|
|
private void HandleGameStateChanged(GameState state)
|
|
{
|
|
ApplyState(state);
|
|
}
|
|
|
|
private void ApplyState(GameState state)
|
|
{
|
|
if (state == GameState.Playing)
|
|
{
|
|
_isRunning = true;
|
|
_spawnTimer = _settings.spawnImmediately ? 0f : _settings.spawnInterval;
|
|
return;
|
|
}
|
|
|
|
_isRunning = false;
|
|
|
|
if (state == GameState.Menu)
|
|
{
|
|
DespawnAllActivePipes();
|
|
}
|
|
}
|
|
|
|
private void UpdateSpawnTimer()
|
|
{
|
|
_spawnTimer -= Time.deltaTime;
|
|
if (_spawnTimer > 0f)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SpawnPipe();
|
|
_spawnTimer += Mathf.Max(0.01f, _settings.spawnInterval);
|
|
}
|
|
|
|
private void SpawnPipe()
|
|
{
|
|
PipeView pipeView = _objectPoolManager.Get<PipeView>();
|
|
|
|
// Randomize the vertical position of the gap
|
|
float gapCenterY = UnityEngine.Random.Range(_settings.minGapCenterY, _settings.maxGapCenterY);
|
|
|
|
pipeView.ConfigureGap(gapCenterY, _settings.gapSize, _settings.scoreTriggerWidth);
|
|
pipeView.SetWorldPosition(new Vector3(_settings.spawnX, 0f, 0f));
|
|
|
|
_activePipes.Add(pipeView);
|
|
}
|
|
|
|
private void MoveActivePipes()
|
|
{
|
|
float step = _settings.moveSpeed * Time.deltaTime;
|
|
|
|
for (int i = _activePipes.Count - 1; i >= 0; i--)
|
|
{
|
|
PipeView pipeView = _activePipes[i];
|
|
pipeView.MoveLeft(step);
|
|
|
|
// Despawn if the pipe has moved past the despawn threshold
|
|
if (pipeView.XPosition > _settings.despawnX)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
_activePipes.RemoveAt(i);
|
|
_objectPoolManager.Return(pipeView);
|
|
}
|
|
}
|
|
|
|
private void DespawnAllActivePipes()
|
|
{
|
|
for (int i = _activePipes.Count - 1; i >= 0; i--)
|
|
{
|
|
_objectPoolManager.Return(_activePipes[i]);
|
|
}
|
|
|
|
_activePipes.Clear();
|
|
}
|
|
}
|
|
} |