迭代拼装玩法与素材
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Definition.Enum;
|
||||
using Event;
|
||||
using UI;
|
||||
using UnityEngine;
|
||||
@@ -42,40 +41,11 @@ namespace CustomComponent
|
||||
/// </summary>
|
||||
[SerializeField] private Transform _puzzleRoot = null;
|
||||
|
||||
/// <summary>
|
||||
/// 拼装开始时提示文本。
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[TextArea(2, 4)]
|
||||
private string _startHint = "Assemble dougong from lower-to-upper and inner-to-outer.";
|
||||
[SerializeField] [TextArea(1, 3)] private string _successHint = "拼接成功";
|
||||
|
||||
/// <summary>
|
||||
/// 放置顺序错误提示文本。
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[TextArea(2, 4)]
|
||||
private string _wrongOrderHint = "Wrong order. Place lower or inner parts first.";
|
||||
[SerializeField] [TextArea(1, 3)] private string _orderErrorHint = "顺序错误";
|
||||
|
||||
/// <summary>
|
||||
/// 部件不匹配提示文本。
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[TextArea(2, 4)]
|
||||
private string _wrongPartHint = "Part does not match this slot.";
|
||||
|
||||
/// <summary>
|
||||
/// 槽位已占用提示文本。
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[TextArea(2, 4)]
|
||||
private string _slotOccupiedHint = "This slot is already occupied.";
|
||||
|
||||
/// <summary>
|
||||
/// 拼装完成提示文本。
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[TextArea(2, 4)]
|
||||
private string _completeHint = "Dougong assembly completed.";
|
||||
[SerializeField] [TextArea(1, 3)] private string _positionErrorHint = "位置错误";
|
||||
|
||||
/// <summary>
|
||||
/// 当前参与拼装的槽位列表。
|
||||
@@ -229,11 +199,6 @@ namespace CustomComponent
|
||||
_isPaused = false;
|
||||
|
||||
GameEntry.Event.Fire(this, CombineProgressEventArgs.Create(_placedCount, _orderedSlots.Count));
|
||||
|
||||
if (!string.IsNullOrEmpty(_startHint))
|
||||
{
|
||||
GameEntry.Event.Fire(this, CombineGuideMessageEventArgs.Create(_startHint));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -311,7 +276,7 @@ namespace CustomComponent
|
||||
return true;
|
||||
}
|
||||
|
||||
RejectPlace(part, _slotOccupiedHint);
|
||||
RejectPlace(part, CombineFeedbackType.PositionError);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -325,8 +290,7 @@ namespace CustomComponent
|
||||
return true;
|
||||
}
|
||||
|
||||
string hint = string.IsNullOrEmpty(slot.MismatchHint) ? _wrongPartHint : slot.MismatchHint;
|
||||
RejectPlace(part, hint);
|
||||
RejectPlace(part, CombineFeedbackType.PositionError);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -340,7 +304,7 @@ namespace CustomComponent
|
||||
return true;
|
||||
}
|
||||
|
||||
RejectPlace(part, _wrongOrderHint);
|
||||
RejectPlace(part, CombineFeedbackType.OrderError);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -354,7 +318,7 @@ namespace CustomComponent
|
||||
|
||||
_placedCount++;
|
||||
AdvanceOrderCursor();
|
||||
PublishExplanation(part, slot);
|
||||
PublishFeedback(CombineFeedbackType.Success);
|
||||
|
||||
GameEntry.Event.Fire(this, CombineProgressEventArgs.Create(_placedCount, _orderedSlots.Count));
|
||||
TryCompletePuzzle();
|
||||
@@ -372,11 +336,6 @@ namespace CustomComponent
|
||||
|
||||
_isCompleted = true;
|
||||
|
||||
if (!string.IsNullOrEmpty(_completeHint))
|
||||
{
|
||||
GameEntry.Event.Fire(this, CombineGuideMessageEventArgs.Create(_completeHint));
|
||||
}
|
||||
|
||||
GameEntry.Event.Fire(this, CombineCompletedEventArgs.Create());
|
||||
_onPuzzleCompleted.Invoke();
|
||||
}
|
||||
@@ -384,14 +343,29 @@ namespace CustomComponent
|
||||
/// <summary>
|
||||
/// 处理放置失败:部件回弹并提示。
|
||||
/// </summary>
|
||||
private void RejectPlace(CombineDraggablePart part, string hint)
|
||||
private void RejectPlace(CombineDraggablePart part, CombineFeedbackType feedbackType)
|
||||
{
|
||||
part.ReturnToSpawnAnimated();
|
||||
PublishFeedback(feedbackType);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(hint))
|
||||
private void PublishFeedback(CombineFeedbackType feedbackType)
|
||||
{
|
||||
string message = string.Empty;
|
||||
switch (feedbackType)
|
||||
{
|
||||
GameEntry.Event.Fire(this, CombineGuideMessageEventArgs.Create(hint));
|
||||
case CombineFeedbackType.Success:
|
||||
message = _successHint;
|
||||
break;
|
||||
case CombineFeedbackType.OrderError:
|
||||
message = _orderErrorHint;
|
||||
break;
|
||||
case CombineFeedbackType.PositionError:
|
||||
message = _positionErrorHint;
|
||||
break;
|
||||
}
|
||||
|
||||
GameEntry.Event.Fire(this, CombineFeedbackEventArgs.Create(feedbackType, message));
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -603,50 +577,6 @@ namespace CustomComponent
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布当前放置对应的力学说明文案。
|
||||
/// </summary>
|
||||
private void PublishExplanation(CombineDraggablePart part, CombineSlot slot)
|
||||
{
|
||||
string explanation = slot.MechanicsExplanation;
|
||||
if (string.IsNullOrEmpty(explanation))
|
||||
{
|
||||
explanation = part.MechanicsExplanation;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(explanation))
|
||||
{
|
||||
explanation = GetDefaultExplanation(part.PartType);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(explanation))
|
||||
{
|
||||
GameEntry.Event.Fire(this, CombinePartMessageEventArgs.Create(explanation));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 兜底力学说明文案。
|
||||
/// </summary>
|
||||
private static string GetDefaultExplanation(CombinePartType partType)
|
||||
{
|
||||
switch (partType)
|
||||
{
|
||||
case CombinePartType.Dou:
|
||||
return "Dou transfers upper load and works as the base node.";
|
||||
case CombinePartType.Sheng:
|
||||
return "Sheng raises layer height to form the bracket hierarchy.";
|
||||
case CombinePartType.Gong:
|
||||
return "Gong spreads force laterally through overhang.";
|
||||
case CombinePartType.Qiao:
|
||||
return "Qiao continues force transfer to the outer side.";
|
||||
case CombinePartType.Ang:
|
||||
return "Ang uses leverage to redirect eave load inward.";
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace CustomComponent
|
||||
{
|
||||
@@ -8,7 +9,7 @@ namespace CustomComponent
|
||||
public sealed class StoryCombineConfig
|
||||
{
|
||||
public bool AutoStart = true;
|
||||
public List<CombineSlotContext> Slots = new List<CombineSlotContext>();
|
||||
public List<CombinePartContext> Parts = new List<CombinePartContext>();
|
||||
public GameObject StructurePrefab;
|
||||
[FormerlySerializedAs("PartPrefabs")] public List<Sprite> PartSprites = new List<Sprite>();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -5,8 +5,6 @@ namespace CustomComponent
|
||||
[CreateAssetMenu(menuName = "Story/Directive/Start Combine", fileName = "Directive_StartCombine")]
|
||||
public sealed class StoryStartCombineDirectiveAsset : StoryDirectiveAsset
|
||||
{
|
||||
[SerializeField] private bool _useDefaultConfig = true;
|
||||
|
||||
[SerializeField] private StoryCombineConfig _combineConfig = new StoryCombineConfig();
|
||||
|
||||
public override string ActionName => "StartCombine";
|
||||
@@ -18,8 +16,7 @@ namespace CustomComponent
|
||||
return;
|
||||
}
|
||||
|
||||
StoryCombineConfig config = _useDefaultConfig ? null : _combineConfig;
|
||||
director.ExecuteStartCombine(config);
|
||||
director.ExecuteStartCombine(_combineConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Definition.Enum;
|
||||
using Event;
|
||||
using UI;
|
||||
using UnityEngine;
|
||||
@@ -293,149 +292,33 @@ namespace CustomComponent
|
||||
|
||||
private static CombineFormContext BuildCombineFormContext(StoryCombineConfig config)
|
||||
{
|
||||
if (config != null && config.Slots != null && config.Slots.Count > 0)
|
||||
if (config == null)
|
||||
{
|
||||
return new CombineFormContext
|
||||
{
|
||||
Slots = CloneSlots(config.Slots),
|
||||
Parts = CloneParts(config.Parts),
|
||||
AutoStart = config.AutoStart
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
return BuildDefaultCombineContext();
|
||||
}
|
||||
|
||||
private static List<CombineSlotContext> CloneSlots(List<CombineSlotContext> source)
|
||||
{
|
||||
var result = new List<CombineSlotContext>();
|
||||
if (source == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int i = 0; i < source.Count; i++)
|
||||
{
|
||||
CombineSlotContext slot = source[i];
|
||||
if (slot == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(new CombineSlotContext
|
||||
{
|
||||
RequiredPartType = slot.RequiredPartType,
|
||||
BuildOrder = slot.BuildOrder,
|
||||
RequireStrictOrder = slot.RequireStrictOrder,
|
||||
AnchoredPosition = slot.AnchoredPosition,
|
||||
SizeDelta = slot.SizeDelta,
|
||||
MechanicsExplanation = slot.MechanicsExplanation,
|
||||
MismatchHint = slot.MismatchHint
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<CombinePartContext> CloneParts(List<CombinePartContext> source)
|
||||
{
|
||||
var result = new List<CombinePartContext>();
|
||||
if (source == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int i = 0; i < source.Count; i++)
|
||||
{
|
||||
CombinePartContext part = source[i];
|
||||
if (part == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(new CombinePartContext
|
||||
{
|
||||
PartType = part.PartType,
|
||||
PartDisplayName = part.PartDisplayName,
|
||||
MechanicsExplanation = part.MechanicsExplanation,
|
||||
LockAfterPlaced = part.LockAfterPlaced
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static CombineFormContext BuildDefaultCombineContext()
|
||||
{
|
||||
List<CombineSlotContext> slots = new List<CombineSlotContext>
|
||||
{
|
||||
new CombineSlotContext
|
||||
{
|
||||
RequiredPartType = CombinePartType.Dou,
|
||||
BuildOrder = 0,
|
||||
RequireStrictOrder = true,
|
||||
AnchoredPosition = new Vector2(-320f, -160f),
|
||||
SizeDelta = new Vector2(120f, 120f),
|
||||
MechanicsExplanation = "Dou transfers upper load and works as the base node."
|
||||
},
|
||||
new CombineSlotContext
|
||||
{
|
||||
RequiredPartType = CombinePartType.Sheng,
|
||||
BuildOrder = 1,
|
||||
RequireStrictOrder = true,
|
||||
AnchoredPosition = new Vector2(-320f, -20f),
|
||||
SizeDelta = new Vector2(120f, 120f),
|
||||
MechanicsExplanation = "Sheng raises layer height to form the bracket hierarchy."
|
||||
},
|
||||
new CombineSlotContext
|
||||
{
|
||||
RequiredPartType = CombinePartType.Gong,
|
||||
BuildOrder = 2,
|
||||
RequireStrictOrder = true,
|
||||
AnchoredPosition = new Vector2(-320f, 120f),
|
||||
SizeDelta = new Vector2(120f, 120f),
|
||||
MechanicsExplanation = "Gong spreads force laterally through overhang."
|
||||
},
|
||||
new CombineSlotContext
|
||||
{
|
||||
RequiredPartType = CombinePartType.Qiao,
|
||||
BuildOrder = 3,
|
||||
RequireStrictOrder = true,
|
||||
AnchoredPosition = new Vector2(-160f, 120f),
|
||||
SizeDelta = new Vector2(120f, 120f),
|
||||
MechanicsExplanation = "Qiao continues force transfer to the outer side."
|
||||
},
|
||||
new CombineSlotContext
|
||||
{
|
||||
RequiredPartType = CombinePartType.Ang,
|
||||
BuildOrder = 4,
|
||||
RequireStrictOrder = true,
|
||||
AnchoredPosition = new Vector2(0f, 120f),
|
||||
SizeDelta = new Vector2(120f, 120f),
|
||||
MechanicsExplanation = "Ang uses leverage to redirect eave load inward."
|
||||
}
|
||||
};
|
||||
|
||||
List<CombinePartContext> parts = new List<CombinePartContext>
|
||||
{
|
||||
new CombinePartContext
|
||||
{ PartType = CombinePartType.Dou, PartDisplayName = "Dou", LockAfterPlaced = true },
|
||||
new CombinePartContext
|
||||
{ PartType = CombinePartType.Sheng, PartDisplayName = "Sheng", LockAfterPlaced = true },
|
||||
new CombinePartContext
|
||||
{ PartType = CombinePartType.Gong, PartDisplayName = "Gong", LockAfterPlaced = true },
|
||||
new CombinePartContext
|
||||
{ PartType = CombinePartType.Qiao, PartDisplayName = "Qiao", LockAfterPlaced = true },
|
||||
new CombinePartContext
|
||||
{ PartType = CombinePartType.Ang, PartDisplayName = "Ang", LockAfterPlaced = true }
|
||||
};
|
||||
|
||||
return new CombineFormContext
|
||||
{
|
||||
Slots = slots,
|
||||
Parts = parts,
|
||||
AutoStart = true
|
||||
StructurePrefab = config.StructurePrefab,
|
||||
PartSprites = ClonePartSprites(config.PartSprites),
|
||||
AutoStart = config.AutoStart
|
||||
};
|
||||
}
|
||||
|
||||
private static List<Sprite> ClonePartSprites(List<Sprite> source)
|
||||
{
|
||||
var result = new List<Sprite>();
|
||||
if (source == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
for (int i = 0; i < source.Count; i++)
|
||||
{
|
||||
result.Add(source[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user