431 lines
16 KiB
C#
431 lines
16 KiB
C#
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<RectTransform>().sizeDelta = new Vector2(300, 148);
|
||
Image img = imgBody.GetComponent<Image>();
|
||
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<Image>();
|
||
Sprite sp = Resources.Load<Sprite>(imgPath);
|
||
img.sprite = sp;
|
||
img.SetNativeSize();
|
||
|
||
_sizeDelta = imgBody.GetComponent<RectTransform>().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<RectTransform>();
|
||
//节点坐标
|
||
_targetPosConverted = new Vector3(_targetPos.x - rt.sizeDelta.x/2, _targetPos.y - rt.sizeDelta.y/2, 0);
|
||
|
||
//根节点
|
||
// GetComponent<Image>().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<RectTransform>();
|
||
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<ScrollRect>().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<RectTransform>();
|
||
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<ScrollRect>().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<ScrollRect>().OnEndDrag(eventData);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_uiGameView.ResizePatchesPool();
|
||
_uiGameView.patchesScrollView.gameObject.GetComponent<ScrollRect>().OnEndDrag(eventData);
|
||
}
|
||
}
|
||
|
||
public void CheckComplete(bool endDrag)
|
||
{
|
||
if (!isMatch)
|
||
{
|
||
if (state == PatchStatus.Dragging)
|
||
{
|
||
RectTransform rt = _uiGameView.puzzleBaseImg.gameObject.GetComponent<RectTransform>();
|
||
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<Image>();
|
||
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<Image>().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<Image>();
|
||
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();
|
||
}
|
||
}
|
||
} |