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();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|