Use normalized movement settings

This commit is contained in:
Michal Pikulski
2025-10-07 09:28:41 +02:00
parent 413576701e
commit 348e982930
7 changed files with 398 additions and 48 deletions

View File

@@ -56,6 +56,15 @@ namespace Minigames.DivingForPictures
// Velocity management
private float _baseMoveSpeed;
private float _velocityFactor = 1.0f;
// Coroutine references
private Coroutine _movementCoroutine;
private Coroutine _tileDestructionCoroutine;
private Coroutine _tileSpawningCoroutine;
private Coroutine _speedRampingCoroutine;
// Screen normalization
private float _screenNormalizationFactor = 1.0f;
private void Awake()
{
@@ -75,7 +84,7 @@ namespace Minigames.DivingForPictures
Debug.LogError("[TrenchTileSpawner] Failed to load diving developer settings!");
}
_baseMoveSpeed = _settings?.MoveSpeed ?? 3f; // Store the original base speed
_baseMoveSpeed = _settings?.NormalizedMoveSpeed ?? 3f; // Store the original base speed
// Calculate tile heights for each prefab
CalculateTileHeights();
@@ -108,8 +117,6 @@ namespace Minigames.DivingForPictures
private void Start()
{
// Find DivingGameManager and subscribe to its initialization event
DivingGameManager gameManager = FindFirstObjectByType<DivingGameManager>();
if (gameManager != null)
@@ -136,23 +143,25 @@ namespace Minigames.DivingForPictures
/// </summary>
private void Initialize()
{
// Calculate screen bounds and normalization factor
CalculateScreenBounds();
CalculateScreenNormalizationFactor();
// Spawn initial tiles to fill the screen
SpawnInitialTiles();
// Initialize velocity and start the velocity calculation coroutine
_currentVelocity = _baseMoveSpeed * Time.fixedDeltaTime;
StartCoroutine(VelocityCalculationRoutine());
// Initialize velocity and apply screen normalization
_baseMoveSpeed = _settings?.NormalizedMoveSpeed ?? 3f;
_currentVelocity = _baseMoveSpeed * Time.fixedDeltaTime * _screenNormalizationFactor;
Debug.Log("[TrenchTileSpawner] Initialized");
}
private void Update()
{
HandleMovement();
HandleTileDestruction();
HandleTileSpawning();
HandleSpeedRamping();
// Start all coroutines
StartCoroutine(VelocityCalculationRoutine());
StartMovementCoroutine();
StartTileDestructionCoroutine();
StartTileSpawningCoroutine();
StartSpeedRampingCoroutine();
Debug.Log("[TrenchTileSpawner] Initialized with normalized speed");
}
/// <summary>
@@ -315,6 +324,24 @@ namespace Minigames.DivingForPictures
_screenTop = top.y;
}
/// <summary>
/// Calculates the screen normalization factor based on current screen height
/// </summary>
private void CalculateScreenNormalizationFactor()
{
// Get reference height from settings with fallback if not available
float referenceHeight = 1080f; // Default fallback value
if (_settings != null)
{
referenceHeight = _settings.ReferenceScreenHeight;
}
// Calculate normalization factor based on screen height
_screenNormalizationFactor = Screen.height / referenceHeight;
Debug.Log($"[TrenchTileSpawner] Screen normalization factor: {_screenNormalizationFactor} (Screen height: {Screen.height}, Reference: {referenceHeight})");
}
/// <summary>
/// Called when the velocity factor changes from the DivingGameManager
/// </summary>
@@ -324,7 +351,7 @@ namespace Minigames.DivingForPictures
// Update the actual move speed based on the velocity factor
// This keeps the original move speed intact for game logic
_baseMoveSpeed = _settings.MoveSpeed * Mathf.Abs(_velocityFactor);
_baseMoveSpeed = _settings.NormalizedMoveSpeed * Mathf.Abs(_velocityFactor);
// Recalculate velocity immediately
CalculateVelocity();
@@ -356,6 +383,55 @@ namespace Minigames.DivingForPictures
_stopSpawning = true;
}
/// <summary>
/// Starts the movement coroutine and stores its reference
/// </summary>
private void StartMovementCoroutine()
{
if (_movementCoroutine != null)
{
StopCoroutine(_movementCoroutine);
}
_movementCoroutine = StartCoroutine(MovementCoroutine());
}
/// <summary>
/// Coroutine that handles obstacle movement using normalized screen-relative speed
/// </summary>
private IEnumerator MovementCoroutine()
{
Debug.Log($"[TrenchTileSpawner] Started movement coroutine with normalized speed: {_currentVelocity:F3}");
while (enabled && gameObject.activeInHierarchy)
{
// Skip if no active tiles
if (_activeTiles.Count == 0)
{
yield return null;
continue;
}
// Use velocity factor sign to determine direction
Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor);
// Apply normalized movement with deltaTime for frame rate independence
float speed = _currentVelocity * _screenNormalizationFactor;
// Move all active tiles
foreach (var tile in _activeTiles)
{
if (tile != null)
{
// Apply movement in correct direction
tile.transform.position += direction * speed;
}
}
// Wait for next frame
yield return null;
}
}
/// <summary>
/// Handles the movement of all active tiles based on the current velocity
/// </summary>
@@ -512,7 +588,7 @@ namespace Minigames.DivingForPictures
_speedUpTimer += Time.deltaTime;
if (_speedUpTimer >= _settings.SpeedUpInterval)
{
_baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxMoveSpeed);
_baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxNormalizedMoveSpeed);
_speedUpTimer = 0f;
}
}
@@ -739,5 +815,217 @@ namespace Minigames.DivingForPictures
}
}
}
/// <summary>
/// Starts the tile destruction coroutine and stores its reference
/// </summary>
private void StartTileDestructionCoroutine()
{
if (_tileDestructionCoroutine != null)
{
StopCoroutine(_tileDestructionCoroutine);
}
_tileDestructionCoroutine = StartCoroutine(TileDestructionCoroutine());
}
/// <summary>
/// Coroutine that checks for tiles to destroy periodically
/// </summary>
private IEnumerator TileDestructionCoroutine()
{
const float checkInterval = 0.5f; // Check every half second as requested
Debug.Log($"[TrenchTileSpawner] Started tile destruction coroutine with interval: {checkInterval}s");
while (enabled && gameObject.activeInHierarchy)
{
// Check and handle tile destruction
if (_activeTiles.Count > 0)
{
GameObject topTile = _activeTiles[0];
if (topTile == null)
{
_activeTiles.RemoveAt(0);
}
else
{
float tileHeight = GetTileHeight(topTile);
bool shouldDestroy;
if (_isSurfacing)
{
// When surfacing, destroy tiles at the bottom
shouldDestroy = topTile.transform.position.y + tileHeight / 2 < _screenBottom - _settings.TileSpawnBuffer;
}
else
{
// When descending, destroy tiles at the top
shouldDestroy = topTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.TileSpawnBuffer;
}
if (shouldDestroy)
{
_activeTiles.RemoveAt(0);
onTileDestroyed?.Invoke(topTile);
if (_devSettings != null && _devSettings.TrenchTileUseObjectPooling && _tilePool != null)
{
// Find the prefab index for this tile
int prefabIndex = GetPrefabIndex(topTile);
if (prefabIndex >= 0)
{
_tilePool.ReturnTile(topTile, prefabIndex);
}
else
{
Destroy(topTile);
}
}
else
{
Destroy(topTile);
}
}
}
}
// Wait for the next check interval
yield return new WaitForSeconds(checkInterval);
}
}
/// <summary>
/// Starts the tile spawning coroutine and stores its reference
/// </summary>
private void StartTileSpawningCoroutine()
{
if (_tileSpawningCoroutine != null)
{
StopCoroutine(_tileSpawningCoroutine);
}
_tileSpawningCoroutine = StartCoroutine(TileSpawningCoroutine());
}
/// <summary>
/// Coroutine that checks if new tiles need to be spawned periodically
/// </summary>
private IEnumerator TileSpawningCoroutine()
{
const float checkInterval = 0.2f; // Check every half second as requested
Debug.Log($"[TrenchTileSpawner] Started tile spawning coroutine with interval: {checkInterval}s");
while (enabled && gameObject.activeInHierarchy)
{
// Check if we need to spawn new tiles
if (_activeTiles.Count == 0)
{
// If we have no active tiles and spawning is stopped, trigger the event
if (_stopSpawning)
{
onLastTileLeft.Invoke();
}
}
else
{
GameObject bottomTile = _activeTiles[^1];
if (bottomTile == null)
{
_activeTiles.RemoveAt(_activeTiles.Count - 1);
}
else
{
// Get the tile height once to use in all calculations
float tileHeight = GetTileHeight(bottomTile);
// If we're in stop spawning mode, check if last tile is leaving
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 bottom of tile is above top of screen
isLastTileLeaving = bottomTile.transform.position.y - tileHeight / 2 > _screenTop + _settings.TileSpawnBuffer;
}
else
{
// When descending, check if top of tile is below bottom of screen
isLastTileLeaving = bottomTile.transform.position.y + tileHeight / 2 < _screenBottom - _settings.TileSpawnBuffer;
}
if (isLastTileLeaving)
{
onLastTileLeft.Invoke();
}
}
}
else
{
// Normal spawning mode
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 + _settings.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 - _settings.TileSpawnBuffer;
newY = bottomTile.transform.position.y - tileHeight;
}
if (shouldSpawn)
{
SpawnTileAtY(newY);
}
}
}
}
// Wait for the next check interval
yield return new WaitForSeconds(checkInterval);
}
}
/// <summary>
/// Starts the speed ramping coroutine and stores its reference
/// </summary>
private void StartSpeedRampingCoroutine()
{
if (_speedRampingCoroutine != null)
{
StopCoroutine(_speedRampingCoroutine);
}
_speedRampingCoroutine = StartCoroutine(SpeedRampingCoroutine());
}
/// <summary>
/// Coroutine that handles increasing the movement speed over time
/// </summary>
private IEnumerator SpeedRampingCoroutine()
{
const float checkInterval = 1.0f; // Check once per second as requested
Debug.Log($"[TrenchTileSpawner] Started speed ramping coroutine with interval: {checkInterval}s");
while (enabled && gameObject.activeInHierarchy)
{
// Increase the base move speed up to the maximum
_baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxNormalizedMoveSpeed);
// Recalculate velocity with the new base speed
CalculateVelocity();
// Wait for the next check interval
yield return new WaitForSeconds(checkInterval);
}
}
}
}