unity_art_puzzle_playable_luna/APPlayableLuna/Assets/Scripts/UIGameView.cs

634 lines
22 KiB
C#
Raw Normal View History

2023-12-21 08:33:05 +00:00
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);
}
}
}