Generic MVP working
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
using Core;
|
||||
using Core.Lifecycle;
|
||||
using Common.Camera;
|
||||
using Core;
|
||||
using Minigames.FortFight.Data;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
@@ -8,11 +8,10 @@ namespace Minigames.FortFight.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages camera states and transitions for the Fort Fight minigame.
|
||||
/// Extends CameraStateManager to use the common state-based camera system.
|
||||
/// Subscribes to turn events and switches camera views accordingly.
|
||||
/// Uses Cinemachine for smooth camera blending.
|
||||
/// Singleton pattern for easy access.
|
||||
/// </summary>
|
||||
public class CameraController : ManagedBehaviour
|
||||
public class CameraController : CameraStateManager<FortFightCameraState>
|
||||
{
|
||||
#region Singleton
|
||||
|
||||
@@ -31,41 +30,15 @@ namespace Minigames.FortFight.Core
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inspector References
|
||||
|
||||
[Header("Cinemachine Cameras")]
|
||||
[Tooltip("Virtual camera showing wide battlefield view (both forts)")]
|
||||
[SerializeField] private CinemachineCamera wideViewCamera;
|
||||
|
||||
[Tooltip("Player One's dedicated camera (position this in the scene for Player 1's view)")]
|
||||
[SerializeField] private CinemachineCamera playerOneCamera;
|
||||
|
||||
[Tooltip("Player Two's dedicated camera (position this in the scene for Player 2's view)")]
|
||||
[SerializeField] private CinemachineCamera playerTwoCamera;
|
||||
|
||||
[Tooltip("Camera that follows projectiles in flight (should have CinemachineFollow component)")]
|
||||
[SerializeField] private CinemachineCamera projectileCamera;
|
||||
|
||||
// Note: TurnManager accessed via singleton
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public CinemachineCamera WideViewCamera => wideViewCamera;
|
||||
public CinemachineCamera PlayerOneCamera => playerOneCamera;
|
||||
public CinemachineCamera PlayerTwoCamera => playerTwoCamera;
|
||||
public CinemachineCamera ProjectileCamera => projectileCamera;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
internal override void OnManagedAwake()
|
||||
{
|
||||
// Base class handles InitializeCameraMap() and ValidateCameras()
|
||||
base.OnManagedAwake();
|
||||
|
||||
// Register singleton
|
||||
// Set singleton
|
||||
if (_instance != null && _instance != this)
|
||||
{
|
||||
Logging.Warning("[CameraController] Multiple instances detected! Destroying duplicate.");
|
||||
@@ -73,28 +46,6 @@ namespace Minigames.FortFight.Core
|
||||
return;
|
||||
}
|
||||
_instance = this;
|
||||
|
||||
// Validate references
|
||||
if (wideViewCamera == null)
|
||||
{
|
||||
Logging.Error("[CameraController] Wide view camera not assigned!");
|
||||
}
|
||||
|
||||
if (playerOneCamera == null)
|
||||
{
|
||||
Logging.Error("[CameraController] Player One camera not assigned!");
|
||||
}
|
||||
|
||||
if (playerTwoCamera == null)
|
||||
{
|
||||
Logging.Error("[CameraController] Player Two camera not assigned!");
|
||||
}
|
||||
|
||||
if (projectileCamera == null)
|
||||
{
|
||||
Logging.Warning("[CameraController] Projectile camera not assigned - projectiles won't be followed!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal override void OnManagedStart()
|
||||
@@ -136,75 +87,55 @@ namespace Minigames.FortFight.Core
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Called when a player's turn starts - activate their dedicated camera
|
||||
/// Called when a player's turn starts - switch to appropriate camera state
|
||||
/// </summary>
|
||||
private void HandleTurnStarted(PlayerData player, TurnState turnState)
|
||||
{
|
||||
Logging.Debug($"[CameraController] Turn started for {player.PlayerName} (Index: {player.PlayerIndex}, State: {turnState})");
|
||||
if (showDebugLogs)
|
||||
Logging.Debug($"[CameraController] Turn started for {player.PlayerName} (Index: {player.PlayerIndex}, State: {turnState})");
|
||||
|
||||
// If transitioning, show wide view
|
||||
if (turnState == TurnState.TransitioningTurn)
|
||||
{
|
||||
ActivateCamera(wideViewCamera);
|
||||
SwitchToState(FortFightCameraState.WideView);
|
||||
return;
|
||||
}
|
||||
|
||||
// Activate the appropriate player camera based on player index
|
||||
// Switch to appropriate player camera based on index
|
||||
if (player.PlayerIndex == 0)
|
||||
{
|
||||
// Player One's turn
|
||||
ActivateCamera(playerOneCamera);
|
||||
SwitchToState(FortFightCameraState.PlayerOne);
|
||||
}
|
||||
else if (player.PlayerIndex == 1)
|
||||
{
|
||||
// Player Two's turn
|
||||
ActivateCamera(playerTwoCamera);
|
||||
SwitchToState(FortFightCameraState.PlayerTwo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[CameraController] Unknown player index: {player.PlayerIndex}, defaulting to wide view");
|
||||
ActivateCamera(wideViewCamera);
|
||||
SwitchToState(FortFightCameraState.WideView);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a player's turn ends - camera switches handled by turn state changes
|
||||
/// Called when a player's turn ends
|
||||
/// </summary>
|
||||
private void HandleTurnEnded(PlayerData player)
|
||||
{
|
||||
Logging.Debug($"[CameraController] Turn ended for {player.PlayerName}");
|
||||
if (showDebugLogs) Logging.Debug($"[CameraController] Turn ended for {player.PlayerName}");
|
||||
// Camera switching happens via OnTurnStarted when state changes to TransitioningTurn
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activate a specific camera by setting its priority highest
|
||||
/// </summary>
|
||||
private void ActivateCamera(CinemachineCamera camera)
|
||||
{
|
||||
if (camera == null) return;
|
||||
|
||||
// Set all cameras to low priority
|
||||
if (wideViewCamera != null) wideViewCamera.Priority.Value = 10;
|
||||
if (playerOneCamera != null) playerOneCamera.Priority.Value = 10;
|
||||
if (playerTwoCamera != null) playerTwoCamera.Priority.Value = 10;
|
||||
if (projectileCamera != null) projectileCamera.Priority.Value = 10;
|
||||
|
||||
// Set target camera to high priority
|
||||
camera.Priority.Value = 20;
|
||||
|
||||
Logging.Debug($"[CameraController] Activated camera: {camera.gameObject.name}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Projectile Tracking
|
||||
|
||||
/// <summary>
|
||||
/// Start following a projectile with the projectile camera.
|
||||
/// Called when a projectile is launched.
|
||||
/// Start following a projectile with the projectile camera
|
||||
/// </summary>
|
||||
public void StartFollowingProjectile(Transform projectileTransform)
|
||||
{
|
||||
var projectileCamera = GetCamera(FortFightCameraState.Projectile);
|
||||
if (projectileCamera == null)
|
||||
{
|
||||
Logging.Warning("[CameraController] Cannot follow projectile - projectile camera not assigned!");
|
||||
@@ -217,38 +148,32 @@ namespace Minigames.FortFight.Core
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify CinemachineFollow component exists (optional check)
|
||||
var followComponent = projectileCamera.GetComponent<CinemachineFollow>();
|
||||
if (followComponent == null)
|
||||
{
|
||||
Logging.Error("[CameraController] Projectile camera missing CinemachineFollow component!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the follow target on the CinemachineCamera's Target property
|
||||
// Set the follow target
|
||||
projectileCamera.Target.TrackingTarget = projectileTransform;
|
||||
|
||||
// Activate the projectile camera
|
||||
ActivateCamera(projectileCamera);
|
||||
// Switch to projectile camera
|
||||
SwitchToState(FortFightCameraState.Projectile);
|
||||
|
||||
Logging.Debug($"[CameraController] Now following projectile: {projectileTransform.gameObject.name}");
|
||||
if (showDebugLogs)
|
||||
Logging.Debug($"[CameraController] Now following projectile: {projectileTransform.gameObject.name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop following the projectile and return to wide view.
|
||||
/// Called when projectile has settled.
|
||||
/// Stop following the projectile and return to wide view
|
||||
/// </summary>
|
||||
public void StopFollowingProjectile()
|
||||
{
|
||||
var projectileCamera = GetCamera(FortFightCameraState.Projectile);
|
||||
if (projectileCamera == null) return;
|
||||
|
||||
// Clear the follow target on the CinemachineCamera's Target property
|
||||
// Clear the follow target
|
||||
projectileCamera.Target.TrackingTarget = null;
|
||||
|
||||
// Return to wide view
|
||||
ActivateCamera(wideViewCamera);
|
||||
SwitchToState(FortFightCameraState.WideView);
|
||||
|
||||
Logging.Debug("[CameraController] Stopped following projectile, returned to wide view");
|
||||
if (showDebugLogs)
|
||||
Logging.Debug("[CameraController] Stopped following projectile, returned to wide view");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -256,11 +181,11 @@ namespace Minigames.FortFight.Core
|
||||
#region Public API
|
||||
|
||||
/// <summary>
|
||||
/// Manually switch to wide view (useful for game start/end)
|
||||
/// Manually switch to wide view
|
||||
/// </summary>
|
||||
public void ShowWideView()
|
||||
{
|
||||
ActivateCamera(wideViewCamera);
|
||||
SwitchToState(FortFightCameraState.WideView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -270,24 +195,36 @@ namespace Minigames.FortFight.Core
|
||||
{
|
||||
if (playerIndex == 0)
|
||||
{
|
||||
ActivateCamera(playerOneCamera);
|
||||
SwitchToState(FortFightCameraState.PlayerOne);
|
||||
}
|
||||
else if (playerIndex == 1)
|
||||
{
|
||||
ActivateCamera(playerTwoCamera);
|
||||
SwitchToState(FortFightCameraState.PlayerTwo);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Editor Helpers
|
||||
#region Validation
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
protected override void ValidateCameras()
|
||||
{
|
||||
// Base class validates all enum states have cameras assigned
|
||||
base.ValidateCameras();
|
||||
|
||||
// Additional validation: Check if projectile camera has follow component
|
||||
var projectileCamera = GetCamera(FortFightCameraState.Projectile);
|
||||
if (projectileCamera != null)
|
||||
{
|
||||
var followComponent = projectileCamera.GetComponent<CinemachineFollow>();
|
||||
if (followComponent == null)
|
||||
{
|
||||
Logging.Warning("[CameraController] Projectile camera missing CinemachineFollow component!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,17 @@ namespace Minigames.FortFight.Core
|
||||
|
||||
#region Override Methods
|
||||
|
||||
public override void Enable()
|
||||
{
|
||||
// Clear any locked trajectory from previous turn
|
||||
if (trajectoryPreview != null)
|
||||
{
|
||||
trajectoryPreview.ForceHide();
|
||||
}
|
||||
|
||||
base.Enable();
|
||||
}
|
||||
|
||||
protected override void StartDrag(Vector2 worldPosition)
|
||||
{
|
||||
// Check ammo before starting drag
|
||||
|
||||
@@ -61,5 +61,15 @@
|
||||
Medium, // Moderate deviations, moderate thinking
|
||||
Hard // Minimal deviations, faster thinking
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Camera states for Fort Fight minigame
|
||||
/// </summary>
|
||||
public enum FortFightCameraState
|
||||
{
|
||||
WideView, // Shows entire battlefield
|
||||
PlayerOne, // Player 1's view
|
||||
PlayerTwo, // Player 2's view
|
||||
Projectile // Follows projectile in flight
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user