diff --git a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs index 0f51521c..f352a5f0 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs @@ -42,8 +42,20 @@ namespace Minigames.DivingForPictures private float timeSinceLastSpawn = 0f; private List activeMonsters = new List(); + // Velocity management + [Header("Surfacing Settings")] + [Tooltip("Duration in seconds for speed transition when surfacing")] + [SerializeField] private float speedTransitionDuration = 2.0f; + [Tooltip("Factor to multiply speed by when surfacing (usually 1.0 for same speed)")] + [SerializeField] private float surfacingSpeedFactor = 3.0f; + + // Velocity state tracking + private float _currentVelocityFactor = 1.0f; // 1.0 = normal descent speed, -1.0 * surfacingSpeedFactor = full surfacing speed + private Coroutine _velocityTransitionCoroutine; + // Public properties public int PlayerScore => playerScore; + public float CurrentVelocityFactor => _currentVelocityFactor; // Events public event Action OnScoreChanged; @@ -52,6 +64,7 @@ namespace Minigames.DivingForPictures public event Action OnSpawnProbabilityChanged; public event Action OnGameOver; public event Action OnRopeBroken; // Passes remaining ropes count + public event Action OnVelocityFactorChanged; // Private state variables for rope system private int currentRopeIndex = 0; @@ -335,29 +348,48 @@ namespace Minigames.DivingForPictures _isSurfacing = true; - // 1. Find and reverse trench tile spawner + // 1. Initiate smooth velocity transition to surfacing speed + float targetVelocityFactor = -1.0f * surfacingSpeedFactor; + SetVelocityFactor(targetVelocityFactor); + + // 2. Find and notify trench tile spawner about direction change (for spawning/despawning logic) TrenchTileSpawner tileSpawner = FindFirstObjectByType(); if (tileSpawner != null) { + // Subscribe to velocity changes if not already subscribed + OnVelocityFactorChanged -= tileSpawner.OnVelocityFactorChanged; + OnVelocityFactorChanged += tileSpawner.OnVelocityFactorChanged; + + // Tell spawner to reverse spawn/despawn logic tileSpawner.StartSurfacing(); + + // Immediately send current velocity factor + tileSpawner.OnVelocityFactorChanged(_currentVelocityFactor); } - // 2. Find bubble spawner and slow down existing bubbles + // 3. Find bubble spawner and slow down existing bubbles (no velocity management needed) BubbleSpawner bubbleSpawner = FindFirstObjectByType(); if (bubbleSpawner != null) { bubbleSpawner.StartSurfacing(); } - // 3. Find obstacle spawner and reverse existing obstacles + // 4. Find obstacle spawner and set up for velocity changes ObstacleSpawner obstacleSpawner = FindFirstObjectByType(); if (obstacleSpawner != null) { + // Subscribe to velocity changes + OnVelocityFactorChanged -= obstacleSpawner.OnVelocityFactorChanged; + OnVelocityFactorChanged += obstacleSpawner.OnVelocityFactorChanged; + + // Tell spawner to reverse spawn/despawn logic obstacleSpawner.StartSurfacing(); + + // Immediately send current velocity factor + obstacleSpawner.OnVelocityFactorChanged(_currentVelocityFactor); } - // Note: Monster spawning is handled automatically through the Update and OnTileSpawned methods - // which will check the _isSurfacing flag + Debug.Log($"[DivingGameManager] Started surfacing with target velocity factor: {targetVelocityFactor}"); } // Call this when the game ends @@ -377,5 +409,49 @@ namespace Minigames.DivingForPictures // Final score could be saved to player prefs or other persistence Debug.Log($"Final Score: {playerScore}"); } + + /// + /// Starts a smooth transition to the new velocity factor + /// + /// Target velocity factor (e.g., -1.0 for surfacing speed) + public void SetVelocityFactor(float targetFactor) + { + if (_velocityTransitionCoroutine != null) + { + StopCoroutine(_velocityTransitionCoroutine); + } + + _velocityTransitionCoroutine = StartCoroutine(TransitionVelocityFactor(targetFactor)); + } + + /// + /// Coroutine to smoothly transition the velocity factor over time + /// + private IEnumerator TransitionVelocityFactor(float targetFactor) + { + float startFactor = _currentVelocityFactor; + float elapsed = 0f; + + while (elapsed < speedTransitionDuration) + { + elapsed += Time.deltaTime; + float t = Mathf.Clamp01(elapsed / speedTransitionDuration); + + // Smooth step interpolation + float smoothStep = t * t * (3f - 2f * t); + + _currentVelocityFactor = Mathf.Lerp(startFactor, targetFactor, smoothStep); + + // Notify listeners about the velocity factor change + OnVelocityFactorChanged?.Invoke(_currentVelocityFactor); + + yield return null; + } + + _currentVelocityFactor = targetFactor; + + // Final assignment to ensure exact target value + OnVelocityFactorChanged?.Invoke(_currentVelocityFactor); + } } } diff --git a/Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs b/Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs index 2f430646..2d285271 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/FloatingObstacle.cs @@ -48,6 +48,8 @@ namespace Minigames.DivingForPictures private Coroutine _movementCoroutine; private Coroutine _offScreenCheckCoroutine; private bool _isSurfacing = false; // Flag to track surfacing state + private float _velocityFactor = 1.0f; // Current velocity factor from game manager + private float _baseMoveSpeed; // Original move speed before velocity factor is applied private void Awake() { @@ -64,6 +66,7 @@ namespace Minigames.DivingForPictures } _mainCamera = Camera.main; + _baseMoveSpeed = moveSpeed; // Store original speed } private void OnEnable() @@ -107,6 +110,30 @@ namespace Minigames.DivingForPictures } } + /// + /// Called when the velocity factor changes from the DivingGameManager via ObstacleSpawner + /// + public void OnVelocityFactorChanged(float velocityFactor) + { + _velocityFactor = velocityFactor; + + // Update actual move speed based on velocity factor and base speed + // We use Abs for magnitude and Sign for direction + moveSpeed = _baseMoveSpeed * Mathf.Abs(_velocityFactor); + + // Restart movement with new speed if needed + if (enableMovement && gameObject.activeInHierarchy) + { + if (_movementCoroutine != null) + { + StopCoroutine(_movementCoroutine); + } + _movementCoroutine = StartCoroutine(MovementCoroutine()); + } + + Debug.Log($"[FloatingObstacle] {gameObject.name} velocity factor updated to {_velocityFactor:F2}, speed: {moveSpeed:F2}"); + } + /// /// Coroutine that handles obstacle movement /// @@ -114,8 +141,12 @@ namespace Minigames.DivingForPictures { while (enabled && gameObject.activeInHierarchy) { - // Move the obstacle upward - transform.position += Vector3.up * (moveSpeed * Time.deltaTime); + // Use velocity factor sign to determine direction + Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor); + float speed = moveSpeed * Time.deltaTime; + + // Apply movement in correct direction + transform.position += direction * speed; // Wait for next frame yield return null; diff --git a/Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs b/Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs index e3ecdcd4..8c69ec38 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/ObstacleSpawner.cs @@ -76,6 +76,7 @@ namespace Minigames.DivingForPictures private readonly List _activeObstacles = new List(); private int _obstacleCounter = 0; // Counter for unique obstacle naming private bool _isSurfacing = false; // Flag to track surfacing state + private float _velocityFactor = 1.0f; // Current velocity factor from the game manager private void Awake() { @@ -491,6 +492,29 @@ namespace Minigames.DivingForPictures CalculateScreenBounds(); } + /// + /// Called when the velocity factor changes from the DivingGameManager + /// + public void OnVelocityFactorChanged(float velocityFactor) + { + _velocityFactor = velocityFactor; + + // Update all active obstacles with the new velocity factor + foreach (GameObject obstacle in _activeObstacles) + { + if (obstacle != null) + { + FloatingObstacle obstacleComponent = obstacle.GetComponent(); + if (obstacleComponent != null) + { + obstacleComponent.OnVelocityFactorChanged(velocityFactor); + } + } + } + + Debug.Log($"[ObstacleSpawner] Velocity factor updated to {_velocityFactor:F2}, propagated to {_activeObstacles.Count} active obstacles"); + } + /// /// Start surfacing mode - reverse direction of existing obstacles and stop spawning new ones /// @@ -500,7 +524,7 @@ namespace Minigames.DivingForPictures _isSurfacing = true; - // Reverse direction of all existing obstacles + // Notify obstacles about surfacing state (for direction-based logic) foreach (GameObject obstacle in _activeObstacles) { if (obstacle != null) @@ -514,7 +538,7 @@ namespace Minigames.DivingForPictures } } - Debug.Log($"[ObstacleSpawner] Started surfacing mode. Reversed direction of {_activeObstacles.Count} active obstacles."); + Debug.Log($"[ObstacleSpawner] Started surfacing mode for {_activeObstacles.Count} active obstacles"); } /// diff --git a/Assets/Scripts/Minigames/DivingForPictures/TrenchTileSpawner.cs b/Assets/Scripts/Minigames/DivingForPictures/TrenchTileSpawner.cs index e436b914..f3d3cba9 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/TrenchTileSpawner.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/TrenchTileSpawner.cs @@ -61,10 +61,15 @@ namespace Minigames.DivingForPictures // Direction state private bool _isSurfacing = false; + + // 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(); @@ -273,6 +278,23 @@ namespace Minigames.DivingForPictures _screenTop = top.y; } + /// + /// Called when the velocity factor changes from the DivingGameManager + /// + 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}"); + } + /// /// Reverses direction to start surfacing /// @@ -280,17 +302,13 @@ namespace Minigames.DivingForPictures { if (_isSurfacing) return; // Already surfacing - // Reverse the movement direction - moveSpeed *= -1; - - // Update velocity immediately - CalculateVelocity(); + // Set surfacing flag for spawn/despawn logic + _isSurfacing = true; // Reverse the active tiles array to maintain consistent indexing logic _activeTiles.Reverse(); - // Set surfacing flag - _isSurfacing = true; + Debug.Log("[TrenchTileSpawner] Started surfacing - reversed array order"); } /// @@ -302,8 +320,12 @@ namespace Minigames.DivingForPictures { if (tile != null) { - // Movement will automatically adapt to negative velocity when surfacing - tile.transform.position += Vector3.up * _currentVelocity; + // Use velocity factor to determine direction + Vector3 direction = Vector3.up * Mathf.Sign(_velocityFactor); + float speed = _currentVelocity; + + // Apply movement + tile.transform.position += direction * speed; } } }