Create a diving minigame MVP (#6)
- Obstacles - Tiles - Object pooling - Monster spawns - Scoring - Minigame End Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Co-authored-by: AlexanderT <alexander@foolhardyhorizons.com> Reviewed-on: #6
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Serialization;
|
||||
@@ -48,13 +49,31 @@ namespace Minigames.DivingForPictures
|
||||
private float _screenBottom;
|
||||
private float _screenTop;
|
||||
private TrenchTilePool _tilePool;
|
||||
|
||||
// Current velocity for tile movement
|
||||
private float _currentVelocity;
|
||||
|
||||
// Interval for velocity calculations (seconds)
|
||||
[SerializeField] private float velocityCalculationInterval = 0.5f;
|
||||
|
||||
private const float TileSpawnZ = -1f;
|
||||
private const float DefaultTileHeight = 5f;
|
||||
|
||||
// Direction state
|
||||
private bool _isSurfacing = false;
|
||||
private bool _stopSpawning = false;
|
||||
|
||||
// Event triggered when the last tile leaves the screen after stopping spawning
|
||||
public UnityEvent onLastTileLeft = new UnityEvent();
|
||||
|
||||
// Velocity management
|
||||
private float _baseMoveSpeed;
|
||||
private float _velocityFactor = 1.0f;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_mainCamera = Camera.main;
|
||||
_baseMoveSpeed = moveSpeed; // Store the original base speed
|
||||
|
||||
// Calculate tile heights for each prefab
|
||||
CalculateTileHeights();
|
||||
@@ -89,15 +108,57 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
CalculateScreenBounds();
|
||||
SpawnInitialTiles();
|
||||
|
||||
// Initialize velocity and start the velocity calculation coroutine
|
||||
_currentVelocity = moveSpeed * Time.fixedDeltaTime;
|
||||
StartCoroutine(VelocityCalculationRoutine());
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
MoveTiles();
|
||||
HandleMovement();
|
||||
HandleTileDestruction();
|
||||
HandleTileSpawning();
|
||||
HandleSpeedRamping();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current velocity of the tiles
|
||||
/// </summary>
|
||||
/// <returns>The current upward velocity of the tiles</returns>
|
||||
public float GetCurrentVelocity()
|
||||
{
|
||||
return _currentVelocity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a custom velocity, overriding the calculated one
|
||||
/// </summary>
|
||||
/// <param name="velocity">The new velocity value</param>
|
||||
public void SetVelocity(float velocity)
|
||||
{
|
||||
_currentVelocity = velocity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine that periodically calculates the velocity based on game state
|
||||
/// </summary>
|
||||
private IEnumerator VelocityCalculationRoutine()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
CalculateVelocity();
|
||||
yield return new WaitForSeconds(velocityCalculationInterval);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the current velocity based on move speed
|
||||
/// </summary>
|
||||
private void CalculateVelocity()
|
||||
{
|
||||
_currentVelocity = moveSpeed * Time.fixedDeltaTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate height values for all tile prefabs
|
||||
@@ -170,9 +231,25 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void SpawnInitialTiles()
|
||||
{
|
||||
// Calculate starting Y position - moved 2 tiles up from the bottom of the screen
|
||||
float startingY = _screenBottom;
|
||||
|
||||
// If we have prefab tiles with known heights, use their average height for offset calculation
|
||||
float tileHeightEstimate = DefaultTileHeight;
|
||||
if (tilePrefabs != null && tilePrefabs.Count > 0 && tilePrefabs[0] != null)
|
||||
{
|
||||
if (_tileHeights.TryGetValue(tilePrefabs[0], out float height))
|
||||
{
|
||||
tileHeightEstimate = height;
|
||||
}
|
||||
}
|
||||
|
||||
// Move starting position up by 2 tile heights
|
||||
startingY += tileHeightEstimate * 2;
|
||||
|
||||
for (int i = 0; i < initialTileCount; i++)
|
||||
{
|
||||
float y = _screenBottom;
|
||||
float y = startingY;
|
||||
// Calculate proper Y position based on previous tiles
|
||||
if (i > 0 && _activeTiles.Count > 0)
|
||||
{
|
||||
@@ -206,16 +283,61 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move all active tiles upward
|
||||
/// Called when the velocity factor changes from the DivingGameManager
|
||||
/// </summary>
|
||||
private void MoveTiles()
|
||||
public void OnVelocityFactorChanged(float velocityFactor)
|
||||
{
|
||||
_velocityFactor = velocityFactor;
|
||||
|
||||
// Update the actual move speed based on the velocity factor
|
||||
// This keeps the original move speed intact for game logic
|
||||
moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor);
|
||||
|
||||
// Recalculate velocity immediately
|
||||
CalculateVelocity();
|
||||
|
||||
Debug.Log($"[TrenchTileSpawner] Velocity factor updated to {_velocityFactor:F2}, moveSpeed: {moveSpeed:F2}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverses direction to start surfacing
|
||||
/// </summary>
|
||||
public void StartSurfacing()
|
||||
{
|
||||
if (_isSurfacing) return; // Already surfacing
|
||||
|
||||
// Set surfacing flag for spawn/despawn logic
|
||||
_isSurfacing = true;
|
||||
|
||||
// Reverse the active tiles array to maintain consistent indexing logic
|
||||
_activeTiles.Reverse();
|
||||
|
||||
Debug.Log("[TrenchTileSpawner] Started surfacing - reversed array order");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops spawning new tiles
|
||||
/// </summary>
|
||||
public void StopSpawning()
|
||||
{
|
||||
_stopSpawning = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the movement of all active tiles based on the current velocity
|
||||
/// </summary>
|
||||
private void HandleMovement()
|
||||
{
|
||||
float moveDelta = moveSpeed * Time.deltaTime;
|
||||
foreach (var tile in _activeTiles)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
tile.transform.position += Vector3.up * moveDelta;
|
||||
// Use velocity factor to determine direction
|
||||
Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor);
|
||||
float speed = _currentVelocity;
|
||||
|
||||
// Apply movement
|
||||
tile.transform.position += direction * speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,7 +357,20 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
|
||||
float tileHeight = GetTileHeight(topTile);
|
||||
if (topTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer)
|
||||
|
||||
bool shouldDestroy;
|
||||
if (_isSurfacing)
|
||||
{
|
||||
// When surfacing, destroy tiles at the bottom
|
||||
shouldDestroy = topTile.transform.position.y + tileHeight / 2 < _screenBottom - tileSpawnBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When descending, destroy tiles at the top
|
||||
shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer;
|
||||
}
|
||||
|
||||
if (shouldDestroy)
|
||||
{
|
||||
_activeTiles.RemoveAt(0);
|
||||
onTileDestroyed?.Invoke(topTile);
|
||||
@@ -265,7 +400,15 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void HandleTileSpawning()
|
||||
{
|
||||
if (_activeTiles.Count == 0) return;
|
||||
if (_activeTiles.Count == 0)
|
||||
{
|
||||
// If we have no active tiles and spawning is stopped, trigger the event
|
||||
if (_stopSpawning)
|
||||
{
|
||||
onLastTileLeft.Invoke();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject bottomTile = _activeTiles[^1];
|
||||
if (bottomTile == null)
|
||||
@@ -274,15 +417,60 @@ namespace Minigames.DivingForPictures
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the tile height once to use in all calculations
|
||||
float tileHeight = GetTileHeight(bottomTile);
|
||||
float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
|
||||
if (bottomEdge > _screenBottom - tileSpawnBuffer)
|
||||
|
||||
// If we're in stop spawning mode, don't spawn new tiles
|
||||
if (_stopSpawning)
|
||||
{
|
||||
// Check if this is the last tile, and if it's about to leave the screen
|
||||
if (_activeTiles.Count == 1)
|
||||
{
|
||||
bool isLastTileLeaving;
|
||||
|
||||
if (_isSurfacing)
|
||||
{
|
||||
// When surfacing, check if the bottom of the tile is above the top of the screen
|
||||
isLastTileLeaving = bottomTile.transform.position.y - tileHeight / 2 > _screenTop + tileSpawnBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When descending, check if the top of the tile is below the bottom of the screen
|
||||
isLastTileLeaving = bottomTile.transform.position.y + tileHeight / 2 < _screenBottom - tileSpawnBuffer;
|
||||
}
|
||||
|
||||
if (isLastTileLeaving)
|
||||
{
|
||||
onLastTileLeft.Invoke();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool shouldSpawn;
|
||||
float newY;
|
||||
|
||||
if (_isSurfacing)
|
||||
{
|
||||
// When surfacing, spawn new tiles at the top
|
||||
float topEdge = bottomTile.transform.position.y + tileHeight / 2;
|
||||
shouldSpawn = topEdge < _screenTop + tileSpawnBuffer;
|
||||
newY = bottomTile.transform.position.y + tileHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
// When descending, spawn new tiles at the bottom
|
||||
float bottomEdge = bottomTile.transform.position.y - tileHeight / 2;
|
||||
shouldSpawn = bottomEdge > _screenBottom - tileSpawnBuffer;
|
||||
newY = bottomTile.transform.position.y - tileHeight;
|
||||
}
|
||||
|
||||
if (shouldSpawn)
|
||||
{
|
||||
float newY = bottomTile.transform.position.y - tileHeight;
|
||||
SpawnTileAtY(newY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handle increasing the movement speed over time
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user