Update the photo taking mode to automatic and hone in visual feedback

This commit is contained in:
Michal Pikulski
2025-12-16 21:31:06 +01:00
parent ecb9bf1b2b
commit 4063e66362
15 changed files with 1581 additions and 99 deletions

View File

@@ -1,4 +1,4 @@
using AppleHills.Core.Interfaces;
using AppleHills.Core.Interfaces;
using Cinematics;
using Core;
using Core.Lifecycle;
@@ -44,7 +44,7 @@ namespace Minigames.DivingForPictures
private float _currentSpawnProbability;
private float _lastSpawnTime = -100f;
private float _timeSinceLastSpawn = 0f;
private List<Monster> _activeMonsters = new List<Monster>();
private List<Monster.Monster> _activeMonsters = new List<Monster.Monster>();
// Velocity management
// Velocity state tracking
@@ -59,8 +59,8 @@ namespace Minigames.DivingForPictures
// Events
public event Action<int> OnScoreChanged;
public event Action<Monster> OnMonsterSpawned;
public event Action<Monster, int> OnPictureTaken;
public event Action<Monster.Monster> OnMonsterSpawned;
public event Action<Monster.Monster, int> OnPictureTaken;
public event Action<float> OnSpawnProbabilityChanged;
public event Action OnGameOver;
public event Action<int> OnRopeBroken; // Passes remaining ropes count
@@ -86,15 +86,16 @@ namespace Minigames.DivingForPictures
// Photo sequence state
private bool _isPhotoSequenceActive = false;
private Monster _currentPhotoTarget = null;
private Monster.Monster _currentPhotoTarget = null;
private float _capturedProximity = 0f;
private Coroutine _autoPhotoCoroutine = null; // Coroutine for automatic photo taking
// List of components to exempt from pausing during photo sequence
private List<IPausable> _exemptFromPhotoSequencePausing = new List<IPausable>();
// Photo sequence events
public event Action<Monster> OnPhotoSequenceStarted;
public event Action<Monster, float> OnPhotoSequenceCompleted; // Now includes proximity score
public event Action<Monster.Monster> OnPhotoSequenceStarted;
public event Action<Monster.Monster, float> OnPhotoSequenceCompleted; // Now includes proximity score
private static DivingGameManager _instance = null;
@@ -151,6 +152,7 @@ namespace Minigames.DivingForPictures
viewfinderManager.OnProximityUpdated += OnProximityUpdated;
viewfinderManager.OnViewfinderTappedDuringAnimation += OnViewfinderTappedDuringAnimation;
viewfinderManager.OnReverseAnimationStarted += OnReverseAnimationStarted;
viewfinderManager.OnPerfectPositionReached += OnPerfectPositionReached;
// 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
@@ -183,6 +185,7 @@ namespace Minigames.DivingForPictures
viewfinderManager.OnProximityUpdated -= OnProximityUpdated;
viewfinderManager.OnViewfinderTappedDuringAnimation -= OnViewfinderTappedDuringAnimation;
viewfinderManager.OnReverseAnimationStarted -= OnReverseAnimationStarted;
viewfinderManager.OnPerfectPositionReached -= OnPerfectPositionReached;
}
}
@@ -255,7 +258,7 @@ namespace Minigames.DivingForPictures
// Instantiate monster at spawn point position
GameObject monsterObj = Instantiate(prefab, spawnPoint.position, Quaternion.identity);
Monster monster = monsterObj.GetComponent<Monster>();
Monster.Monster monster = monsterObj.GetComponent<Monster.Monster>();
if (monster != null)
{
@@ -281,7 +284,7 @@ namespace Minigames.DivingForPictures
}
}
private void DoPictureTaken(Monster monster)
private void DoPictureTaken(Monster.Monster monster)
{
// Calculate points based on depth
int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier);
@@ -838,14 +841,57 @@ namespace Minigames.DivingForPictures
component.DoResume();
}
// Change input mode to UI when menu is open
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
// Restore game input mode
InputManager.Instance.SetInputMode(InputMode.Game);
Logging.Debug($"[DivingGameManager] Game resumed. Resumed {_pausableComponents.Count} components.");
}
#region Photo Sequence Methods
/// <summary>
/// Coroutine to automatically take a photo after a configured delay
/// </summary>
private IEnumerator AutomaticPhotoSequence(Monster.Monster monster)
{
// Wait for the configured delay
yield return new WaitForSeconds(_settings.AutoPhotoDelay);
// Check if monster is still valid and player is still in range
if (monster != null && monster.IsPlayerInDetectionRange && !_isPhotoSequenceActive && !monster.IsPictureTaken)
{
// Start photo sequence automatically
_isPhotoSequenceActive = true;
_currentPhotoTarget = monster;
// Pause the game
DoPause(false);
// Mark monster as in photo sequence
monster.SetPhotoSequenceInProgress();
// Reset captured proximity
_capturedProximity = 0f;
// Notify listeners
OnPhotoSequenceStarted?.Invoke(monster);
// Start the viewfinder animation
if (viewfinderManager != null)
{
viewfinderManager.StartViewfinderSequence(monster.transform);
Logging.Debug($"[DivingGameManager] Automatically started photo sequence for monster {monster.name}");
}
else
{
Debug.LogError("[DivingGameManager] No ViewfinderManager available!");
CompletePhotoSequence();
}
}
_autoPhotoCoroutine = null;
}
/// <summary>
/// Called when the viewfinder animation phase changes to reverse (zoom out)
/// </summary>
@@ -854,6 +900,22 @@ namespace Minigames.DivingForPictures
Logging.Debug("[DivingGameManager] Viewfinder animation entering reverse (zoom-out) phase");
}
/// <summary>
/// Called when the viewfinder reaches perfect position (end of zoom-in phase)
/// In automatic mode, this triggers the photo capture
/// </summary>
private void OnPerfectPositionReached()
{
Logging.Debug("[DivingGameManager] Viewfinder reached perfect position");
// In automatic mode, take the photo when perfect position is reached
if (_settings.PhotoTakingMode == PhotoTakingMode.Automatic && _isPhotoSequenceActive)
{
Logging.Debug("[DivingGameManager] Automatic mode - taking photo at perfect position");
TakePicture();
}
}
/// <summary>
/// Called when proximity value is updated during animation
/// </summary>
@@ -888,6 +950,12 @@ namespace Minigames.DivingForPictures
if (!_isPhotoSequenceActive || _currentPhotoTarget == null)
return;
// Stop the viewfinder animation if it's still running
if (viewfinderManager != null)
{
viewfinderManager.StopViewfinderAnimation();
}
// Notify the monster that its picture was taken
_currentPhotoTarget.NotifyPictureTaken();
@@ -914,7 +982,7 @@ namespace Minigames.DivingForPictures
/// <summary>
/// Calculates the score for a picture based on proximity to target and monster depth
/// </summary>
private void CalculateScore(Monster monster, float proximity)
private void CalculateScore(Monster.Monster monster, float proximity)
{
if (monster == null) return;
@@ -1035,7 +1103,7 @@ namespace Minigames.DivingForPictures
#endregion
private void DoMonsterSpawned(Monster monster)
private void DoMonsterSpawned(Monster.Monster monster)
{
if (monster != null)
{
@@ -1049,7 +1117,7 @@ namespace Minigames.DivingForPictures
}
}
private void DoMonsterDespawned(Monster monster)
private void DoMonsterDespawned(Monster.Monster monster)
{
// Remove from active list
_activeMonsters.Remove(monster);
@@ -1064,29 +1132,47 @@ namespace Minigames.DivingForPictures
}
// Handles player entering monster detection range
private void OnPlayerEnterMonsterRange(Monster monster)
private void OnPlayerEnterMonsterRange(Monster.Monster monster)
{
if (monster != null && !_isPhotoSequenceActive)
{
// Store current target for later use
_currentPhotoTarget = monster;
// Show the full-screen viewfinder (first step in two-step process)
if (viewfinderManager != null)
// Check the photo taking mode from settings
if (_settings.PhotoTakingMode == PhotoTakingMode.Automatic)
{
viewfinderManager.ShowFullScreenViewfinder();
Logging.Debug($"[DivingGameManager] Player entered range of monster {monster.name}, showing full-screen viewfinder");
// Automatic mode: Start coroutine to automatically take photo after delay
_autoPhotoCoroutine = StartCoroutine(AutomaticPhotoSequence(monster));
Logging.Debug($"[DivingGameManager] Player entered range of monster {monster.name}, starting automatic photo sequence");
}
else
{
// Input mode: Show the full-screen viewfinder (first step in two-step process)
if (viewfinderManager != null)
{
viewfinderManager.ShowFullScreenViewfinder();
Logging.Debug($"[DivingGameManager] Player entered range of monster {monster.name}, showing full-screen viewfinder");
}
}
}
}
// Handles player exiting monster detection range
private void OnPlayerExitMonsterRange(Monster monster)
private void OnPlayerExitMonsterRange(Monster.Monster monster)
{
// Only hide viewfinder if we're not already in a photo sequence
if (!_isPhotoSequenceActive && monster == _currentPhotoTarget)
{
// Hide the viewfinder
// Cancel automatic photo coroutine if it's running
if (_autoPhotoCoroutine != null)
{
StopCoroutine(_autoPhotoCoroutine);
_autoPhotoCoroutine = null;
Logging.Debug($"[DivingGameManager] Player exited range, cancelled automatic photo sequence");
}
// Hide the viewfinder (only relevant for input mode)
if (viewfinderManager != null)
{
viewfinderManager.HideViewfinder();