Files
Flappy-Bird-AI-Driven-Result/Assets/Scripts/Gameplay/Pipes/PipeSpawner.cs
T
2026-03-16 14:38:46 +02:00

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();
}
}
}