mirror of
https://github.com/Earth-Genesis-Games/Ajedrez_Purgatorio.git
synced 2026-09-11 09:47:35 +00:00
feat: IA por dificultad, eventos captura/jaque y consolidar SceneTransitionManager
This commit is contained in:
@@ -484,9 +484,9 @@ public class ProjectSetup
|
||||
}
|
||||
|
||||
// SceneTransitionManager
|
||||
if (Object.FindFirstObjectByType<AjedrezPurgatorio.UI.SceneTransitionManager>() == null)
|
||||
if (Object.FindFirstObjectByType<SceneTransitionManager>() == null)
|
||||
{
|
||||
new GameObject("SceneTransitionManager").AddComponent<AjedrezPurgatorio.UI.SceneTransitionManager>();
|
||||
new GameObject("SceneTransitionManager").AddComponent<SceneTransitionManager>();
|
||||
Debug.Log(" ✅ SceneTransitionManager.");
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ public class ProjectSetup
|
||||
if (cs != null) Ref(so, "_campaignState", cs);
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
|
||||
new GameObject("SceneTransitionManager").AddComponent<AjedrezPurgatorio.UI.SceneTransitionManager>();
|
||||
new GameObject("SceneTransitionManager").AddComponent<SceneTransitionManager>();
|
||||
new GameObject("SaveSystem").AddComponent<AjedrezPurgatorio.Meta.SaveSystem>();
|
||||
new GameObject("AudioManager").AddComponent<AjedrezPurgatorio.Audio.AudioManager>();
|
||||
Debug.Log(" ✅ Managers MainMenu creados.");
|
||||
|
||||
@@ -20,33 +20,50 @@ public class AIController : MonoBehaviour
|
||||
|
||||
private IAIStrategy _currentStrategy;
|
||||
private bool _waitingForMove = false;
|
||||
private bool _subscribedToTurnEvents = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
InitializeStrategy();
|
||||
// Solo inicializar con la dificultad por defecto si nadie la configuró antes
|
||||
// (CampaignManager puede aplicar la dificultad del capítulo antes del Start).
|
||||
if (_currentStrategy == null)
|
||||
{
|
||||
InitializeStrategy();
|
||||
}
|
||||
|
||||
// Reintentar suscripción por si OnEnable corrió antes que GameManager.Awake
|
||||
SubscribeToTurnEvents();
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
// Suscribirse al evento de cambio de turno
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.OnTurnChanged += HandleTurnChanged;
|
||||
}
|
||||
SubscribeToTurnEvents();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
// Desuscribirse del evento para evitar memory leaks
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.OnTurnChanged -= HandleTurnChanged;
|
||||
}
|
||||
UnsubscribeFromTurnEvents();
|
||||
|
||||
// Cancelar movimiento pendiente si existe
|
||||
CancelInvoke(nameof(ExecuteAIMove));
|
||||
}
|
||||
|
||||
private void SubscribeToTurnEvents()
|
||||
{
|
||||
if (_subscribedToTurnEvents || GameManager.Instance == null) return;
|
||||
|
||||
GameManager.Instance.OnTurnChanged += HandleTurnChanged;
|
||||
_subscribedToTurnEvents = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeFromTurnEvents()
|
||||
{
|
||||
if (!_subscribedToTurnEvents || GameManager.Instance == null) return;
|
||||
|
||||
GameManager.Instance.OnTurnChanged -= HandleTurnChanged;
|
||||
_subscribedToTurnEvents = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inicializa la estrategia según la dificultad configurada.
|
||||
/// </summary>
|
||||
|
||||
@@ -648,10 +648,29 @@ public class CampaignManager : MonoBehaviour
|
||||
|
||||
Debug.Log($"[CampaignManager] Configurando IA: {aiConfig.difficulty} - {aiConfig.strategy}");
|
||||
|
||||
// TODO (S4-005): Configurar AIController con la dificultad del capítulo
|
||||
// AIController necesita API pública para SetDifficulty() y SetStrategy()
|
||||
// FindObjectOfType<AIController>()?.SetDifficulty(aiConfig.difficulty);
|
||||
Debug.Log("[CampaignManager] TODO: Aplicar configuración a AIController");
|
||||
AIController aiController = FindObjectOfType<AIController>();
|
||||
if (aiController != null)
|
||||
{
|
||||
aiController.SetDifficulty(ParseAIDifficulty(aiConfig.difficulty));
|
||||
aiController.SetEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[CampaignManager] AIController no encontrado en la escena. No se pudo aplicar la dificultad del capítulo.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convierte la dificultad en string del AIConfig al enum AIDifficulty.
|
||||
/// </summary>
|
||||
private static AIDifficulty ParseAIDifficulty(string difficulty)
|
||||
{
|
||||
return difficulty?.ToLowerInvariant() switch
|
||||
{
|
||||
"medium" => AIDifficulty.Medium,
|
||||
"hard" => AIDifficulty.Hard,
|
||||
_ => AIDifficulty.Easy
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -68,6 +68,16 @@ public class GameManager : MonoBehaviour
|
||||
/// Se dispara después de que una pieza se mueve. Parámetros: pieza, posición anterior, posición nueva.
|
||||
/// </summary>
|
||||
public event Action<Piece, Vector2Int, Vector2Int> OnPieceMoved;
|
||||
|
||||
/// <summary>
|
||||
/// Se dispara cuando una pieza es capturada. Parámetro: la pieza capturada.
|
||||
/// </summary>
|
||||
public event Action<Piece> OnPieceCaptured;
|
||||
|
||||
/// <summary>
|
||||
/// Se dispara cuando un rey que estaba en jaque sale del jaque tras un movimiento.
|
||||
/// </summary>
|
||||
public event Action OnCheckResolved;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
@@ -163,6 +173,7 @@ public class GameManager : MonoBehaviour
|
||||
}
|
||||
|
||||
Vector2Int oldPos = piece.currentPos;
|
||||
bool wasInCheckBeforeMove = _checkDetector.IsInCheck(_board, _whiteTurn);
|
||||
|
||||
// Tracking para en passant
|
||||
_lastMovedPiece = piece;
|
||||
@@ -202,6 +213,8 @@ public class GameManager : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
OnPieceCaptured?.Invoke(captured);
|
||||
|
||||
Destroy(captured.gameObject);
|
||||
}
|
||||
|
||||
@@ -214,6 +227,11 @@ public class GameManager : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
if (isEnPassant && enPassantCaptured != null)
|
||||
{
|
||||
OnPieceCaptured?.Invoke(enPassantCaptured);
|
||||
}
|
||||
|
||||
// Mover pieza
|
||||
_board[oldPos.x, oldPos.y] = null;
|
||||
_board[newPos.x, newPos.y] = piece;
|
||||
@@ -266,6 +284,12 @@ public class GameManager : MonoBehaviour
|
||||
OnCheck?.Invoke(isNextPlayerWhite);
|
||||
}
|
||||
|
||||
// Resolución de jaque: si la pieza que estaba en jaque ya no lo está tras moverse
|
||||
if (wasInCheckBeforeMove && !_checkDetector.IsInCheck(_board, _whiteTurn))
|
||||
{
|
||||
OnCheckResolved?.Invoke();
|
||||
}
|
||||
|
||||
// Disparar evento de movimiento completado
|
||||
OnPieceMoved?.Invoke(piece, oldPos, newPos);
|
||||
|
||||
|
||||
@@ -58,11 +58,9 @@ namespace AjedrezPurgatorio.UI
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.OnTurnChanged += OnTurnChanged;
|
||||
// TODO: Add OnPieceCaptured event to GameManager
|
||||
// GameManager.Instance.OnPieceCaptured += OnPieceCaptured;
|
||||
// TODO: Add OnCheck and OnCheckResolved events to GameManager
|
||||
// GameManager.Instance.OnCheck += OnCheck;
|
||||
// GameManager.Instance.OnCheckResolved += OnCheckResolved;
|
||||
GameManager.Instance.OnPieceCaptured += OnPieceCaptured;
|
||||
GameManager.Instance.OnCheck += OnCheck;
|
||||
GameManager.Instance.OnCheckResolved += OnCheckResolved;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,11 +70,9 @@ namespace AjedrezPurgatorio.UI
|
||||
if (GameManager.Instance != null)
|
||||
{
|
||||
GameManager.Instance.OnTurnChanged -= OnTurnChanged;
|
||||
// TODO: Unsubscribe from OnPieceCaptured
|
||||
// GameManager.Instance.OnPieceCaptured -= OnPieceCaptured;
|
||||
// TODO: Unsubscribe from OnCheck and OnCheckResolved
|
||||
// GameManager.Instance.OnCheck -= OnCheck;
|
||||
// GameManager.Instance.OnCheckResolved -= OnCheckResolved;
|
||||
GameManager.Instance.OnPieceCaptured -= OnPieceCaptured;
|
||||
GameManager.Instance.OnCheck -= OnCheck;
|
||||
GameManager.Instance.OnCheckResolved -= OnCheckResolved;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections;
|
||||
|
||||
namespace AjedrezPurgatorio.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages scene transitions with fade effects.
|
||||
/// Singleton pattern for easy access from anywhere.
|
||||
/// </summary>
|
||||
public class SceneTransitionManager : MonoBehaviour
|
||||
{
|
||||
#region Singleton
|
||||
|
||||
private static SceneTransitionManager _instance;
|
||||
|
||||
public static SceneTransitionManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject go = new GameObject("SceneTransitionManager");
|
||||
_instance = go.AddComponent<SceneTransitionManager>();
|
||||
DontDestroyOnLoad(go);
|
||||
_instance.Initialize();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Configuration
|
||||
|
||||
[Header("Fade Settings")]
|
||||
[SerializeField] private float _fadeOutDuration = 0.5f;
|
||||
[SerializeField] private float _fadeInDuration = 0.5f;
|
||||
[SerializeField] private Color _fadeColor = Color.black;
|
||||
|
||||
[Header("Debug")]
|
||||
[SerializeField] private bool _enableDebugLogging = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private Canvas _canvas;
|
||||
private Image _fadeImage;
|
||||
private bool _isTransitioning = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity Lifecycle
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_instance != null && _instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
_instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the fade canvas and image.
|
||||
/// </summary>
|
||||
private void Initialize()
|
||||
{
|
||||
if (_canvas != null)
|
||||
return; // Already initialized
|
||||
|
||||
// Create canvas
|
||||
GameObject canvasGO = new GameObject("FadeCanvas");
|
||||
canvasGO.transform.SetParent(transform);
|
||||
|
||||
_canvas = canvasGO.AddComponent<Canvas>();
|
||||
_canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
_canvas.sortingOrder = 9999; // Top-most layer
|
||||
|
||||
CanvasScaler scaler = canvasGO.AddComponent<CanvasScaler>();
|
||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1920, 1080);
|
||||
|
||||
canvasGO.AddComponent<GraphicRaycaster>();
|
||||
|
||||
// Create fade image
|
||||
GameObject imageGO = new GameObject("FadeImage");
|
||||
imageGO.transform.SetParent(canvasGO.transform, false);
|
||||
|
||||
_fadeImage = imageGO.AddComponent<Image>();
|
||||
_fadeImage.color = new Color(_fadeColor.r, _fadeColor.g, _fadeColor.b, 0f);
|
||||
|
||||
RectTransform rt = imageGO.GetComponent<RectTransform>();
|
||||
rt.anchorMin = Vector2.zero;
|
||||
rt.anchorMax = Vector2.one;
|
||||
rt.sizeDelta = Vector2.zero;
|
||||
|
||||
if (_enableDebugLogging)
|
||||
Debug.Log("[SceneTransitionManager] Initialized.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public API
|
||||
|
||||
/// <summary>
|
||||
/// Transitions to a new scene with fade effect.
|
||||
/// </summary>
|
||||
/// <param name="sceneName">Name of the scene to load</param>
|
||||
public void TransitionToScene(string sceneName)
|
||||
{
|
||||
if (_isTransitioning)
|
||||
{
|
||||
Debug.LogWarning("[SceneTransitionManager] Transition already in progress.");
|
||||
return;
|
||||
}
|
||||
|
||||
StartCoroutine(TransitionCoroutine(sceneName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fades out the screen.
|
||||
/// </summary>
|
||||
public void FadeOut(System.Action onComplete = null)
|
||||
{
|
||||
StartCoroutine(FadeCoroutine(0f, 1f, _fadeOutDuration, onComplete));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fades in the screen.
|
||||
/// </summary>
|
||||
public void FadeIn(System.Action onComplete = null)
|
||||
{
|
||||
StartCoroutine(FadeCoroutine(1f, 0f, _fadeInDuration, onComplete));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Coroutines
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine for scene transition with fade.
|
||||
/// </summary>
|
||||
private IEnumerator TransitionCoroutine(string sceneName)
|
||||
{
|
||||
_isTransitioning = true;
|
||||
|
||||
if (_enableDebugLogging)
|
||||
Debug.Log($"[SceneTransitionManager] Starting transition to scene: {sceneName}");
|
||||
|
||||
// Fade out
|
||||
yield return FadeCoroutine(0f, 1f, _fadeOutDuration, null);
|
||||
|
||||
// Load scene
|
||||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
|
||||
|
||||
while (!asyncLoad.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Fade in
|
||||
yield return FadeCoroutine(1f, 0f, _fadeInDuration, null);
|
||||
|
||||
_isTransitioning = false;
|
||||
|
||||
if (_enableDebugLogging)
|
||||
Debug.Log($"[SceneTransitionManager] Transition to {sceneName} complete.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coroutine for fade effect.
|
||||
/// </summary>
|
||||
private IEnumerator FadeCoroutine(float startAlpha, float endAlpha, float duration, System.Action onComplete)
|
||||
{
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
float alpha = Mathf.Lerp(startAlpha, endAlpha, t);
|
||||
|
||||
_fadeImage.color = new Color(_fadeColor.r, _fadeColor.g, _fadeColor.b, alpha);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Ensure final alpha
|
||||
_fadeImage.color = new Color(_fadeColor.r, _fadeColor.g, _fadeColor.b, endAlpha);
|
||||
|
||||
onComplete?.Invoke();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42a7f6937327de9469fc73fc1f0cae64
|
||||
@@ -1726,13 +1726,60 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 365129009}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 42a7f6937327de9469fc73fc1f0cae64, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: e1e89932918bf4f45b1b8b65506d6dd9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::AjedrezPurgatorio.UI.SceneTransitionManager
|
||||
_fadeOutDuration: 0.5
|
||||
_fadeInDuration: 0.5
|
||||
_fadeColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
_enableDebugLogging: 0
|
||||
m_EditorClassIdentifier: Assembly-CSharp::SceneTransitionManager
|
||||
_fadeCanvasGroup: {fileID: 0}
|
||||
_fadeImage: {fileID: 0}
|
||||
_fadeDuration: 0.8
|
||||
_fadeOutCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
_fadeInCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
--- !u!4 &365129011
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -8995,6 +9042,55 @@ Canvas:
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 120
|
||||
m_TargetDisplay: 0
|
||||
--- !u!1 &1910000001
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1910000002}
|
||||
- component: {fileID: 1910000003}
|
||||
m_Layer: 0
|
||||
m_Name: AIController
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1910000003
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1910000001}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 55be8b8bddc882c4c8c14fe8572460c9, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::AIController
|
||||
_difficulty: 0
|
||||
_thinkDelayMin: 0.3
|
||||
_thinkDelayMax: 0.8
|
||||
_enableAI: 1
|
||||
_positionTables: {fileID: 0}
|
||||
--- !u!4 &1910000002
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1910000001}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -9019,3 +9115,4 @@ SceneRoots:
|
||||
- {fileID: 1105990741}
|
||||
- {fileID: 180650685}
|
||||
- {fileID: 1129911953}
|
||||
- {fileID: 1910000002}
|
||||
|
||||
Reference in New Issue
Block a user