634 lines
22 KiB
C#
634 lines
22 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using DG.Tweening;
|
||
using Sequence = DG.Tweening.Sequence;
|
||
|
||
namespace GuruClient
|
||
{
|
||
public class UIGameView : MonoBehaviour
|
||
{
|
||
public Transform patchesScrollView;
|
||
|
||
public Slider sldLevelProgress;
|
||
|
||
public Transform tipsFinger;
|
||
|
||
public GuruScrollRect sr;
|
||
|
||
public Text txtProgress;
|
||
|
||
public GameObject patchTemplate;
|
||
|
||
public Transform puzzleWhole;
|
||
public Transform puzzleBaseImg;
|
||
public Transform puzzleBaseImgLines;
|
||
public GameObject patchesPool;
|
||
public GameObject btnBack;
|
||
public GameObject btnTips;
|
||
public GameObject btnDebugDrag;
|
||
public Texture noiseTexture;
|
||
public GameObject objStageWinFx;
|
||
public GameObject objDotProgress;
|
||
|
||
private GameModel _gameModel;
|
||
|
||
private Sequence _myTipsSequence = null;
|
||
//已完成的拼图
|
||
private List<Patche> _completePatche = new List<Patche>();
|
||
private GameObject _roleTemplate;
|
||
|
||
//手指抬起时间
|
||
private double _fingerUpTime = 0f;
|
||
|
||
//第一关的自动提示
|
||
private int _autoTipsTimer;
|
||
private int _levelDurationTimer;
|
||
|
||
//自动游戏的Timer
|
||
private int _autoPlayTimer = 0;
|
||
|
||
private float _lastMatchTime;
|
||
private bool _hasGuide = false;
|
||
private bool _isFirstRefresh = true;
|
||
|
||
//是否已经开始下一关下载
|
||
private bool _hasStartDownloadNextLevel = false;
|
||
|
||
private void Awake()
|
||
{
|
||
|
||
}
|
||
|
||
// Start is called before the first frame update
|
||
void Start()
|
||
{
|
||
EventManager.AddListenner("UPDATE_PROGRESS", UpdateProgress);
|
||
EventManager.AddListenner("START_NEXT_LEVEL", OnNextLevel);
|
||
EventManager.AddListenner("UPDATE_PROGRESS_DOT", UpdateProgressDot);
|
||
|
||
btnTips.GetComponent<Button>().onClick.AddListener(() =>
|
||
{
|
||
ShowTips(true);
|
||
});
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
EventManager.RemoveListenner("UPDATE_PROGRESS", UpdateProgress);
|
||
EventManager.RemoveListenner("START_NEXT_LEVEL", OnNextLevel);
|
||
EventManager.RemoveListenner("UPDATE_PROGRESS_DOT", UpdateProgressDot);
|
||
}
|
||
|
||
public void StartGame()
|
||
{
|
||
_gameModel = GameManager.Instance.GetModel();
|
||
|
||
GameManager.Instance.PatchPool.OnInit(delegate(GameObject obj)
|
||
{
|
||
Patche patche = obj.GetComponent<Patche>();
|
||
if (patche != null)
|
||
{
|
||
patche.Init();
|
||
}
|
||
});
|
||
GameManager.Instance.StartStage();
|
||
OnNextLevel();
|
||
UpdateProgress();
|
||
}
|
||
|
||
public void AddCompletePatche(Patche patche)
|
||
{
|
||
_completePatche.Add(patche);
|
||
}
|
||
|
||
private string GetPsdID()
|
||
{
|
||
if (_gameModel != null)
|
||
{
|
||
ALevel aLevel = _gameModel.GetCurrentLevel();
|
||
if (aLevel != null)
|
||
{
|
||
return aLevel.psdID;
|
||
}
|
||
}
|
||
|
||
return "";
|
||
}
|
||
|
||
//给已经patched的进行排序
|
||
public void SortPatched()
|
||
{
|
||
if (_completePatche.Count > 1)
|
||
{
|
||
_completePatche[_completePatche.Count - 1].transform.SetSiblingIndex(_completePatche.Count);
|
||
for (int i = _completePatche.Count - 1; i >= 0 ; i--)
|
||
{
|
||
Patche cur = _completePatche[i];
|
||
Patche pre = null;
|
||
if (i - 1 >= 0)
|
||
{
|
||
pre = _completePatche[i - 1];
|
||
}
|
||
|
||
if (pre != null)
|
||
{
|
||
int preOrder = pre.GetOrder();
|
||
int curOrder = cur.GetOrder();
|
||
if (preOrder > curOrder)
|
||
{
|
||
Patche tmp = pre;
|
||
_completePatche[i - 1] = cur;
|
||
_completePatche[i] = tmp;
|
||
}else
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
for (int i = 0; i < _completePatche.Count; i++)
|
||
{
|
||
_completePatche[i].transform.SetSiblingIndex(_completePatche[i].GetOrder());
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除patch对应的一条线
|
||
/// </summary>
|
||
/// <param name="aPatch">拼图文件数据</param>
|
||
public void RemoveLine(APatch aPatch)
|
||
{
|
||
if (_gameModel.IsHideLineWhenPatched() && aPatch.IsPatch())
|
||
{
|
||
string lineName = aPatch.name.Replace("patch", "line");
|
||
|
||
Transform tf = puzzleBaseImgLines.Find(lineName);
|
||
RemoveALine(tf);
|
||
}
|
||
}
|
||
|
||
public void OnNextLevel(IEventData data = null)
|
||
{
|
||
sldLevelProgress.maxValue = GameManager.Instance.GetCurrentStageData().Count;
|
||
|
||
sldLevelProgress.value = _gameModel.GetCurrentStep();
|
||
}
|
||
|
||
public void UpdateProgress(IEventData data = null)
|
||
{
|
||
txtProgress.text = _gameModel.GetCompletePatchCount() + "/" + _gameModel.GetTotalPatchCount();
|
||
sldLevelProgress.value = _gameModel.GetCurrentStep();
|
||
}
|
||
|
||
public void UpdateProgressDot(IEventData data = null)
|
||
{
|
||
//更新dot progress
|
||
Tuple<int, int> stagePro = _gameModel.GetStageProgress();
|
||
if (stagePro.Item2 <= 1)
|
||
{
|
||
return;
|
||
}
|
||
int childCount = objDotProgress.transform.childCount;
|
||
// Log.E(stagePro.Item1 - 1 +"/"+stagePro.Item2);
|
||
GameObject prefab = objDotProgress.transform.GetChild(0).gameObject;
|
||
for (int i = 0; i < stagePro.Item2; i++)
|
||
{
|
||
GameObject obj;
|
||
if (i < childCount)
|
||
{
|
||
obj = objDotProgress.transform.GetChild(i).gameObject;
|
||
}
|
||
else
|
||
{
|
||
obj = Instantiate(prefab, objDotProgress.transform);
|
||
}
|
||
|
||
obj.SetActive(true);
|
||
if (i < stagePro.Item1 - 1)
|
||
{
|
||
obj.transform.Find("Dot").gameObject.SetActive(true);
|
||
}
|
||
else
|
||
{
|
||
obj.transform.Find("Dot").gameObject.SetActive(false);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void LoadAutoPatches(List<APatch> patches, bool isTexture = false, bool isRecover = false, Action callback = null)
|
||
{
|
||
for (int i = 0; i < patches.Count; i++)
|
||
{
|
||
APatch aPatch = patches[i];
|
||
// GameObject temp = Instantiate(patchTemplate, puzzleBaseImg);
|
||
GameObject temp = GameManager.Instance.PatchPool.GetObj(puzzleBaseImg);
|
||
Patche p = temp.GetComponent<Patche>();
|
||
string folder = isTexture ? "Texture" : "Atlas";
|
||
string patchImgPath = $"Levels/{GetPsdID()}/{folder}/{aPatch.name}";
|
||
p.SetData(this, aPatch, patchImgPath);
|
||
p.PositionedFinal(false);
|
||
|
||
if (i == 0)
|
||
{
|
||
p.ShowEffect(true, isRecover, null, 1.0f, callback);
|
||
}
|
||
else
|
||
{
|
||
p.ShowEffect(true, isRecover, null, 1.0f, null);
|
||
}
|
||
}
|
||
|
||
if (patches.Count == 0)
|
||
{
|
||
Timer.Instance.SetTimeout(0.05f, () => {
|
||
callback?.Invoke();
|
||
});
|
||
}
|
||
}
|
||
|
||
public void LoadBg(Action callback)
|
||
{
|
||
Debug.Log("加载背景 开始");
|
||
Dictionary<string, APatch> patchDB = _gameModel.GetPatchDB();
|
||
APatch aPatch = patchDB[$"base"];
|
||
// GameObject temp = Instantiate(patchTemplate, puzzleBaseImg);
|
||
Debug.Log("加载背景 step 1");
|
||
GameObject temp = GameManager.Instance.PatchPool.GetObj(puzzleBaseImg);
|
||
temp.transform.SetSiblingIndex(0);
|
||
Debug.Log("加载背景 step 2");
|
||
Patche p = temp.GetComponent<Patche>();
|
||
string patchImgPath = $"Levels/{GetPsdID()}/Texture/{aPatch.name}";
|
||
Debug.Log("加载背景 step 3");
|
||
p.SetData(this, aPatch, patchImgPath);
|
||
|
||
Debug.Log("加载背景 step 4");
|
||
p.PositionedFinal(false);
|
||
Debug.Log("加载背景 step 5");
|
||
|
||
p.ShowEffect(true, false, null, 1.0f, callback);
|
||
Debug.Log("加载背景 成功");
|
||
}
|
||
|
||
//加载人物
|
||
public void LoadRole(bool isRecover = false, bool isFinish = false, Action callback = null)
|
||
{
|
||
Dictionary<string, APatch> patchDB = _gameModel.GetPatchDB();
|
||
APatch aPatch = new APatch();
|
||
bool found = false;
|
||
//如果是恢复游戏,则找到上一个人物,并显示
|
||
if(isRecover)
|
||
{
|
||
for (int i = _gameModel.GetCurrentStage(); i >= 0; i--)
|
||
{
|
||
if (patchDB.TryGetValue($"role_{i - 1}", out aPatch))
|
||
{
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
}else //否则使用当前人物
|
||
{
|
||
if (patchDB.TryGetValue($"role_{_gameModel.GetCurrentStage() - 1}", out aPatch))
|
||
{
|
||
found = true;
|
||
}
|
||
}
|
||
if (found)
|
||
{
|
||
//移除以前的人物
|
||
if (_roleTemplate != null)
|
||
{
|
||
GameObject tmp = _roleTemplate;
|
||
ShowEffectInner(tmp, null);
|
||
}
|
||
// GameObject temp = Instantiate(patchTemplate, puzzleBaseImg);
|
||
GameObject temp = GameManager.Instance.PatchPool.GetObj(puzzleBaseImg);
|
||
_roleTemplate = temp;
|
||
Patche p = temp.GetComponent<Patche>();
|
||
temp.transform.SetSiblingIndex(aPatch.sub_stage);
|
||
string patchImgPath = $"Levels/{GetPsdID()}/Texture/{aPatch.name}_{aPatch.sub_stage}";
|
||
p.SetData(this, aPatch, patchImgPath);
|
||
|
||
p.PositionedFinal(false);
|
||
|
||
p.ShowFade(true, false, callback);
|
||
}
|
||
|
||
callback?.Invoke();
|
||
}
|
||
|
||
//新增协程
|
||
private void ShowEffectInner(GameObject go, Action callback)
|
||
{
|
||
go.GetComponent<Patche>().ShowFade(false, false, () =>
|
||
{
|
||
_completePatche.Remove(go.GetComponent<Patche>());
|
||
// DestroyImmediate(go);
|
||
GameManager.Instance.PatchPool.RecycleObj(go);
|
||
callback?.Invoke();
|
||
});
|
||
}
|
||
|
||
//加载线稿图
|
||
public void LoadLineTemplate(Action callback)
|
||
{
|
||
// GamePlayConfig gamePlayConfig = GameConfig.GetConfig<GamePlayConfig>();
|
||
// int hideLineLevel = gamePlayConfig.GetHideLineLevel(_gameModel.GetCurrentLevel().type);
|
||
bool isRemoveLineWhenPatched = true;
|
||
|
||
List<APatch> lines = GameManager.Instance.GetCurrentStageLineData();
|
||
foreach (APatch aPatch in lines)
|
||
{
|
||
Transform patchTrans = puzzleBaseImg.Find(aPatch.name.Replace("line", "patch"));
|
||
if ((isRemoveLineWhenPatched && patchTrans == null) || !isRemoveLineWhenPatched)
|
||
{
|
||
// APatch aPatch = patchDB[$"line_{_gameModel.GetCurrentStage()}"];
|
||
// GameObject temp = Instantiate(patchTemplate, puzzleBaseImgLines);
|
||
GameObject temp = GameManager.Instance.PatchPool.GetObj(puzzleBaseImgLines);
|
||
Patche p = temp.GetComponent<Patche>();
|
||
temp.transform.SetSiblingIndex(10000);
|
||
string patchImgPath = $"Levels/{GetPsdID()}/Lines/{aPatch.name}";
|
||
p.SetData(this, aPatch, patchImgPath);
|
||
|
||
p.PositionedFinal(false);
|
||
|
||
p.ShowEffect(true, false, null, 1.0f);
|
||
}
|
||
}
|
||
|
||
Timer.Instance.SetTimeoutAsync(1.0f, callback);
|
||
}
|
||
|
||
public void RemoveLineTemplate(Action callback)
|
||
{
|
||
if (puzzleBaseImgLines.childCount > 0)
|
||
{
|
||
for (int i = puzzleBaseImgLines.childCount - 1; i >= 0; i--)
|
||
{
|
||
RemoveALine(puzzleBaseImgLines.GetChild(i));
|
||
}
|
||
|
||
Timer.Instance.SetTimeout(2.0f , () =>
|
||
{
|
||
callback?.Invoke();
|
||
});
|
||
}else
|
||
{
|
||
callback?.Invoke();
|
||
}
|
||
}
|
||
|
||
private void RemoveALine(Transform line)
|
||
{
|
||
if (line != null)
|
||
{
|
||
RemoveALineInner(line, null);
|
||
}
|
||
}
|
||
|
||
private void RemoveALineInner(Transform line, Action callback)
|
||
{
|
||
line.GetComponent<Patche>().ShowEffect(false, false, null, 1.0f, callback);
|
||
DestroyImmediate(line.gameObject);
|
||
// GameManager.Instance.PatchPool.RecycleObj(line.gameObject);
|
||
}
|
||
|
||
//游戏结束
|
||
public void GameWin(bool isDrop)
|
||
{
|
||
StopTipsTimer();
|
||
// UIManager.Instance.Show(UIID.UIGameWin, new object[2]{_gameModel.GetCurrentLevel(), isDrop}, (uibase) => {
|
||
// CustomAssetBundle cab = GameManager.Instance.GetCustomAssetBundle();
|
||
// //避免资源被释放,主动添加引用
|
||
// cab.AddTag(uibase.GetUIConfig().prefab);
|
||
// GameManager.Instance.ExitGame();
|
||
// });
|
||
|
||
Debug.Log("拼图完成");
|
||
}
|
||
|
||
public void StopTipsTimer()
|
||
{
|
||
if (_autoTipsTimer != 0)
|
||
{
|
||
Timer.Instance.Stop(_autoTipsTimer);
|
||
_autoTipsTimer = 0;
|
||
}
|
||
|
||
if(_autoPlayTimer != 0)
|
||
{
|
||
Timer.Instance.Stop(_autoPlayTimer);
|
||
_autoPlayTimer = 0;
|
||
}
|
||
}
|
||
|
||
public void ShowTips(bool isFree)
|
||
{
|
||
string psdID = GetPsdID();
|
||
if (true)
|
||
{
|
||
APatch patch = GameManager.Instance.GetOneUnCompletePatch();
|
||
if (patch.isValid())
|
||
{
|
||
Transform tipsChild = null;
|
||
Transform poolTrans = patchesPool.transform;
|
||
int childCount = OriginPatchObjs.Count;
|
||
for (int i = 0; i < childCount; i++)
|
||
{
|
||
Transform child = OriginPatchObjs[i].transform;
|
||
APatch p = child.GetComponent<Patche>().GetData();
|
||
if(p.Equals(patch))
|
||
{
|
||
tipsChild = child;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(tipsChild != null)
|
||
{
|
||
sr.StopMovement();
|
||
|
||
float x = -tipsChild.localPosition.x + Screen.width/2;
|
||
x = Mathf.Min(x, 0);
|
||
if(poolTrans.parent.GetComponent<RectTransform>().sizeDelta.x > 0)
|
||
{
|
||
x = Mathf.Max(x, -poolTrans.parent.GetComponent<RectTransform>().sizeDelta.x);
|
||
}
|
||
|
||
poolTrans.parent.localPosition = new Vector3(x, poolTrans.parent.localPosition.y, poolTrans.parent.localPosition.z);
|
||
|
||
StopTips();
|
||
Patche patche = tipsChild.GetComponent<Patche>();
|
||
APatch p = patche.GetData();
|
||
|
||
Vector2 endPos = puzzleWhole.localPosition + patche.GetConvertedTargetPos();
|
||
|
||
//控制手指从A移动到B
|
||
tipsFinger.position = tipsChild.position;
|
||
tipsFinger.gameObject.SetActive(true);
|
||
_myTipsSequence = DOTween.Sequence();
|
||
_myTipsSequence.SetLoops(-1);
|
||
_myTipsSequence.Append(tipsFinger.GetComponent<Image>().DOFade(1, 0.5f));
|
||
_myTipsSequence.Append(tipsFinger.DOLocalMove(endPos, 1.0f).SetDelay( 0.5f));
|
||
_myTipsSequence.Append(tipsFinger.GetComponent<Image>().DOFade(0, 0.5f).SetDelay( 0.5f).OnComplete(() => {
|
||
|
||
}));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//停止引导动作
|
||
public void StopTips()
|
||
{
|
||
if (_myTipsSequence != null)
|
||
{
|
||
_myTipsSequence.Kill();
|
||
_myTipsSequence = null;
|
||
tipsFinger.localPosition = new Vector3(3000, 30000, 0);
|
||
tipsFinger.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化拼图
|
||
/// </summary>
|
||
/// <param name="stage">需要初始化的阶段,-1表示全部</param>
|
||
/// <param name="complete">完成后的回调</param>
|
||
/// <returns></returns>
|
||
public void InitPatches(int stage, Action complete)
|
||
{
|
||
List<APatch> patchDB = _gameModel.GetOperablePatch();
|
||
_patchObjs.Clear();
|
||
OriginPatchObjs.Clear();
|
||
List<APatch> tmpList = new List<APatch>();
|
||
|
||
int index = 1;
|
||
foreach (APatch item in patchDB)
|
||
{
|
||
if (((stage == -1 && item.stage >= _gameModel.GetCurrentStage()) || stage == item.stage) && !GameManager.Instance.IsCompletedPatch(item))
|
||
{
|
||
tmpList.Add(item);
|
||
CreatePatch(item, index);
|
||
index ++;
|
||
}
|
||
}
|
||
|
||
SetPatchIndex(tmpList);
|
||
SortPatches(true, complete, true, 0.05f);
|
||
}
|
||
|
||
private void SetPatchIndex(List<APatch> patchDB)
|
||
{
|
||
patchDB.Sort(delegate(APatch patch1, APatch patch2)
|
||
{
|
||
if (patch1.stage < patch2.stage)
|
||
{
|
||
return -1;
|
||
}
|
||
if (patch1.stage > patch2.stage)
|
||
{
|
||
return 1;
|
||
}
|
||
if (patch1.sub_stage < patch2.sub_stage)
|
||
{
|
||
return -1;
|
||
}
|
||
if (patch1.sub_stage > patch2.sub_stage)
|
||
{
|
||
return 1;
|
||
}
|
||
|
||
return 1;
|
||
});
|
||
|
||
for (int i = 0; i < patchDB.Count; i++)
|
||
{
|
||
if (_patchObjs.TryGetValue(patchDB[i].name, out var obj))
|
||
{
|
||
obj.transform.SetSiblingIndex(i);
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("index不存在");
|
||
}
|
||
}
|
||
}
|
||
|
||
private void CreatePatch(APatch aPatch, int index)
|
||
{
|
||
// GameObject temp = Instantiate(patchTemplate, patchesPool.transform);
|
||
GameObject temp = GameManager.Instance.PatchPool.GetObj(patchesPool.transform);
|
||
// temp.AddComponent<KeepReverseWhenAdded>();
|
||
Patche p = temp.GetComponent<Patche>();
|
||
_patchObjs[aPatch.name] = temp;
|
||
OriginPatchObjs.Add(temp);
|
||
string patchImgPath = $"Levels/{GetPsdID()}/Atlas/{aPatch.name}";
|
||
p.SetData(this, aPatch, patchImgPath);
|
||
//1000为固定偏移,之后sort的时候,做入场效果
|
||
temp.transform.localPosition = new Vector3(GameDefine.Game.PATCH_PADDING + (GameDefine.Game.PATCH_SIZE_MAX.x + GameDefine.Game.PATCH_SPAN) * index + 1500, 0, 0);
|
||
}
|
||
|
||
private Dictionary<string, GameObject> _patchObjs = new Dictionary<string, GameObject>();
|
||
public List<GameObject> OriginPatchObjs { set; get; } = new List<GameObject>();
|
||
|
||
private float _moveTime = 0.5f;
|
||
public void SortPatches(bool hasAnimation = false, Action complete = null, bool isResize = true, float delay = 0)
|
||
{
|
||
int completeCount = 0;
|
||
// RectTransform rtf = patchesPool.GetComponent<RectTransform>();
|
||
|
||
if (isResize)
|
||
{
|
||
ResizePatchesPool();
|
||
}
|
||
|
||
float totalDelay = delay;
|
||
int childCount = OriginPatchObjs.Count;
|
||
for (int i = 0; i < childCount; i++)
|
||
{
|
||
Transform child = OriginPatchObjs[i].transform;
|
||
if (hasAnimation)
|
||
{
|
||
Tweener tw = child.DOLocalMove(
|
||
new Vector3(
|
||
GameDefine.Game.PATCH_PADDING +
|
||
(GameDefine.Game.PATCH_SIZE_MAX.x + GameDefine.Game.PATCH_SPAN) * i +
|
||
GameDefine.Game.PATCH_SIZE_MAX.x / 2, 0, 0), _moveTime)
|
||
.OnComplete(() =>
|
||
{
|
||
completeCount++;
|
||
if (completeCount == childCount)
|
||
{
|
||
complete?.Invoke();
|
||
}
|
||
}).SetRecyclable();
|
||
if (i <= 5)
|
||
{
|
||
tw.SetDelay(totalDelay);
|
||
totalDelay += delay;
|
||
}
|
||
}else
|
||
{
|
||
child.localPosition = new Vector3(GameDefine.Game.PATCH_PADDING + (GameDefine.Game.PATCH_SIZE_MAX.x + GameDefine.Game.PATCH_SPAN) * i + GameDefine.Game.PATCH_SIZE_MAX.x/2, 0, 0);
|
||
}
|
||
}
|
||
|
||
if (!hasAnimation)
|
||
{
|
||
complete?.Invoke();
|
||
}
|
||
}
|
||
|
||
public void ResizePatchesPool()
|
||
{
|
||
RectTransform rtf = patchesPool.GetComponent<RectTransform>();
|
||
rtf.sizeDelta = new Vector2(rtf.childCount * (GameDefine.Game.PATCH_SIZE_MAX.x + GameDefine.Game.PATCH_SPAN) + 2 * GameDefine.Game.PATCH_PADDING - GameDefine.Game.PATCH_SPAN, rtf.sizeDelta.y);
|
||
}
|
||
}
|
||
}
|