Initial Commit

This commit is contained in:
2026-03-16 14:38:46 +02:00
commit b8f7327a21
2327 changed files with 253610 additions and 0 deletions
@@ -0,0 +1,23 @@
using UnityEngine;
namespace FlappyBird.Ground
{
[CreateAssetMenu(fileName = "GroundSettings", menuName = "FlappyBird/Ground Settings")]
public class GroundSettings : ScriptableObject
{
[Tooltip("World X position where the first ground segment starts.")]
public float spawnX = -5f;
[Tooltip("World X position where ground segments are returned to the pool.")]
public float despawnX = -15f;
[Tooltip("The exact width of the ground sprite/collider to ensure seamless looping.")]
public float groundWidth = 10f;
[Tooltip("World Y position where the ground is placed.")]
public float yPosition = -4f;
[Tooltip("Number of ground segments to create up front.")]
public int initialPoolSize = 3;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2646352a67506b34181e2563502f05fb
@@ -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);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9b7f0d695b68afb4bbc3556af67e7c7b
@@ -0,0 +1,37 @@
using FlappyBird.Core;
using FlappyBird.Pipes;
using UnityEngine;
using Zenject;
namespace FlappyBird.Ground
{
public class GroundView : MonoBehaviour, Core.IPoolable
{
private Transform _cachedTransform;
public float XPosition => _cachedTransform.position.x;
private void Awake()
{
_cachedTransform = transform;
}
public void SetPosition(Vector3 position)
{
_cachedTransform.position = position;
}
public void MoveLeft(float distance)
{
_cachedTransform.position += Vector3.left * distance;
}
public void OnSpawned()
{
}
public void OnDespawned()
{
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0d496ba852926f14cb1a0cbbda11884f