unity_art_puzzle_playable_luna/APPlayableLuna/Assets/Scripts/Patche.cs

431 lines
16 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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