Revamp game pausing and input handling. Fix minigame tutorial and end sequence. (#39)
- Revamp pausing and centralize management in GameManager - Switch Pause implementation to be counter-based to solve corner case of multiple pause requests - Remove duplicated Pause logic from other components - Add pausing when browsing the card album - Fully deliver the exclusive UI implementation - Spruce up the MiniGame tutorial with correct pausing, hiding other UI - Correctly unpause after showing tutorial - Fix minigame ending sequence. The cinematic correctly plays only once now - Replaying the minigame works Co-authored-by: Michal Adam Pikulski <michal@foolhardyhorizons.com> Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: #39
This commit is contained in:
@@ -29,12 +29,6 @@ namespace Minigames.DivingForPictures
|
||||
private Coroutine _wobbleCoroutine;
|
||||
private Coroutine _offScreenCheckCoroutine;
|
||||
|
||||
// Pause state tracking
|
||||
private bool _isPaused = false;
|
||||
|
||||
// IPausable implementation
|
||||
public bool IsPaused => _isPaused;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Cache references and randomize time offset for wobble
|
||||
@@ -67,9 +61,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if (_isPaused) return; // Already paused
|
||||
|
||||
_isPaused = true;
|
||||
StopBubbleBehavior();
|
||||
|
||||
// Debug log for troubleshooting
|
||||
@@ -81,9 +72,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void DoResume()
|
||||
{
|
||||
if (!_isPaused) return; // Already running
|
||||
|
||||
_isPaused = false;
|
||||
StartBubbleBehavior();
|
||||
|
||||
// Debug log for troubleshooting
|
||||
@@ -95,7 +83,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void StartBubbleBehavior()
|
||||
{
|
||||
if (_isPaused || !isActiveAndEnabled) return; // Don't start if paused
|
||||
if (GameManager.Instance.IsPaused || !isActiveAndEnabled) return; // Don't start if paused
|
||||
|
||||
_movementCoroutine = StartCoroutine(MovementCoroutine());
|
||||
_wobbleCoroutine = StartCoroutine(WobbleCoroutine());
|
||||
|
||||
@@ -25,15 +25,9 @@ namespace Minigames.DivingForPictures
|
||||
private UnityEngine.Camera _mainCamera; // Cache camera reference
|
||||
private bool _isSurfacing = false;
|
||||
|
||||
// Pause state
|
||||
private bool _isPaused = false;
|
||||
|
||||
// Coroutines for pause/resume
|
||||
private Coroutine _spawnCoroutine;
|
||||
|
||||
// IPausable implementation
|
||||
public bool IsPaused => _isPaused;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_mainCamera = UnityEngine.Camera.main;
|
||||
@@ -87,10 +81,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if (_isPaused) return; // Already paused
|
||||
|
||||
_isPaused = true;
|
||||
|
||||
// Stop spawning coroutine
|
||||
if (_spawnCoroutine != null)
|
||||
{
|
||||
@@ -116,10 +106,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void DoResume()
|
||||
{
|
||||
if (!_isPaused) return; // Already running
|
||||
|
||||
_isPaused = false;
|
||||
|
||||
// Restart spawning coroutine
|
||||
StartSpawningCoroutine();
|
||||
|
||||
@@ -141,7 +127,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void StartSpawningCoroutine()
|
||||
{
|
||||
if (_spawnCoroutine == null && !_isPaused)
|
||||
if (_spawnCoroutine == null && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
_spawnCoroutine = StartCoroutine(SpawnBubblesRoutine());
|
||||
}
|
||||
@@ -219,7 +205,7 @@ namespace Minigames.DivingForPictures
|
||||
bubble.SetWobbleScaleLimits(_devSettings.BubbleWobbleMinScale, _devSettings.BubbleWobbleMaxScale);
|
||||
|
||||
// If the game is already paused, pause this bubble immediately
|
||||
if (_isPaused)
|
||||
if (GameManager.Instance.IsPaused)
|
||||
{
|
||||
bubble.Pause();
|
||||
}
|
||||
@@ -262,7 +248,7 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
Logging.Debug("[BubbleSpawner] Started bubble spawning coroutine");
|
||||
|
||||
while (enabled && gameObject.activeInHierarchy && !_isPaused)
|
||||
while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
SpawnBubble();
|
||||
SetNextSpawnInterval(); // Set interval for next spawn
|
||||
|
||||
@@ -7,8 +7,9 @@ using Minigames.DivingForPictures.PictureCamera;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Bootstrap;
|
||||
using UI;
|
||||
using UI.Core;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Playables;
|
||||
@@ -38,24 +39,24 @@ namespace Minigames.DivingForPictures
|
||||
public CameraViewfinderManager viewfinderManager;
|
||||
|
||||
// Settings reference
|
||||
private IDivingMinigameSettings settings;
|
||||
private IDivingMinigameSettings _settings;
|
||||
|
||||
// Private state variables
|
||||
private int playerScore = 0;
|
||||
private float currentSpawnProbability;
|
||||
private float lastSpawnTime = -100f;
|
||||
private float timeSinceLastSpawn = 0f;
|
||||
private List<Monster> activeMonsters = new List<Monster>();
|
||||
private int _playerScore = 0;
|
||||
private float _currentSpawnProbability;
|
||||
private float _lastSpawnTime = -100f;
|
||||
private float _timeSinceLastSpawn = 0f;
|
||||
private List<Monster> _activeMonsters = new List<Monster>();
|
||||
|
||||
// Velocity management
|
||||
// Velocity state tracking
|
||||
private float currentVelocityFactor = 1.0f; // 1.0 = normal descent speed, -1.0 * surfacingSpeedFactor = full surfacing speed
|
||||
private Coroutine velocityTransitionCoroutine;
|
||||
private Coroutine surfacingSequenceCoroutine;
|
||||
private float _currentVelocityFactor = 1.0f; // 1.0 = normal descent speed, -1.0 * surfacingSpeedFactor = full surfacing speed
|
||||
private Coroutine _velocityTransitionCoroutine;
|
||||
private Coroutine _surfacingSequenceCoroutine;
|
||||
|
||||
// Public properties
|
||||
public int PlayerScore => playerScore;
|
||||
public float CurrentVelocityFactor => currentVelocityFactor;
|
||||
public int PlayerScore => _playerScore;
|
||||
public float CurrentVelocityFactor => _currentVelocityFactor;
|
||||
|
||||
// Events
|
||||
public event Action<int> OnScoreChanged;
|
||||
@@ -67,8 +68,8 @@ namespace Minigames.DivingForPictures
|
||||
public event Action<float> OnVelocityFactorChanged;
|
||||
|
||||
// Private state variables for rope system
|
||||
private int currentRopeIndex = 0;
|
||||
private bool isGameOver = false;
|
||||
private int _currentRopeIndex = 0;
|
||||
private bool _isGameOver = false;
|
||||
private bool _isSurfacing = false;
|
||||
|
||||
// Initialization state
|
||||
@@ -77,23 +78,17 @@ namespace Minigames.DivingForPictures
|
||||
// Used to track if we're currently surfacing
|
||||
public bool IsSurfacing => _isSurfacing;
|
||||
|
||||
// Event for game components to subscribe to
|
||||
// TODO: Get rid of this in favor of proper game pausing?
|
||||
public event Action OnGameInitialized;
|
||||
|
||||
// Pause state
|
||||
private bool _isPaused = false;
|
||||
|
||||
// List of pausable components controlled by this manager
|
||||
private List<IPausable> _pausableComponents = new List<IPausable>();
|
||||
|
||||
// IPausable implementation
|
||||
public bool IsPaused => _isPaused;
|
||||
|
||||
// Photo sequence state
|
||||
private bool _isPhotoSequenceActive = false;
|
||||
private Monster _currentPhotoTarget = null;
|
||||
private Dictionary<IPausable, bool> _pauseStateBackup = new Dictionary<IPausable, bool>();
|
||||
private float _capturedProximity = 0f; // New: tracks how close to target the photo was taken (0-1)
|
||||
private float _capturedProximity = 0f;
|
||||
|
||||
// List of components to exempt from pausing during photo sequence
|
||||
private List<IPausable> _exemptFromPhotoSequencePausing = new List<IPausable>();
|
||||
@@ -101,7 +96,6 @@ namespace Minigames.DivingForPictures
|
||||
// Photo sequence events
|
||||
public event Action<Monster> OnPhotoSequenceStarted;
|
||||
public event Action<Monster, float> OnPhotoSequenceCompleted; // Now includes proximity score
|
||||
public event Action<float> OnPhotoSequenceProgressUpdated;
|
||||
|
||||
private static DivingGameManager _instance = null;
|
||||
private static bool _isQuitting = false;
|
||||
@@ -113,8 +107,8 @@ namespace Minigames.DivingForPictures
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||
currentSpawnProbability = settings?.BaseSpawnProbability ?? 0.2f;
|
||||
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||
_currentSpawnProbability = _settings?.BaseSpawnProbability ?? 0.2f;
|
||||
|
||||
if (_instance == null)
|
||||
{
|
||||
@@ -124,6 +118,9 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
// Ensure any previous run state is reset when this manager awakes
|
||||
_isGameOver = false;
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
@@ -133,44 +130,8 @@ namespace Minigames.DivingForPictures
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Find PauseMenu and subscribe to its events
|
||||
PauseMenu pauseMenu = PauseMenu.Instance;
|
||||
if (pauseMenu != null)
|
||||
{
|
||||
pauseMenu.OnGamePaused += Pause;
|
||||
pauseMenu.OnGameResumed += DoResume;
|
||||
|
||||
Logging.Debug("[DivingGameManager] Subscribed to PauseMenu events");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("[DivingGameManager] PauseMenu not found. Pause functionality won't work properly.");
|
||||
}
|
||||
|
||||
// Register this manager with the global GameManager
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.RegisterPausableComponent(this);
|
||||
}
|
||||
|
||||
// Subscribe to SceneOrientationEnforcer's event
|
||||
if (SceneOrientationEnforcer.Instance != null)
|
||||
{
|
||||
SceneOrientationEnforcer.Instance.OnOrientationCorrect += InitializeGame;
|
||||
SceneOrientationEnforcer.Instance.OnOrientationIncorrect += Pause;
|
||||
|
||||
// If orientation is already correct, initialize right away
|
||||
// This prevents issues if the orientation was already correct before subscription
|
||||
if (SceneOrientationEnforcer.Instance.IsOrientationCorrect())
|
||||
{
|
||||
InitializeGame();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("[DivingGameManager] SceneOrientationEnforcer not found. Initializing game immediately.");
|
||||
InitializeGame();
|
||||
}
|
||||
// Register for post-boot initialization
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
|
||||
// Subscribe to player damage events (this doesn't depend on initialization)
|
||||
PlayerCollisionBehavior.OnDamageTaken += OnPlayerDamageTaken;
|
||||
@@ -189,6 +150,7 @@ namespace Minigames.DivingForPictures
|
||||
viewfinderManager.OnViewfinderTappedDuringAnimation += OnViewfinderTappedDuringAnimation;
|
||||
viewfinderManager.OnReverseAnimationStarted += OnReverseAnimationStarted;
|
||||
|
||||
// TODO: Give this a second look and make sure this is correct
|
||||
// Add the viewfinder manager to exempt list to ensure it keeps working during photo sequences
|
||||
if (viewfinderManager is IPausable viewfinderPausable)
|
||||
{
|
||||
@@ -197,6 +159,36 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
|
||||
OnMonsterSpawned += DoMonsterSpawned;
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Register this manager with the global GameManager
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.RegisterPausableComponent(this);
|
||||
}
|
||||
|
||||
// Subscribe to SceneOrientationEnforcer's event
|
||||
if (SceneOrientationEnforcer.Instance != null)
|
||||
{
|
||||
// TODO: This is a bit of a hack to make sure the game is initialized after the orientation is correct
|
||||
SceneOrientationEnforcer.Instance.OnOrientationCorrect += InitializeGame;
|
||||
SceneOrientationEnforcer.Instance.OnOrientationIncorrect += Pause;
|
||||
|
||||
// If orientation is already correct, initialize right away
|
||||
// This prevents issues if the orientation was already correct before subscription
|
||||
if (SceneOrientationEnforcer.Instance.IsOrientationCorrect())
|
||||
{
|
||||
InitializeGame();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning("[DivingGameManager] SceneOrientationEnforcer not found. Initializing game immediately.");
|
||||
InitializeGame();
|
||||
}
|
||||
|
||||
CinematicsManager.Instance.OnCinematicStopped += EndGame;
|
||||
}
|
||||
|
||||
@@ -211,14 +203,6 @@ namespace Minigames.DivingForPictures
|
||||
SceneOrientationEnforcer.Instance.OnOrientationIncorrect -= Pause;
|
||||
}
|
||||
|
||||
// Unsubscribe from PauseMenu events
|
||||
PauseMenu pauseMenu = PauseMenu.Instance;
|
||||
if (pauseMenu != null)
|
||||
{
|
||||
pauseMenu.OnGamePaused -= Pause;
|
||||
pauseMenu.OnGameResumed -= DoResume;
|
||||
}
|
||||
|
||||
// Unregister from GameManager
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
@@ -241,19 +225,19 @@ namespace Minigames.DivingForPictures
|
||||
|
||||
private void Update()
|
||||
{
|
||||
timeSinceLastSpawn += Time.deltaTime;
|
||||
_timeSinceLastSpawn += Time.deltaTime;
|
||||
|
||||
// Gradually increase spawn probability over time
|
||||
float previousProbability = currentSpawnProbability;
|
||||
if (currentSpawnProbability < settings.MaxSpawnProbability)
|
||||
float previousProbability = _currentSpawnProbability;
|
||||
if (_currentSpawnProbability < _settings.MaxSpawnProbability)
|
||||
{
|
||||
currentSpawnProbability += settings.ProbabilityIncreaseRate * Time.deltaTime;
|
||||
currentSpawnProbability = Mathf.Min(currentSpawnProbability, settings.MaxSpawnProbability);
|
||||
_currentSpawnProbability += _settings.ProbabilityIncreaseRate * Time.deltaTime;
|
||||
_currentSpawnProbability = Mathf.Min(_currentSpawnProbability, _settings.MaxSpawnProbability);
|
||||
|
||||
// Only fire event if probability changed significantly
|
||||
if (Mathf.Abs(currentSpawnProbability - previousProbability) > 0.01f)
|
||||
if (Mathf.Abs(_currentSpawnProbability - previousProbability) > 0.01f)
|
||||
{
|
||||
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability);
|
||||
OnSpawnProbabilityChanged?.Invoke(_currentSpawnProbability);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,14 +252,14 @@ namespace Minigames.DivingForPictures
|
||||
// If we're surfacing, don't spawn new monsters
|
||||
if (_isSurfacing) return;
|
||||
|
||||
bool forceSpawn = timeSinceLastSpawn >= settings.GuaranteedSpawnTime;
|
||||
bool onCooldown = timeSinceLastSpawn < settings.SpawnCooldown;
|
||||
bool forceSpawn = _timeSinceLastSpawn >= _settings.GuaranteedSpawnTime;
|
||||
bool onCooldown = _timeSinceLastSpawn < _settings.SpawnCooldown;
|
||||
|
||||
// Don't spawn if on cooldown, unless forced
|
||||
if (onCooldown && !forceSpawn) return;
|
||||
|
||||
// Check probability or forced spawn
|
||||
if (forceSpawn || UnityEngine.Random.value <= currentSpawnProbability)
|
||||
if (forceSpawn || UnityEngine.Random.value <= _currentSpawnProbability)
|
||||
{
|
||||
// Pick a random spawn point from this tile
|
||||
MonsterSpawnPoint spawnPoint = spawnPoints[UnityEngine.Random.Range(0, spawnPoints.Length)];
|
||||
@@ -284,10 +268,10 @@ namespace Minigames.DivingForPictures
|
||||
SpawnMonster(spawnPoint.transform);
|
||||
|
||||
// Reset timer and adjust probability
|
||||
lastSpawnTime = Time.time;
|
||||
timeSinceLastSpawn = 0f;
|
||||
currentSpawnProbability = settings.BaseSpawnProbability;
|
||||
OnSpawnProbabilityChanged?.Invoke(currentSpawnProbability);
|
||||
_lastSpawnTime = Time.time;
|
||||
_timeSinceLastSpawn = 0f;
|
||||
_currentSpawnProbability = _settings.BaseSpawnProbability;
|
||||
OnSpawnProbabilityChanged?.Invoke(_currentSpawnProbability);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,14 +319,14 @@ namespace Minigames.DivingForPictures
|
||||
private void DoPictureTaken(Monster monster)
|
||||
{
|
||||
// Calculate points based on depth
|
||||
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * settings.DepthMultiplier);
|
||||
int pointsAwarded = settings.BasePoints + depthBonus;
|
||||
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier);
|
||||
int pointsAwarded = _settings.BasePoints + depthBonus;
|
||||
|
||||
// Add score
|
||||
playerScore += pointsAwarded;
|
||||
_playerScore += pointsAwarded;
|
||||
|
||||
// Fire events
|
||||
OnScoreChanged?.Invoke(playerScore);
|
||||
OnScoreChanged?.Invoke(_playerScore);
|
||||
OnPictureTaken?.Invoke(monster, pointsAwarded);
|
||||
}
|
||||
|
||||
@@ -351,13 +335,13 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void OnPlayerDamageTaken()
|
||||
{
|
||||
if (isGameOver) return;
|
||||
if (_isGameOver) return;
|
||||
|
||||
// Break the next rope in sequence
|
||||
BreakNextRope();
|
||||
|
||||
// Check if all ropes are broken
|
||||
if (currentRopeIndex >= playerRopes.Length)
|
||||
if (_currentRopeIndex >= playerRopes.Length)
|
||||
{
|
||||
TriggerGameOver();
|
||||
deathAudioPlayer.Play();
|
||||
@@ -365,7 +349,7 @@ namespace Minigames.DivingForPictures
|
||||
else
|
||||
{
|
||||
// Notify listeners about rope break and remaining ropes
|
||||
int remainingRopes = playerRopes.Length - currentRopeIndex;
|
||||
int remainingRopes = playerRopes.Length - _currentRopeIndex;
|
||||
OnRopeBroken?.Invoke(remainingRopes);
|
||||
|
||||
Logging.Debug($"[DivingGameManager] Rope broken! {remainingRopes} ropes remaining.");
|
||||
@@ -377,9 +361,9 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void BreakNextRope()
|
||||
{
|
||||
if (currentRopeIndex < playerRopes.Length)
|
||||
if (_currentRopeIndex < playerRopes.Length)
|
||||
{
|
||||
RopeBreaker ropeToBreak = playerRopes[currentRopeIndex];
|
||||
RopeBreaker ropeToBreak = playerRopes[_currentRopeIndex];
|
||||
|
||||
if (ropeToBreak != null)
|
||||
{
|
||||
@@ -388,11 +372,11 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[DivingGameManager] Rope at index {currentRopeIndex} is null!");
|
||||
Logging.Warning($"[DivingGameManager] Rope at index {_currentRopeIndex} is null!");
|
||||
}
|
||||
|
||||
// Move to the next rope regardless if current was null
|
||||
currentRopeIndex++;
|
||||
_currentRopeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +385,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void ForceBreakRope()
|
||||
{
|
||||
if (!isGameOver)
|
||||
if (!_isGameOver)
|
||||
{
|
||||
OnPlayerDamageTaken();
|
||||
}
|
||||
@@ -412,9 +396,9 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void TriggerGameOver()
|
||||
{
|
||||
if (isGameOver) return;
|
||||
if (_isGameOver) return;
|
||||
|
||||
isGameOver = true;
|
||||
_isGameOver = true;
|
||||
Logging.Debug("[DivingGameManager] Game Over! All ropes broken. Starting surfacing sequence...");
|
||||
|
||||
// Fire game over event
|
||||
@@ -450,8 +434,8 @@ namespace Minigames.DivingForPictures
|
||||
public void ResetRopeSystem()
|
||||
{
|
||||
// Reset rope state
|
||||
currentRopeIndex = 0;
|
||||
isGameOver = false;
|
||||
_currentRopeIndex = 0;
|
||||
_isGameOver = false;
|
||||
|
||||
// Restore all broken ropes
|
||||
if (playerRopes != null)
|
||||
@@ -477,8 +461,11 @@ namespace Minigames.DivingForPictures
|
||||
|
||||
_isSurfacing = true;
|
||||
|
||||
// TODO: Call it here?
|
||||
UIPageController.Instance.HideAllUI();
|
||||
|
||||
// 1. Initiate smooth velocity transition to surfacing speed
|
||||
float targetVelocityFactor = -1.0f * settings.SurfacingSpeedFactor;
|
||||
float targetVelocityFactor = -1.0f * _settings.SurfacingSpeedFactor;
|
||||
SetVelocityFactor(targetVelocityFactor);
|
||||
|
||||
// 2. Find and notify trench tile spawner about direction change (for spawning/despawning logic)
|
||||
@@ -497,7 +484,7 @@ namespace Minigames.DivingForPictures
|
||||
tileSpawner.StartSurfacing();
|
||||
|
||||
// Immediately send current velocity factor
|
||||
tileSpawner.OnVelocityFactorChanged(currentVelocityFactor);
|
||||
tileSpawner.OnVelocityFactorChanged(_currentVelocityFactor);
|
||||
}
|
||||
|
||||
// Handle the Rock object - disable components and animate it falling offscreen
|
||||
@@ -565,15 +552,15 @@ namespace Minigames.DivingForPictures
|
||||
obstacleSpawner.StartSurfacing();
|
||||
|
||||
// Immediately send current velocity factor
|
||||
obstacleSpawner.OnVelocityFactorChanged(currentVelocityFactor);
|
||||
obstacleSpawner.OnVelocityFactorChanged(_currentVelocityFactor);
|
||||
}
|
||||
|
||||
// Start the surfacing sequence coroutine
|
||||
if (surfacingSequenceCoroutine != null)
|
||||
if (_surfacingSequenceCoroutine != null)
|
||||
{
|
||||
StopCoroutine(surfacingSequenceCoroutine);
|
||||
StopCoroutine(_surfacingSequenceCoroutine);
|
||||
}
|
||||
surfacingSequenceCoroutine = StartCoroutine(SurfacingSequence());
|
||||
_surfacingSequenceCoroutine = StartCoroutine(SurfacingSequence());
|
||||
|
||||
Logging.Debug($"[DivingGameManager] Started surfacing with target velocity factor: {targetVelocityFactor}");
|
||||
}
|
||||
@@ -649,7 +636,7 @@ namespace Minigames.DivingForPictures
|
||||
private IEnumerator SurfacingSequence()
|
||||
{
|
||||
// Wait for the configured delay
|
||||
yield return new WaitForSeconds(settings.SurfacingSpawnDelay);
|
||||
yield return new WaitForSeconds(_settings.SurfacingSpawnDelay);
|
||||
|
||||
// Find tile spawner and tell it to stop spawning
|
||||
TrenchTileSpawner tileSpawner = FindFirstObjectByType<TrenchTileSpawner>();
|
||||
@@ -686,7 +673,6 @@ namespace Minigames.DivingForPictures
|
||||
// Call this when the game ends
|
||||
public void EndGame()
|
||||
{
|
||||
// TODO: Investigate why called twice
|
||||
CinematicsManager.Instance.OnCinematicStopped -= EndGame;
|
||||
// Start the end game sequence that grants a booster, waits for the UI animation, then shows Game Over.
|
||||
StartCoroutine(EndGameSequence());
|
||||
@@ -695,7 +681,7 @@ namespace Minigames.DivingForPictures
|
||||
private IEnumerator EndGameSequence()
|
||||
{
|
||||
// Clean up active monsters
|
||||
foreach (var monster in activeMonsters.ToArray())
|
||||
foreach (var monster in _activeMonsters.ToArray())
|
||||
{
|
||||
if (monster != null)
|
||||
{
|
||||
@@ -703,7 +689,7 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
}
|
||||
|
||||
activeMonsters.Clear();
|
||||
_activeMonsters.Clear();
|
||||
|
||||
// 1) Call the booster pack giver if available
|
||||
bool completed = false;
|
||||
@@ -714,6 +700,7 @@ namespace Minigames.DivingForPictures
|
||||
UnityAction onDone = null;
|
||||
onDone = () => { completed = true; giver.OnCompleted.RemoveListener(onDone); };
|
||||
giver.OnCompleted.AddListener(onDone);
|
||||
UIPageController.Instance.ShowAllUI();
|
||||
giver.GiveBoosterPack();
|
||||
|
||||
// 2) Wait for it to finish (with a safety timeout in case it's not wired)
|
||||
@@ -733,9 +720,9 @@ namespace Minigames.DivingForPictures
|
||||
|
||||
// 3) Only then show the game over screen
|
||||
CinematicsManager.Instance.ShowGameOverScreen();
|
||||
|
||||
|
||||
// Final score could be saved to player prefs or other persistence
|
||||
Logging.Debug($"Final Score: {playerScore}");
|
||||
Logging.Debug($"Final Score: {_playerScore}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -744,12 +731,12 @@ namespace Minigames.DivingForPictures
|
||||
/// <param name="targetFactor">Target velocity factor (e.g., -1.0 for surfacing speed)</param>
|
||||
public void SetVelocityFactor(float targetFactor)
|
||||
{
|
||||
if (velocityTransitionCoroutine != null)
|
||||
if (_velocityTransitionCoroutine != null)
|
||||
{
|
||||
StopCoroutine(velocityTransitionCoroutine);
|
||||
StopCoroutine(_velocityTransitionCoroutine);
|
||||
}
|
||||
|
||||
velocityTransitionCoroutine = StartCoroutine(TransitionVelocityFactor(targetFactor));
|
||||
_velocityTransitionCoroutine = StartCoroutine(TransitionVelocityFactor(targetFactor));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -757,29 +744,29 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private IEnumerator<WaitForEndOfFrame> TransitionVelocityFactor(float targetFactor)
|
||||
{
|
||||
float startFactor = currentVelocityFactor;
|
||||
float startFactor = _currentVelocityFactor;
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < settings.SpeedTransitionDuration)
|
||||
while (elapsed < _settings.SpeedTransitionDuration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / settings.SpeedTransitionDuration);
|
||||
float t = Mathf.Clamp01(elapsed / _settings.SpeedTransitionDuration);
|
||||
|
||||
// Smooth step interpolation
|
||||
float smoothStep = t * t * (3f - 2f * t);
|
||||
|
||||
currentVelocityFactor = Mathf.Lerp(startFactor, targetFactor, smoothStep);
|
||||
_currentVelocityFactor = Mathf.Lerp(startFactor, targetFactor, smoothStep);
|
||||
|
||||
// Notify listeners about the velocity factor change
|
||||
OnVelocityFactorChanged?.Invoke(currentVelocityFactor);
|
||||
OnVelocityFactorChanged?.Invoke(_currentVelocityFactor);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
currentVelocityFactor = targetFactor;
|
||||
_currentVelocityFactor = targetFactor;
|
||||
|
||||
// Final assignment to ensure exact target value
|
||||
OnVelocityFactorChanged?.Invoke(currentVelocityFactor);
|
||||
OnVelocityFactorChanged?.Invoke(_currentVelocityFactor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -793,7 +780,7 @@ namespace Minigames.DivingForPictures
|
||||
_pausableComponents.Add(component);
|
||||
|
||||
// If the game is already paused, pause the component immediately
|
||||
if (_isPaused)
|
||||
if (GameManager.Instance.IsPaused)
|
||||
{
|
||||
component.Pause();
|
||||
}
|
||||
@@ -820,48 +807,46 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
// Ignore pause requests once the game has reached Game Over
|
||||
if (_isGameOver) return;
|
||||
DoPause();
|
||||
}
|
||||
|
||||
public void DoPause(bool turnOffGameInput = true)
|
||||
{
|
||||
if (_isPaused) return; // Already paused
|
||||
|
||||
_isPaused = true;
|
||||
|
||||
// Pause all registered components
|
||||
foreach (var component in _pausableComponents)
|
||||
{
|
||||
component.Pause();
|
||||
}
|
||||
|
||||
// Change input mode to UI when menu is open
|
||||
if(turnOffGameInput)
|
||||
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
||||
|
||||
Logging.Debug($"[DivingGameManager] Game paused. Paused {_pausableComponents.Count} components.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume the game and all registered components
|
||||
/// </summary>
|
||||
public void DoResume()
|
||||
{
|
||||
if (!_isPaused) return; // Already running
|
||||
|
||||
_isPaused = false;
|
||||
|
||||
// Resume all registered components
|
||||
foreach (var component in _pausableComponents)
|
||||
{
|
||||
component.DoResume();
|
||||
}
|
||||
|
||||
// Change input mode to UI when menu is open
|
||||
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
||||
|
||||
Logging.Debug($"[DivingGameManager] Game resumed. Resumed {_pausableComponents.Count} components.");
|
||||
}
|
||||
}
|
||||
|
||||
public void DoPause(bool turnOffGameInput = true)
|
||||
{
|
||||
// Ignore pause requests once the game has ended
|
||||
if (_isGameOver) return;
|
||||
// Pause all registered components
|
||||
foreach (var component in _pausableComponents)
|
||||
{
|
||||
component.Pause();
|
||||
}
|
||||
|
||||
// Change input mode to UI when menu is open
|
||||
if(turnOffGameInput)
|
||||
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
||||
|
||||
Logging.Debug($"[DivingGameManager] Game paused. Paused {_pausableComponents.Count} components.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume the game and all registered components
|
||||
/// </summary>
|
||||
public void DoResume()
|
||||
{
|
||||
// Ignore resume requests once the game has ended
|
||||
if (_isGameOver) return;
|
||||
// Resume all registered components
|
||||
foreach (var component in _pausableComponents)
|
||||
{
|
||||
component.DoResume();
|
||||
}
|
||||
|
||||
// Change input mode to UI when menu is open
|
||||
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
|
||||
|
||||
Logging.Debug($"[DivingGameManager] Game resumed. Resumed {_pausableComponents.Count} components.");
|
||||
}
|
||||
|
||||
#region Photo Sequence Methods
|
||||
|
||||
@@ -938,23 +923,23 @@ namespace Minigames.DivingForPictures
|
||||
if (monster == null) return;
|
||||
|
||||
// Calculate base points from depth
|
||||
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * settings.DepthMultiplier);
|
||||
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier);
|
||||
|
||||
// Apply proximity multiplier (0-100%)
|
||||
float proximityMultiplier = Mathf.Clamp01(proximity); // Ensure it's in 0-1 range
|
||||
int proximityBonus = Mathf.RoundToInt(settings.BasePoints * proximityMultiplier);
|
||||
int proximityBonus = Mathf.RoundToInt(_settings.BasePoints * proximityMultiplier);
|
||||
|
||||
// Calculate total score
|
||||
int pointsAwarded = settings.BasePoints + proximityBonus + depthBonus;
|
||||
int pointsAwarded = _settings.BasePoints + proximityBonus + depthBonus;
|
||||
|
||||
Logging.Debug($"[DivingGameManager] Picture score calculation: base={proximityBonus} (proximity={proximity:F2}), " +
|
||||
$"depth bonus={depthBonus}, total={pointsAwarded}");
|
||||
|
||||
// Add score
|
||||
playerScore += pointsAwarded;
|
||||
_playerScore += pointsAwarded;
|
||||
|
||||
// Fire events
|
||||
OnScoreChanged?.Invoke(playerScore);
|
||||
OnScoreChanged?.Invoke(_playerScore);
|
||||
OnPictureTaken?.Invoke(monster, pointsAwarded);
|
||||
}
|
||||
|
||||
@@ -1061,14 +1046,14 @@ namespace Minigames.DivingForPictures
|
||||
monster.OnMonsterDespawned += DoMonsterDespawned;
|
||||
|
||||
// Add to active monsters list
|
||||
activeMonsters.Add(monster);
|
||||
_activeMonsters.Add(monster);
|
||||
}
|
||||
}
|
||||
|
||||
private void DoMonsterDespawned(Monster monster)
|
||||
{
|
||||
// Remove from active list
|
||||
activeMonsters.Remove(monster);
|
||||
_activeMonsters.Remove(monster);
|
||||
|
||||
// Unsubscribe from monster events
|
||||
if (monster != null)
|
||||
|
||||
@@ -59,12 +59,6 @@ namespace Minigames.DivingForPictures
|
||||
private float _screenNormalizationFactor = 1.0f;
|
||||
private IDivingMinigameSettings _settings;
|
||||
|
||||
// Pause state
|
||||
private bool _isPaused = false;
|
||||
|
||||
// IPausable implementation
|
||||
public bool IsPaused => _isPaused;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_collider = GetComponent<Collider2D>();
|
||||
@@ -124,7 +118,7 @@ namespace Minigames.DivingForPictures
|
||||
private void OnEnable()
|
||||
{
|
||||
// Only start coroutines if not paused
|
||||
if (!_isPaused)
|
||||
if (!GameManager.Instance.IsPaused)
|
||||
{
|
||||
StartObstacleCoroutines();
|
||||
}
|
||||
@@ -143,9 +137,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if (_isPaused) return; // Already paused
|
||||
|
||||
_isPaused = true;
|
||||
StopObstacleCoroutines();
|
||||
|
||||
Logging.Debug($"[FloatingObstacle] Paused obstacle: {name}");
|
||||
@@ -156,9 +147,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void DoResume()
|
||||
{
|
||||
if (!_isPaused) return; // Already running
|
||||
|
||||
_isPaused = false;
|
||||
StartObstacleCoroutines();
|
||||
|
||||
Logging.Debug($"[FloatingObstacle] Resumed obstacle: {name}");
|
||||
|
||||
@@ -43,12 +43,6 @@ namespace Minigames.DivingForPictures
|
||||
private bool _isSurfacing = false; // Flag to track surfacing state
|
||||
private float _velocityFactor = 1.0f; // Current velocity factor from the game manager
|
||||
|
||||
// Pause state
|
||||
private bool _isPaused = false;
|
||||
|
||||
// IPausable implementation
|
||||
public bool IsPaused => _isPaused;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_mainCamera = UnityEngine.Camera.main;
|
||||
@@ -127,10 +121,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if (_isPaused) return; // Already paused
|
||||
|
||||
_isPaused = true;
|
||||
|
||||
// Stop spawning coroutine
|
||||
if (_spawnCoroutine != null)
|
||||
{
|
||||
@@ -159,10 +149,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void DoResume()
|
||||
{
|
||||
if (!_isPaused) return; // Already running
|
||||
|
||||
_isPaused = false;
|
||||
|
||||
// Restart spawning coroutine if not in surfacing mode
|
||||
if (!_isSurfacing)
|
||||
{
|
||||
@@ -190,7 +176,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void StartSpawnCoroutine()
|
||||
{
|
||||
if (_spawnCoroutine == null && !_isPaused && !_isSurfacing)
|
||||
if (_spawnCoroutine == null && !GameManager.Instance.IsPaused && !_isSurfacing)
|
||||
{
|
||||
_spawnCoroutine = StartCoroutine(SpawnObstacleRoutine());
|
||||
}
|
||||
@@ -201,7 +187,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void StartMoveCoroutine()
|
||||
{
|
||||
if (_moveCoroutine == null && !_isPaused)
|
||||
if (_moveCoroutine == null && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
_moveCoroutine = StartCoroutine(MoveObstaclesRoutine());
|
||||
}
|
||||
@@ -212,7 +198,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void StartDespawnCoroutine()
|
||||
{
|
||||
if (_despawnCoroutine == null && !_isPaused)
|
||||
if (_despawnCoroutine == null && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
_despawnCoroutine = StartCoroutine(DespawnObstaclesRoutine());
|
||||
}
|
||||
@@ -553,7 +539,7 @@ namespace Minigames.DivingForPictures
|
||||
obstacleComponent.SetSpawner(this);
|
||||
|
||||
// If spawner is already paused, pause the obstacle immediately
|
||||
if (_isPaused)
|
||||
if (GameManager.Instance.IsPaused)
|
||||
{
|
||||
obstacleComponent.Pause();
|
||||
}
|
||||
@@ -677,7 +663,7 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
Logging.Debug("[ObstacleSpawner] Started spawning coroutine");
|
||||
|
||||
while (enabled && gameObject.activeInHierarchy && !_isPaused && !_isSurfacing)
|
||||
while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused && !_isSurfacing)
|
||||
{
|
||||
// Calculate next spawn time with variation
|
||||
float nextSpawnTime = _settings.ObstacleSpawnInterval +
|
||||
@@ -707,7 +693,7 @@ namespace Minigames.DivingForPictures
|
||||
Logging.Debug("[ObstacleSpawner] Started obstacle monitoring coroutine");
|
||||
|
||||
// This coroutine now just monitors obstacles, not moves them
|
||||
while (enabled && gameObject.activeInHierarchy && !_isPaused)
|
||||
while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
// Clean up any null references in the active obstacles list
|
||||
_activeObstacles.RemoveAll(obstacle => obstacle == null);
|
||||
@@ -729,7 +715,7 @@ namespace Minigames.DivingForPictures
|
||||
const float checkInterval = 0.5f; // Check every half second
|
||||
Logging.Debug("[ObstacleSpawner] Started despawn coroutine with interval: " + checkInterval);
|
||||
|
||||
while (enabled && gameObject.activeInHierarchy && !_isPaused)
|
||||
while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
// Calculate screen bounds for despawning
|
||||
float despawnBuffer = 2f; // Extra buffer beyond screen edges
|
||||
|
||||
@@ -18,26 +18,26 @@ namespace Minigames.DivingForPictures.Player
|
||||
[SerializeField] private EdgeAnchor edgeAnchor;
|
||||
|
||||
// Settings reference
|
||||
private IDivingMinigameSettings settings;
|
||||
private IDivingMinigameSettings _settings;
|
||||
|
||||
private float targetFingerX;
|
||||
private bool isTouchActive;
|
||||
private float originY;
|
||||
private float _targetFingerX;
|
||||
private bool _isTouchActive;
|
||||
private float _originY;
|
||||
|
||||
// Tap impulse system variables
|
||||
private float tapImpulseStrength = 0f;
|
||||
private float tapDirection = 0f;
|
||||
private float _tapImpulseStrength = 0f;
|
||||
private float _tapDirection = 0f;
|
||||
|
||||
// Initialization flag
|
||||
private bool isInitialized = false;
|
||||
private bool _isInitialized = false;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
originY = transform.position.y;
|
||||
_originY = transform.position.y;
|
||||
|
||||
// Get settings from GameManager
|
||||
settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||
if (settings == null)
|
||||
_settings = GameManager.GetSettingsObject<IDivingMinigameSettings>();
|
||||
if (_settings == null)
|
||||
{
|
||||
Debug.LogError("[PlayerController] Failed to load diving minigame settings!");
|
||||
}
|
||||
@@ -49,8 +49,8 @@ namespace Minigames.DivingForPictures.Player
|
||||
DivingGameManager.Instance.RegisterPausableComponent(this);
|
||||
|
||||
// Initialize target to current position
|
||||
targetFingerX = transform.position.x;
|
||||
isTouchActive = false;
|
||||
_targetFingerX = transform.position.x;
|
||||
_isTouchActive = false;
|
||||
|
||||
// Try to find edge anchor if not assigned
|
||||
if (edgeAnchor == null)
|
||||
@@ -100,12 +100,12 @@ namespace Minigames.DivingForPictures.Player
|
||||
/// </summary>
|
||||
private void Initialize()
|
||||
{
|
||||
if (isInitialized) return;
|
||||
if (_isInitialized) return;
|
||||
|
||||
// Register as default consumer for input
|
||||
InputManager.Instance?.SetDefaultConsumer(this);
|
||||
|
||||
isInitialized = true;
|
||||
_isInitialized = true;
|
||||
Logging.Debug("[PlayerController] Initialized");
|
||||
}
|
||||
|
||||
@@ -130,19 +130,19 @@ namespace Minigames.DivingForPictures.Player
|
||||
public void OnTap(Vector2 worldPosition)
|
||||
{
|
||||
// Ignore input when paused
|
||||
if (isPaused) return;
|
||||
if (GameManager.Instance.IsPaused) return;
|
||||
|
||||
// Logging.Debug($"[EndlessDescenderController] OnTap at {worldPosition}");
|
||||
float targetX = Mathf.Clamp(worldPosition.x, settings.ClampXMin, settings.ClampXMax);
|
||||
float targetX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
|
||||
|
||||
// Calculate tap direction (+1 for right, -1 for left)
|
||||
tapDirection = Mathf.Sign(targetX - transform.position.x);
|
||||
_tapDirection = Mathf.Sign(targetX - transform.position.x);
|
||||
|
||||
// Set impulse strength to full
|
||||
tapImpulseStrength = 1.0f;
|
||||
_tapImpulseStrength = 1.0f;
|
||||
|
||||
// Store target X for animation purposes
|
||||
targetFingerX = targetX;
|
||||
_targetFingerX = targetX;
|
||||
|
||||
// Do not set _isTouchActive for taps anymore
|
||||
// _isTouchActive = true; - Removed to prevent continuous movement
|
||||
@@ -154,11 +154,11 @@ namespace Minigames.DivingForPictures.Player
|
||||
public void OnHoldStart(Vector2 worldPosition)
|
||||
{
|
||||
// Ignore input when paused
|
||||
if (isPaused) return;
|
||||
if (GameManager.Instance.IsPaused) return;
|
||||
|
||||
// Logging.Debug($"[EndlessDescenderController] OnHoldStart at {worldPosition}");
|
||||
targetFingerX = Mathf.Clamp(worldPosition.x, settings.ClampXMin, settings.ClampXMax);
|
||||
isTouchActive = true;
|
||||
_targetFingerX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
|
||||
_isTouchActive = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -167,10 +167,10 @@ namespace Minigames.DivingForPictures.Player
|
||||
public void OnHoldMove(Vector2 worldPosition)
|
||||
{
|
||||
// Ignore input when paused
|
||||
if (isPaused) return;
|
||||
if (GameManager.Instance.IsPaused) return;
|
||||
|
||||
// Logging.Debug($"[EndlessDescenderController] OnHoldMove at {worldPosition}");
|
||||
targetFingerX = Mathf.Clamp(worldPosition.x, settings.ClampXMin, settings.ClampXMax);
|
||||
_targetFingerX = Mathf.Clamp(worldPosition.x, _settings.ClampXMin, _settings.ClampXMax);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -179,25 +179,25 @@ namespace Minigames.DivingForPictures.Player
|
||||
public void OnHoldEnd(Vector2 worldPosition)
|
||||
{
|
||||
// Ignore input when paused
|
||||
if (isPaused) return;
|
||||
if (GameManager.Instance.IsPaused) return;
|
||||
|
||||
// Logging.Debug($"[EndlessDescenderController] OnHoldEnd at {worldPosition}");
|
||||
isTouchActive = false;
|
||||
_isTouchActive = false;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Skip movement processing if paused
|
||||
if (isPaused) return;
|
||||
if (GameManager.Instance.IsPaused) return;
|
||||
|
||||
// Handle hold movement
|
||||
if (isTouchActive)
|
||||
if (_isTouchActive)
|
||||
{
|
||||
float currentX = transform.position.x;
|
||||
float lerpSpeed = settings.LerpSpeed;
|
||||
float maxOffset = settings.MaxOffset;
|
||||
float exponent = settings.SpeedExponent;
|
||||
float targetX = targetFingerX;
|
||||
float lerpSpeed = _settings.LerpSpeed;
|
||||
float maxOffset = _settings.MaxOffset;
|
||||
float exponent = _settings.SpeedExponent;
|
||||
float targetX = _targetFingerX;
|
||||
float offset = targetX - currentX;
|
||||
offset = Mathf.Clamp(offset, -maxOffset, maxOffset);
|
||||
float absOffset = Mathf.Abs(offset);
|
||||
@@ -206,32 +206,32 @@ namespace Minigames.DivingForPictures.Player
|
||||
// Prevent overshooting
|
||||
moveStep = Mathf.Clamp(moveStep, -absOffset, absOffset);
|
||||
float newX = currentX + moveStep;
|
||||
newX = Mathf.Clamp(newX, settings.ClampXMin, settings.ClampXMax);
|
||||
newX = Mathf.Clamp(newX, _settings.ClampXMin, _settings.ClampXMax);
|
||||
|
||||
UpdatePosition(newX);
|
||||
}
|
||||
// Handle tap impulse movement
|
||||
else if (tapImpulseStrength > 0)
|
||||
else if (_tapImpulseStrength > 0)
|
||||
{
|
||||
float currentX = transform.position.x;
|
||||
float maxOffset = settings.MaxOffset;
|
||||
float lerpSpeed = settings.LerpSpeed;
|
||||
float maxOffset = _settings.MaxOffset;
|
||||
float lerpSpeed = _settings.LerpSpeed;
|
||||
|
||||
// Calculate move distance based on impulse strength
|
||||
float moveDistance = maxOffset * tapImpulseStrength * Time.deltaTime * lerpSpeed;
|
||||
float moveDistance = maxOffset * _tapImpulseStrength * Time.deltaTime * lerpSpeed;
|
||||
|
||||
// Limit total movement from single tap
|
||||
moveDistance = Mathf.Min(moveDistance, settings.TapMaxDistance * tapImpulseStrength);
|
||||
moveDistance = Mathf.Min(moveDistance, _settings.TapMaxDistance * _tapImpulseStrength);
|
||||
|
||||
// Apply movement in tap direction
|
||||
float newX = currentX + (moveDistance * tapDirection);
|
||||
newX = Mathf.Clamp(newX, settings.ClampXMin, settings.ClampXMax);
|
||||
float newX = currentX + (moveDistance * _tapDirection);
|
||||
newX = Mathf.Clamp(newX, _settings.ClampXMin, _settings.ClampXMax);
|
||||
|
||||
// Reduce impulse strength over time
|
||||
tapImpulseStrength -= Time.deltaTime * settings.TapDecelerationRate;
|
||||
if (tapImpulseStrength < 0.01f)
|
||||
_tapImpulseStrength -= Time.deltaTime * _settings.TapDecelerationRate;
|
||||
if (_tapImpulseStrength < 0.01f)
|
||||
{
|
||||
tapImpulseStrength = 0f;
|
||||
_tapImpulseStrength = 0f;
|
||||
}
|
||||
|
||||
UpdatePosition(newX);
|
||||
@@ -243,7 +243,7 @@ namespace Minigames.DivingForPictures.Player
|
||||
/// </summary>
|
||||
private void UpdatePosition(float newX)
|
||||
{
|
||||
float newY = originY;
|
||||
float newY = _originY;
|
||||
// Add vertical offset from WobbleBehavior if present
|
||||
WobbleBehavior wobble = GetComponent<WobbleBehavior>();
|
||||
if (wobble != null)
|
||||
@@ -258,7 +258,7 @@ namespace Minigames.DivingForPictures.Player
|
||||
/// </summary>
|
||||
public void UpdateOriginY(float newOriginY)
|
||||
{
|
||||
originY = newOriginY;
|
||||
_originY = newOriginY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -267,7 +267,7 @@ namespace Minigames.DivingForPictures.Player
|
||||
/// </summary>
|
||||
private void UpdateOriginYFromCurrentPosition()
|
||||
{
|
||||
originY = transform.position.y;
|
||||
_originY = transform.position.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -276,24 +276,19 @@ namespace Minigames.DivingForPictures.Player
|
||||
/// </summary>
|
||||
private void UpdateOriginYFromAnchor()
|
||||
{
|
||||
originY = edgeAnchor.transform.position.y;
|
||||
_originY = edgeAnchor.transform.position.y;
|
||||
}
|
||||
|
||||
#region IPausable Implementation
|
||||
private bool isPaused = false;
|
||||
|
||||
/// <summary>
|
||||
/// Pauses the player controller, blocking all input processing
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if (isPaused) return;
|
||||
|
||||
isPaused = true;
|
||||
|
||||
// If we're being paused, stop any active touch and tap impulse
|
||||
isTouchActive = false;
|
||||
tapImpulseStrength = 0f;
|
||||
_isTouchActive = false;
|
||||
_tapImpulseStrength = 0f;
|
||||
|
||||
Logging.Debug("[PlayerController] Paused");
|
||||
}
|
||||
@@ -303,16 +298,8 @@ namespace Minigames.DivingForPictures.Player
|
||||
/// </summary>
|
||||
public void DoResume()
|
||||
{
|
||||
if (!isPaused) return;
|
||||
|
||||
isPaused = false;
|
||||
Logging.Debug("[PlayerController] Resumed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the player controller is currently paused
|
||||
/// </summary>
|
||||
public bool IsPaused => isPaused;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using UnityEngine;
|
||||
using AppleHills.Core.Settings;
|
||||
using Core;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a wobble (rocking and vertical movement) effect to the object, based on speed and time.
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Serialization;
|
||||
using Pooling;
|
||||
using AppleHills.Core.Settings;
|
||||
using Utils;
|
||||
using AppleHills.Core.Interfaces;
|
||||
@@ -113,12 +111,6 @@ namespace Minigames.DivingForPictures
|
||||
}
|
||||
}
|
||||
|
||||
// Pause state
|
||||
private bool _isPaused = false;
|
||||
|
||||
// IPausable implementation
|
||||
public bool IsPaused => _isPaused;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_mainCamera = UnityEngine.Camera.main;
|
||||
@@ -193,10 +185,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if (_isPaused) return; // Already paused
|
||||
|
||||
_isPaused = true;
|
||||
|
||||
// Stop all active coroutines but save their references
|
||||
if (_movementCoroutine != null)
|
||||
{
|
||||
@@ -230,10 +218,6 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
public void DoResume()
|
||||
{
|
||||
if (!_isPaused) return; // Already running
|
||||
|
||||
_isPaused = false;
|
||||
|
||||
// Restart all necessary coroutines
|
||||
StartMovementCoroutine();
|
||||
StartTileDestructionCoroutine();
|
||||
@@ -500,7 +484,7 @@ namespace Minigames.DivingForPictures
|
||||
/// </summary>
|
||||
private void StartMovementCoroutine()
|
||||
{
|
||||
if (_movementCoroutine == null && !_isPaused)
|
||||
if (_movementCoroutine == null && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
_movementCoroutine = StartCoroutine(MoveActiveTilesRoutine());
|
||||
}
|
||||
@@ -513,7 +497,7 @@ namespace Minigames.DivingForPictures
|
||||
{
|
||||
Logging.Debug($"[TrenchTileSpawner] Started movement coroutine with normalized speed: {_baseMoveSpeed:F3}");
|
||||
|
||||
while (enabled && gameObject.activeInHierarchy && !_isPaused)
|
||||
while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
// Skip if no active tiles
|
||||
if (_activeTiles.Count == 0)
|
||||
@@ -554,7 +538,7 @@ namespace Minigames.DivingForPictures
|
||||
const float checkInterval = 1.0f; // Check once per second
|
||||
Logging.Debug($"[TrenchTileSpawner] Started speed ramping coroutine with interval: {checkInterval}s");
|
||||
|
||||
while (enabled && gameObject.activeInHierarchy && !_isPaused)
|
||||
while (enabled && gameObject.activeInHierarchy && !GameManager.Instance.IsPaused)
|
||||
{
|
||||
// Increase the base move speed up to the maximum
|
||||
_baseMoveSpeed = Mathf.Min(_baseMoveSpeed + _settings.SpeedUpFactor, _settings.MaxNormalizedMoveSpeed);
|
||||
|
||||
@@ -7,8 +7,6 @@ namespace Minigames.DivingForPictures.Utilities
|
||||
{
|
||||
[SerializeField] private WobbleBehavior wobbleReference;
|
||||
|
||||
private bool isPaused = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
DivingGameManager.Instance.RegisterPausableComponent(this);
|
||||
@@ -17,15 +15,11 @@ namespace Minigames.DivingForPictures.Utilities
|
||||
public void Pause()
|
||||
{
|
||||
wobbleReference.enabled = false;
|
||||
isPaused = true;
|
||||
}
|
||||
|
||||
public void DoResume()
|
||||
{
|
||||
wobbleReference.enabled = true;
|
||||
isPaused = false;
|
||||
}
|
||||
|
||||
public bool IsPaused => isPaused;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ namespace Minigames.DivingForPictures.Utilities
|
||||
[SerializeField] private RockFollower rockReference;
|
||||
[SerializeField] private WobbleBehavior rockWobbleReference;
|
||||
|
||||
private bool isPaused = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
DivingGameManager.Instance.RegisterPausableComponent(this);
|
||||
@@ -19,16 +17,12 @@ namespace Minigames.DivingForPictures.Utilities
|
||||
{
|
||||
rockReference.enabled = false;
|
||||
rockWobbleReference.enabled = false;
|
||||
isPaused = true;
|
||||
}
|
||||
|
||||
public void DoResume()
|
||||
{
|
||||
rockReference.enabled = true;
|
||||
rockWobbleReference.enabled = true;
|
||||
isPaused = false;
|
||||
}
|
||||
|
||||
public bool IsPaused => isPaused;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user