using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using DG.Tweening; namespace GuruClient { public enum PatchStatus { None, //初始 Dragging, //拖拽中 ShowEffect, //显示特效 Matched //拼图完成 } public class Patche : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public GameObject imgBody; private float _scale; private Vector2 _sizeDelta; public Vector3 originalPos{get;set;} private int originalOrder{get; set;} private int originalDataOrder{get; set;} public Vector3 _targetPos{get;set;} private Vector3 _targetPosConverted; private bool isMatch = false; private Vector3 mouseWorld; private float threshold = 40f; private PatchStatus state = PatchStatus.None; private float step = 1.5f; private float tnthreshold = 120f; private UIGameView _uiGameView; private APatch _aPatch; private Vector3 _touchOriginPos; bool _isShow; private float dragDXScale; private float dragDYScale; private float _moveTime = 0.5f; private Material _mat; private Coroutine _effectTimerCoroutine; public void Init() { isMatch = false; state = PatchStatus.None; tnthreshold = 120f; imgBody.transform.localScale=Vector3.one; imgBody.transform.localPosition = Vector3.zero; imgBody.GetComponent().sizeDelta = new Vector2(300, 148); Image img = imgBody.GetComponent(); img.color = new Color(img.color.r, img.color.g, img.color.b, 1); dragDXScale = 1.3f; dragDYScale = 1.3f; } public void SetData(UIGameView uiGameView, APatch aPatch, string imgPath) { _uiGameView = uiGameView; _aPatch = aPatch; //左下角坐标 _targetPos = new Vector3(aPatch.pos[0], aPatch.pos[1], 0); gameObject.name = aPatch.name; Image img = imgBody.GetComponent(); Sprite sp = Resources.Load(imgPath); img.sprite = sp; img.SetNativeSize(); _sizeDelta = imgBody.GetComponent().sizeDelta; float sxmax = GameDefine.Game.PATCH_SIZE_MAX.x / _sizeDelta.x; float symax = GameDefine.Game.PATCH_SIZE_MAX.y / _sizeDelta.y; //缩小到最小,保证所尺寸都在容器内 float scalemax = Mathf.Min(sxmax, symax); scalemax = Math.Min(scalemax, 1); //说明原始尺寸已经在容器内,考虑放大到最小尺寸 //出故意强制false,暂不需要此功能, 后续可能会打开 if (false && scalemax == 1) { float sxmin = GameDefine.Game.PATCH_SIZE_MIN.x / _sizeDelta.x; float symin = GameDefine.Game.PATCH_SIZE_MIN.y / _sizeDelta.y; float scalemin = Mathf.Min(sxmin, symin); scalemin = Mathf.Max(scalemin, 1); _scale = scalemin; }else { _scale = scalemax; } imgBody.transform.localScale = new Vector3(_scale, _scale, 1); RectTransform rt = _uiGameView.puzzleBaseImg.gameObject.GetComponent(); //节点坐标 _targetPosConverted = new Vector3(_targetPos.x - rt.sizeDelta.x/2, _targetPos.y - rt.sizeDelta.y/2, 0); //根节点 // GetComponent().sprite = sp; } public APatch GetData() { return _aPatch; } //放到最终位置 public void PositionedFinal(bool hasScaleAnim) { isMatch = true; if (_aPatch.IsLine()) { this.transform.SetParent(_uiGameView.puzzleBaseImgLines); }else { this.transform.SetParent(_uiGameView.puzzleBaseImg); } imgBody.transform.localScale = Vector3.one; transform.localPosition = _targetPosConverted; if (_aPatch.tag != "role" && hasScaleAnim) { Sequence mySequence = DOTween.Sequence(); mySequence.Append(transform.DOScale(new Vector3(1.1f, 1.1f, 1.1f), 0.1f)); mySequence.Append(transform.DOScale(new Vector3(1.0f, 1.0f, 1.0f), 0.1f)); } if (_aPatch.tag != "line") { _uiGameView.AddCompletePatche(this); } _uiGameView.SortPatched(); //移除对应的描线 _uiGameView.RemoveLine(_aPatch); } public Vector3 GetConvertedTargetPos() { return _targetPosConverted; } void Update() { CheckComplete(false); } private bool CheckDrag(PointerEventData eventData, bool isBegan) { bool draged = false; if (!isMatch) { _uiGameView.StopTips(); if (Math.Abs(eventData.delta.y) - Math.Abs(eventData.delta.x) > 0 && eventData.position.y - eventData.pressPosition.y > 25) { originalDataOrder = _uiGameView.OriginPatchObjs.IndexOf(gameObject); if (originalDataOrder == -1) { return false; } state = PatchStatus.Dragging; RectTransform rt = _uiGameView.puzzleBaseImg.gameObject.GetComponent(); Vector2 localPos = Utility.ScreenPointToUILocalPoint(rt, Input.mousePosition); originalOrder = this.transform.GetSiblingIndex(); transform.SetParent(_uiGameView.puzzleWhole); _uiGameView.OriginPatchObjs.RemoveAt(originalDataOrder); gameObject.transform.localPosition = new Vector3(localPos.x, localPos.y + _sizeDelta.y/2 + GameDefine.Game.FINGER_OFFSET, 0); Vector3 globalPos = transform.position; _touchOriginPos = localPos; imgBody.transform.DOScale(1, _moveTime); _uiGameView.SortPatches(true, null, false); draged = true; transform.DOKill(true); //DOKill(true)调用complete时会设置DOLocalMove的最终位置,这里设置一下全局位置,避免位置闪一下的情况 transform.position = globalPos; } else if (isBegan) { _uiGameView.patchesScrollView.gameObject.GetComponent().OnBeginDrag(eventData); } } return draged; } public void OnBeginDrag(PointerEventData eventData) { CheckDrag(eventData, true); } public void OnDrag(PointerEventData eventData) { if (!isMatch) { if (state == PatchStatus.Dragging) { RectTransform rt = _uiGameView.puzzleBaseImg.gameObject.GetComponent(); Vector2 localPos = Utility.ScreenPointToUILocalPoint(rt, Input.mousePosition); float dx = (localPos.x - _touchOriginPos.x) * dragDXScale; float dy = (localPos.y - _touchOriginPos.y) * dragDYScale; gameObject.transform.localPosition = new Vector3(_touchOriginPos.x + dx, _touchOriginPos.y + dy + _sizeDelta.y/2 + GameDefine.Game.FINGER_OFFSET, 0); } if (state == PatchStatus.None) { bool draged = CheckDrag(eventData, false); if (!draged) { _uiGameView.patchesScrollView.gameObject.GetComponent().OnDrag(eventData); } // Log.I($"OnDrag {eventData.delta}"); } } } public void OnEndDrag(PointerEventData eventData) { if (!isMatch) { if (state == PatchStatus.Dragging) { CheckComplete(true); _uiGameView.SortPatches(true, null, false); }else { _uiGameView.patchesScrollView.gameObject.GetComponent().OnEndDrag(eventData); } } else { _uiGameView.ResizePatchesPool(); _uiGameView.patchesScrollView.gameObject.GetComponent().OnEndDrag(eventData); } } public void CheckComplete(bool endDrag) { if (!isMatch) { if (state == PatchStatus.Dragging) { RectTransform rt = _uiGameView.puzzleBaseImg.gameObject.GetComponent(); Vector2 uiPos = transform.localPosition;//new Vector2(.x + rt.sizeDelta.x/2, transform.localPosition.y + rt.sizeDelta.y/2);//Utility.ScreenPointToUILocalPoint(rt, transform.localPosition); if (GameManager.Instance.CanDragging() && _aPatch.stage == GameManager.Instance.GetModel().GetCurrentStage() && Mathf.Abs(uiPos.x - _targetPosConverted.x) < threshold && Mathf.Abs(uiPos.y - _targetPosConverted.y) < threshold) { PositionedFinal(true); state = PatchStatus.ShowEffect; int stepTmp = GameManager.Instance.AddScore(_aPatch); EventManager.Dispatch("MATCH_ITEM_SUCCESS"); // AudioManager.Instance.PlaySoundEffect(SoundType.Put); //提前判断当前stage是否完成 bool stageComplete = GameManager.Instance.IsCompleteStage(); //提前判断关卡是否完成 bool levelComplete = GameManager.Instance.GetModel().IsCompleteByPatch(); if (stageComplete && !levelComplete) { EventManager.Dispatch("MATCH_STAGE_SUCCESS"); } ShowEffect(true,false,delegate() { GameManager.Instance.CheckNextLevel(stepTmp); }); }else { if (endDrag) { imgBody.transform.DOScale(_scale, _moveTime); gameObject.transform.SetParent(_uiGameView.patchesPool.transform); gameObject.transform.SetSiblingIndex(originalOrder); if (originalDataOrder > _uiGameView.OriginPatchObjs.Count) { originalDataOrder = _uiGameView.OriginPatchObjs.Count; } _uiGameView.OriginPatchObjs.Insert(originalDataOrder, gameObject); state = PatchStatus.None; } } } } } public int GetOrder() { int order = 0; switch (_aPatch.tag) { case "line": order = 10000; break; case "base": order = 0; break; case "role": int currStage = GameManager.Instance.GetModel().GetCurrentStage(); order = currStage * 100 + _aPatch.sub_stage; break; default: order = _aPatch.stage * 100 + _aPatch.sub_stage; break; } return order; } public IEnumerator EffecTimer(bool isRecover, Action onCallback = null, float scale = 1f) { float tnthresholdMax = (_aPatch.IsPatch() && !isRecover) ? 120f : 100f; float tnthresholdMin = -20f; tnthreshold = _isShow ? tnthresholdMax : tnthresholdMin; while (true) { if (_mat == null) { break; } _mat.SetFloat("_Threshold", tnthreshold % 120 / 100); if (_isShow) { tnthreshold = tnthreshold - step * scale; }else { tnthreshold = tnthreshold + step * scale; } if ((_isShow && tnthreshold < tnthresholdMin) || (!_isShow && tnthreshold >= 100)) { Image bodyImg = imgBody.GetComponent(); if (bodyImg) { bodyImg.material = null; } DestroyMat(); state = PatchStatus.Matched; break; } yield return null; } onCallback?.Invoke(); } public void SetState(PatchStatus ps) { state = ps; } public void ShowEffect(bool isShow = true, bool isRecover = false, Action onCallback = null, float scale = 1f, Action callback = null) { _isShow = isShow; //暂时回滚 ShowFadeInner(isShow, isRecover, () => { state = PatchStatus.Matched; onCallback?.Invoke(); callback?.Invoke(); }); // if (true) // { // DestroyMat(); // _mat = new Material(Shader.Find("UI/UI_dissWithAlpha")); // _mat.SetTexture("_NoiseTex", _uiGameView.noiseTexture); // imgBody.GetComponent().material = _mat; // // if (_effectTimerCoroutine != null) // { // StopCoroutine(_effectTimerCoroutine); // _effectTimerCoroutine = null; // } // // _effectTimerCoroutine = StartCoroutine(EffecTimer(isRecover, delegate // { // onCallback?.Invoke(); // callback?.Invoke(); // }, scale)); // } } private void DestroyMat() { if (_mat != null) { Destroy(_mat); _mat = null; } } public void ShowFade(bool isShow = true, bool isRecover = false, Action callback = null) { ShowFadeInner(isShow, isRecover, null, callback); } public void ShowFadeInner(bool isShow = true, bool isRecover = false, Action onCallback = null, Action callback = null) { Image img = imgBody.GetComponent(); img.color = new Color(img.color.r, img.color.g, img.color.b, isShow ? 0 : 1); img.DOFade(isShow ? 1f : 0, 0.75f).OnComplete(() => { onCallback?.Invoke(); callback?.Invoke(); }); } public void Dispose() { DestroyMat(); } } }