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:
2025-10-24 11:09:32 +00:00
parent 35acaddca5
commit 5a85a602bd
26 changed files with 1342 additions and 1023 deletions

View File

@@ -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
}
}