Initial Commit
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
using FlappyBird.Core;
|
||||
using FlappyBird.Ground;
|
||||
using FlappyBird.Pipes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Zenject;
|
||||
|
||||
namespace FlappyBird.Environment
|
||||
{
|
||||
public class GroundSpawner : IInitializable, ITickable, IDisposable
|
||||
{
|
||||
private readonly IObjectPoolManager _objectPoolManager;
|
||||
private readonly IGameManager _gameManager;
|
||||
private readonly PipeSettings _pipeSettings;
|
||||
private readonly GroundSettings _groundSettings;
|
||||
private readonly GameObject _groundPrefab;
|
||||
|
||||
private readonly List<GroundView> _activeGrounds = new List<GroundView>();
|
||||
|
||||
private bool _isRunning;
|
||||
|
||||
[Inject]
|
||||
public GroundSpawner(
|
||||
IObjectPoolManager objectPoolManager,
|
||||
IGameManager gameManager,
|
||||
PipeSettings pipeSettings,
|
||||
GroundSettings groundSettings,
|
||||
[Inject(Id = "GroundPrefab")] GameObject groundPrefab)
|
||||
{
|
||||
_objectPoolManager = objectPoolManager;
|
||||
_gameManager = gameManager;
|
||||
_pipeSettings = pipeSettings;
|
||||
_groundSettings = groundSettings;
|
||||
_groundPrefab = groundPrefab;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the ground system by registering the object pool and
|
||||
/// spawning initial segments. They will remain stationary until the game starts.
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
_objectPoolManager.RegisterPool<GroundView>(_groundPrefab, _groundSettings.initialPoolSize);
|
||||
|
||||
_gameManager.OnGameStateChanged += HandleGameStateChanged;
|
||||
|
||||
// Pre-spawn segments so the floor is visible in the Menu state
|
||||
float currentX = _groundSettings.spawnX;
|
||||
for (int i = 0; i < Mathf.Max(1, _groundSettings.initialPoolSize); i++)
|
||||
{
|
||||
SpawnGround(currentX);
|
||||
currentX += _groundSettings.groundWidth;
|
||||
}
|
||||
|
||||
// Sets initial movement state based on current GameManager state (Menu = stopped)
|
||||
ApplyState(_gameManager.CurrentState);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_gameManager.OnGameStateChanged -= HandleGameStateChanged;
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MoveActiveGrounds();
|
||||
}
|
||||
|
||||
private void HandleGameStateChanged(GameState state)
|
||||
{
|
||||
ApplyState(state);
|
||||
}
|
||||
|
||||
private void ApplyState(GameState state)
|
||||
{
|
||||
// Ground only moves during active gameplay
|
||||
_isRunning = state == GameState.Playing;
|
||||
}
|
||||
|
||||
private void MoveActiveGrounds()
|
||||
{
|
||||
float step = _pipeSettings.moveSpeed * Time.deltaTime;
|
||||
float rightmostX = GetRightmostGroundX();
|
||||
|
||||
for (int i = _activeGrounds.Count - 1; i >= 0; i--)
|
||||
{
|
||||
GroundView groundView = _activeGrounds[i];
|
||||
groundView.MoveLeft(step);
|
||||
|
||||
if (groundView.XPosition > _groundSettings.despawnX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_activeGrounds.RemoveAt(i);
|
||||
_objectPoolManager.Return(groundView);
|
||||
|
||||
// Re-spawn at the end of the chain
|
||||
SpawnGround(rightmostX + _groundSettings.groundWidth - step);
|
||||
rightmostX += _groundSettings.groundWidth;
|
||||
}
|
||||
}
|
||||
|
||||
private float GetRightmostGroundX()
|
||||
{
|
||||
float maxX = float.MinValue;
|
||||
foreach (var ground in _activeGrounds)
|
||||
{
|
||||
if (ground.XPosition > maxX) maxX = ground.XPosition;
|
||||
}
|
||||
return maxX == float.MinValue ? _groundSettings.spawnX : maxX;
|
||||
}
|
||||
|
||||
private void SpawnGround(float xPosition)
|
||||
{
|
||||
GroundView groundView = _objectPoolManager.Get<GroundView>();
|
||||
groundView.SetPosition(new Vector3(xPosition, _groundSettings.yPosition, 0f));
|
||||
_activeGrounds.Add(groundView);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user