refactor & fix
- 将 `CombatScheduler` 的职责分散到 3 个类中
- `PhaseLoopRuntime`:负责关卡各波次的调度
- `CombatLoadSession`:负责地图与 UI 等资源的加载
- `CombatEventBridge`:负责相关事件的处理
- 统一了战斗的命名为 `Combat`
- 调整了各个地图的坐标,使其位于摄像头中心
- 新增了 CombatInfoForm 展示战斗内的信息
- 补充了循环执行 LevelPhase,手动结束战斗的逻辑
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
using GeometryTD.Definition;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class CombineArea : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private CombineSlotItem[] _slots;
|
||||
|
||||
public void OnInit(CombineAreaContext context)
|
||||
{
|
||||
if (_slots == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _slots.Length; i++)
|
||||
{
|
||||
if (_slots[i] != null)
|
||||
{
|
||||
_slots[i].OnInit(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
if (_slots == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var slot in _slots)
|
||||
{
|
||||
if (slot != null)
|
||||
{
|
||||
slot.OnReset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCombineClick()
|
||||
{
|
||||
// TODO: Combine logic.
|
||||
}
|
||||
|
||||
public bool TryAssignItem(RepoItemContext itemContext)
|
||||
{
|
||||
if (itemContext == null || itemContext.ComponentSlotType == TowerCompSlotType.None)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CombineSlotItem targetSlot = FindSlot(itemContext.ComponentSlotType);
|
||||
if (targetSlot == null || targetSlot.HasItem)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
targetSlot.BindItem(itemContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryClearSlot(int slotIndex, out long removedItemId)
|
||||
{
|
||||
removedItemId = 0;
|
||||
if (_slots == null || slotIndex < 0 || slotIndex >= _slots.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CombineSlotItem slot = _slots[slotIndex];
|
||||
if (slot == null || !slot.HasItem)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
removedItemId = slot.BoundItemId;
|
||||
slot.ClearSlot();
|
||||
return true;
|
||||
}
|
||||
|
||||
private CombineSlotItem FindSlot(TowerCompSlotType slotType)
|
||||
{
|
||||
if (_slots == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _slots.Length; i++)
|
||||
{
|
||||
CombineSlotItem slot = _slots[i];
|
||||
if (slot != null && slot.AcceptSlotType == slotType)
|
||||
{
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce74fc07cb1849b89ad101683cc63546
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,82 @@
|
||||
using GeometryTD.CustomEvent;
|
||||
using GeometryTD.Definition;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class CombineSlotItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TowerCompSlotType _acceptSlotType = TowerCompSlotType.None;
|
||||
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
|
||||
[SerializeField] private CommonButton _button;
|
||||
|
||||
private string _defaultTitle = string.Empty;
|
||||
|
||||
private long _boundItemId;
|
||||
|
||||
private int _slotIndex = -1;
|
||||
|
||||
public TowerCompSlotType AcceptSlotType => _acceptSlotType;
|
||||
|
||||
public bool HasItem => _boundItemId > 0;
|
||||
|
||||
public int SlotIndex => _slotIndex;
|
||||
|
||||
public long BoundItemId => _boundItemId;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_titleText != null)
|
||||
{
|
||||
_defaultTitle = _titleText.text;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnInit(int slotIndex)
|
||||
{
|
||||
_slotIndex = slotIndex;
|
||||
ClearSlot();
|
||||
}
|
||||
|
||||
public void BindItem(RepoItemContext itemContext)
|
||||
{
|
||||
_boundItemId = itemContext?.InstanceId ?? 0;
|
||||
_button.Interactive = true;
|
||||
|
||||
if (_titleText != null)
|
||||
{
|
||||
_titleText.text = itemContext?.Title ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearSlot()
|
||||
{
|
||||
_boundItemId = 0;
|
||||
_button.Interactive = false;
|
||||
|
||||
if (_titleText != null)
|
||||
{
|
||||
_titleText.text = _defaultTitle;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
_slotIndex = -1;
|
||||
ClearSlot();
|
||||
}
|
||||
|
||||
public void OnClick()
|
||||
{
|
||||
if (_slotIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.Event.Fire(this, CombineSlotClickedEventArgs.Create(_slotIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b172c08f0d9b46d3b2cb108a1cc67377
|
||||
timeCreated: 1772107100
|
||||
@@ -0,0 +1,126 @@
|
||||
using System.Collections.Generic;
|
||||
using GameFramework.ObjectPool;
|
||||
using GeometryTD.PoolObjectBase;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class CompArea : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform m_Content;
|
||||
[SerializeField] private RepoItem m_ItemTemplate;
|
||||
[SerializeField] private int m_InstancePoolCapacity = 64;
|
||||
|
||||
private readonly List<RepoItem> m_ActiveItems = new List<RepoItem>();
|
||||
private readonly Dictionary<long, RepoItem> m_ItemMap = new Dictionary<long, RepoItem>();
|
||||
private IObjectPool<RepoItemObject> m_ItemPool;
|
||||
private string m_PoolName;
|
||||
|
||||
public void OnInit(CompAreaContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
OnReset();
|
||||
return;
|
||||
}
|
||||
|
||||
EnsurePool();
|
||||
OnReset();
|
||||
|
||||
if (context.Items == null || context.Items.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < context.Items.Length; i++)
|
||||
{
|
||||
RepoItem item = CreateOrSpawnItem();
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
item.gameObject.SetActive(true);
|
||||
item.OnInit(context.Items[i]);
|
||||
m_ActiveItems.Add(item);
|
||||
m_ItemMap[context.Items[i].InstanceId] = item;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
for (int i = m_ActiveItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
RepoItem item = m_ActiveItems[i];
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
item.OnReset();
|
||||
item.gameObject.SetActive(false);
|
||||
m_ItemPool?.Unspawn(item);
|
||||
}
|
||||
|
||||
m_ActiveItems.Clear();
|
||||
m_ItemMap.Clear();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
OnReset();
|
||||
m_ItemPool?.ReleaseAllUnused();
|
||||
}
|
||||
|
||||
private void EnsurePool()
|
||||
{
|
||||
if (m_ItemPool != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_PoolName = $"RepoItemPool_{GetInstanceID()}";
|
||||
m_ItemPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool<RepoItemObject>(m_PoolName, m_InstancePoolCapacity);
|
||||
}
|
||||
|
||||
private RepoItem CreateOrSpawnItem()
|
||||
{
|
||||
if (m_ItemPool == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
RepoItemObject itemObject = m_ItemPool.Spawn();
|
||||
RepoItem item = itemObject != null ? (RepoItem)itemObject.Target : null;
|
||||
if (item == null)
|
||||
{
|
||||
if (m_ItemTemplate == null)
|
||||
{
|
||||
Log.Warning("CompArea requires an item template.");
|
||||
return null;
|
||||
}
|
||||
|
||||
item = Instantiate(m_ItemTemplate);
|
||||
m_ItemPool.Register(RepoItemObject.Create(item), true);
|
||||
}
|
||||
|
||||
if (m_Content != null)
|
||||
{
|
||||
item.transform.SetParent(m_Content, false);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public void SetItemSelected(long itemId, bool isSelected)
|
||||
{
|
||||
if (!m_ItemMap.TryGetValue(itemId, out RepoItem item))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
item.SetSelected(isSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3b1aede0e52479995cf71ba52a69d63
|
||||
timeCreated: 1772106310
|
||||
@@ -0,0 +1,82 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class EventForm : UGuiForm
|
||||
{
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
[SerializeField] private TMP_Text _descriptionText;
|
||||
[SerializeField] private EventOptionItem[] _optionItems;
|
||||
|
||||
private EventFormContext _context;
|
||||
|
||||
public void RefreshUI(EventFormContext context)
|
||||
{
|
||||
_context = context;
|
||||
|
||||
if (_titleText != null)
|
||||
{
|
||||
_titleText.text = context?.Title ?? string.Empty;
|
||||
}
|
||||
|
||||
if (_descriptionText != null)
|
||||
{
|
||||
_descriptionText.text = context?.Description ?? string.Empty;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _optionItems.Length; i++)
|
||||
{
|
||||
EventOptionItemContext optionContext = null;
|
||||
if (context?.OptionItems != null && i < context.OptionItems.Length)
|
||||
{
|
||||
optionContext = context.OptionItems[i];
|
||||
}
|
||||
|
||||
if (_optionItems[i] != null)
|
||||
{
|
||||
_optionItems[i].OnInit(optionContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnOpen(object userData)
|
||||
{
|
||||
base.OnOpen(userData);
|
||||
|
||||
if (userData is EventFormContext context)
|
||||
{
|
||||
RefreshUI(context);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Warning("EventForm requires EventFormContext as userData.");
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
_context = null;
|
||||
|
||||
if (_titleText != null)
|
||||
{
|
||||
_titleText.text = string.Empty;
|
||||
}
|
||||
|
||||
if (_descriptionText != null)
|
||||
{
|
||||
_descriptionText.text = string.Empty;
|
||||
}
|
||||
|
||||
foreach (var item in _optionItems)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
item.OnReset();
|
||||
}
|
||||
}
|
||||
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81064d72b60548b6b54d07d94d20b519
|
||||
timeCreated: 1772104206
|
||||
@@ -0,0 +1,50 @@
|
||||
using GeometryTD.CustomEvent;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class EventOptionItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_Text _optionText;
|
||||
|
||||
private int _optionIndex;
|
||||
|
||||
public void OnInit(EventOptionItemContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
OnReset();
|
||||
gameObject.SetActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_optionIndex = context.OptionIndex;
|
||||
if (_optionText != null)
|
||||
{
|
||||
_optionText.text = context.OptionText ?? string.Empty;
|
||||
}
|
||||
|
||||
gameObject.SetActive(!string.IsNullOrEmpty(context.OptionText));
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
_optionIndex = -1;
|
||||
if (_optionText != null)
|
||||
{
|
||||
_optionText.text = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClick()
|
||||
{
|
||||
if (_optionIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.Event.Fire(this, EventOptionItemSelectedEventArgs.Create(_optionIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86cf465d14c649a58473c19ae946d220
|
||||
timeCreated: 1772104205
|
||||
@@ -0,0 +1,49 @@
|
||||
using GeometryTD.CustomEvent;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class MainForm : UGuiForm
|
||||
{
|
||||
private MainFormContext _context;
|
||||
|
||||
public void RefreshUI(MainFormContext context)
|
||||
{
|
||||
_context = context;
|
||||
if (_context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReturnButtonClick()
|
||||
{
|
||||
GameEntry.Event.Fire(this, ReturnButtonClickedEventArgs.Create());
|
||||
}
|
||||
|
||||
public void OnRepoButtonClick()
|
||||
{
|
||||
GameEntry.Event.Fire(this, RepoButtonClickedEventArgs.Create());
|
||||
}
|
||||
|
||||
protected override void OnOpen(object userData)
|
||||
{
|
||||
base.OnOpen(userData);
|
||||
|
||||
if (userData is MainFormContext context)
|
||||
{
|
||||
RefreshUI(context);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Warning("MainForm requires MainFormContext as userData.");
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
_context = null;
|
||||
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 838d81ed05914e248972f7ad7df7787d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class RepoForm : UGuiForm
|
||||
{
|
||||
[SerializeField] private CombineArea _combineArea;
|
||||
[SerializeField] private CompArea _compArea;
|
||||
|
||||
public void RefreshUI(RepoFormContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_combineArea?.OnInit(context.CombineAreaContext);
|
||||
_compArea?.OnInit(context.CompAreaContext);
|
||||
}
|
||||
|
||||
public bool TryAssignItemToCombineArea(RepoItemContext itemContext)
|
||||
{
|
||||
if (_combineArea == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _combineArea.TryAssignItem(itemContext);
|
||||
}
|
||||
|
||||
public bool TryClearCombineSlot(int slotIndex, out long removedItemId)
|
||||
{
|
||||
removedItemId = 0;
|
||||
if (_combineArea == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _combineArea.TryClearSlot(slotIndex, out removedItemId);
|
||||
}
|
||||
|
||||
public void SetRepoItemSelected(long itemId, bool isSelected)
|
||||
{
|
||||
_compArea?.SetItemSelected(itemId, isSelected);
|
||||
}
|
||||
|
||||
protected override void OnOpen(object userData)
|
||||
{
|
||||
base.OnOpen(userData);
|
||||
if (userData is RepoFormContext context)
|
||||
{
|
||||
RefreshUI(context);
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Warning("RepoForm requires RepoFormContext as userData.");
|
||||
}
|
||||
|
||||
protected override void OnClose(bool isShutdown, object userData)
|
||||
{
|
||||
_combineArea?.OnReset();
|
||||
_compArea?.OnReset();
|
||||
base.OnClose(isShutdown, userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e10fdbb413c14f5eb749888590f56ff7
|
||||
timeCreated: 1772106307
|
||||
@@ -0,0 +1,69 @@
|
||||
using GeometryTD.CustomEvent;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.UI
|
||||
{
|
||||
public class RepoItem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_Text _titleText;
|
||||
[SerializeField] private Image _highlightImage;
|
||||
|
||||
private static readonly Color NormalColor = new Color32(40, 40, 40, 180);
|
||||
private static readonly Color SelectedColor = new Color32(255, 216, 102, 255);
|
||||
|
||||
private RepoItemContext _context;
|
||||
|
||||
public void OnInit(RepoItemContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
OnReset();
|
||||
return;
|
||||
}
|
||||
|
||||
_context = context;
|
||||
|
||||
if (_titleText != null)
|
||||
{
|
||||
_titleText.text = context.Title ?? string.Empty;
|
||||
}
|
||||
|
||||
SetSelected(false);
|
||||
}
|
||||
|
||||
public void OnReset()
|
||||
{
|
||||
_context = null;
|
||||
|
||||
if (_titleText != null)
|
||||
{
|
||||
_titleText.text = string.Empty;
|
||||
}
|
||||
|
||||
SetSelected(false);
|
||||
}
|
||||
|
||||
public void SetSelected(bool isSelected)
|
||||
{
|
||||
if (_highlightImage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_highlightImage.color = isSelected ? SelectedColor : NormalColor;
|
||||
}
|
||||
|
||||
public void OnClick()
|
||||
{
|
||||
if (_context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.Event.Fire(this, RepoItemSelectedEventArgs.Create(_context.InstanceId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba332072a148499b8f6ec886c661c00f
|
||||
timeCreated: 1772106309
|
||||
Reference in New Issue
Block a user