Unity-卡片迴圈滾動

develop true發表於2020-11-13

在這裡插入圖片描述

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using DG.Tweening;
using System;

enum FINGER { FINGER_STATE_NUL, FINGER_STATE_TOUCH, FINGER_STATE_ADD }
public class CardMove : MonoBehaviour
{

    private GameObject[] sprites;
    private int halfSize;
    Vector2 screenCenterPos;
    public float startAngle = -90;//中間卡牌的角度
    float deltaAngle = 20;//相鄰卡牌的角度差值
                          /* public float moveSpeed;//移動動畫的速度*/
    public string currentSelectName;
    public Vector2 center;//橢圓中心點
    public float Y_axis = 400;//long axis
    public float X_axis = 100;//short axis
    private int cardcount;//卡牌數量

    private float fingerActionSensitivity = Screen.width * 0.05f; //手指動作的敏感度,這裡設定為 二十分之一的螢幕寬度.

    private float fingerBeginX;
    private float fingerBeginY;
    private float fingerCurrentX;
    private float fingerCurrentY;
    private float fingerSegmentX;
    private float fingerSegmentY;
    private FINGER fingerTouchState;
    float angle;
    public float mouseSpeed = 1;
    public Action MoveEndAction;
   
    void Start()
    {
       
        deltaAngle = Screen.width / 100f;
        Y_axis = Screen.width / 2;
     
        UpdateChild();
    }

    /// <summary>
    /// 初始化卡牌顯示位置
    /// </summary>
    void InitSprites()
    {
        screenCenterPos = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
        cardcount = transform.childCount;
        halfSize = (cardcount - 1) / 2;
        sprites = new GameObject[cardcount];
        for (int i = 0; i < cardcount; i++)
        {
            sprites[i] = transform.GetChild(i).gameObject;
            SetPosition(i, false);
            SetDeeps(i);
        }

    }
    /// <summary>
    /// 橢圓的半長軸為A,半短軸為B,計算橢圓上一點的位置
    /// x=A*cos(angle),y=B*sin(angle)
    /// </summary>
    /// <param name="index">Index.</param>
    /// <param name="userTweener">是否使用tween動畫.</param>
    void SetPosition(int index, bool userTweener = true)
    {
        //計算每一張卡片在橢圓上相對中間卡牌的角度
        angle = 0;


        if (index < halfSize)
        {//left
            angle = startAngle - (halfSize - index) * deltaAngle;
            sprites[index].GetComponent<RectTransform>().DOScale(1f, 0.3f);
        }
        else if (index > halfSize)
        {//right

            angle = startAngle + (index - halfSize) * deltaAngle;
            sprites[index].GetComponent<RectTransform>().DOScale(1f, 0.3f);
        }
        else
        {//medim
            angle = startAngle;
            sprites[index].GetComponent<RectTransform>().DOScale(1.5f, 0.3f).OnComplete(MoveEnd);

        }

        //通過卡牌的角度,計算對應的位置
        float xpos = Y_axis * Mathf.Cos((angle / 180) * Mathf.PI) + center.x;
        float ypos = X_axis * Mathf.Sin((angle / 180) * Mathf.PI) + center.y;

        Vector2 pos = new Vector2(xpos, ypos);
        // Vector2 pos = new Vector2(center.x, center.y);
        if (!userTweener)
        {
            sprites[index].GetComponent<RectTransform>().DOMove(new Vector2(screenCenterPos.x + pos.x, screenCenterPos.y + pos.y), 0f);
        }
        else
            sprites[index].GetComponent<RectTransform>().DOMove(new Vector2(screenCenterPos.x + pos.x, screenCenterPos.y + pos.y), 0.2f);


    }
    /// <summary>
    /// 選擇移動動畫結束後的設定當前選擇的名字和回撥
    /// </summary>
    void MoveEnd()
    {
        currentSelectName = transform.GetChild(transform.childCount - 1).name;
        if (MoveEndAction != null) MoveEndAction();

    }

    /// <summary>
    /// 計算每一張卡片的層級
    /// </summary>
    /// <param name="index">Index.</param>
    void SetDeeps(int index)
    {
        int deep = 0;
        if (index < halfSize)
        {//左側卡牌層級,從左側到中間,層級依此遞增
            deep = index;
        }
        else if (deep > halfSize)
        {//右側卡牌層級,從中間到右側,層級依此遞減
            deep = sprites.Length - (index + 1);
        }
        else
        {
            deep = halfSize;
        }
        sprites[index].GetComponent<RectTransform>().SetSiblingIndex(deep);
    }
    public void LeftMove()
    {
        int length = sprites.Length;

        GameObject temp = sprites[0];
        for (int i = 0; i < length; i++)
        {//移動卡片在陣列中的位置,依此向前移動一位
            if (i == length - 1)
                sprites[i] = temp;
            else
                sprites[i] = sprites[i + 1];

        }

        for (int i = 0; i < length; i++)
        {//更新陣列卡片需要顯示的位置和層級
            if (i < length - 1) SetPosition(i);
            else SetPosition(i, false);
            SetDeeps(i);



        }
    }
    public void RightMove()
    {
        int length = sprites.Length;
        GameObject temp = sprites[length - 1];
        for (int i = length - 1; i >= 0; i--)
        {
            if (i == 0)
                sprites[i] = temp;
            else
                sprites[i] = sprites[i - 1];
        }
        for (int i = 0; i < length; i++)
        {
            if (i == 0) SetPosition(i, false);
            else SetPosition(i);
            SetDeeps(i);
        }
    }
    private void Update()
    {
        CheckMouse();
    }
    private void AddFingerAction()
    {
        fingerTouchState = FINGER.FINGER_STATE_ADD;
        if (Mathf.Abs(fingerSegmentX) > Mathf.Abs(fingerSegmentY))
        {
            fingerSegmentY = 0;
        }
        else
        {
            fingerSegmentX = 0;
        }

        if (fingerSegmentY == 0)
        {
            if (fingerSegmentX > 0)
            {
                RightMove();
            }
            else
            {
                LeftMove();
            }
        }

    }

    readonly string MYMouseScrollWheel = "Mouse ScrollWheel";
    float timer, axis;//timer可以防止快速滾輪導致速度過快動畫得bug
    void CheckMouse()
    {

        switch (fingerTouchState)
        {
            case FINGER.FINGER_STATE_NUL:
                if (Input.GetKeyDown(KeyCode.Mouse0))
                {
                    fingerTouchState = FINGER.FINGER_STATE_TOUCH;
                    fingerBeginX = Input.mousePosition.x;
                    fingerBeginY = Input.mousePosition.y;
                }
                break;
            case FINGER.FINGER_STATE_TOUCH:
                fingerCurrentX = Input.mousePosition.x;
                fingerCurrentY = Input.mousePosition.y;
                fingerSegmentX = fingerCurrentX - fingerBeginX;
                fingerSegmentY = fingerCurrentY - fingerBeginY;

                float fingerDistance = fingerSegmentX * fingerSegmentX + fingerSegmentY * fingerSegmentY;

                if (fingerDistance > (fingerActionSensitivity * fingerActionSensitivity))
                {
                    AddFingerAction();
                }
                break;
            case FINGER.FINGER_STATE_ADD:
                break;
        }
        if (Input.GetKeyUp(KeyCode.Mouse0))
        {
            fingerTouchState = FINGER.FINGER_STATE_NUL;
        }
        timer += Time.deltaTime;

        axis = Input.GetAxis(MYMouseScrollWheel);
        if (axis > 0 && timer > 0.2f)
        {
            timer = 0;
            LeftMove();
        }
        else if (axis < 0 && timer > 0.2f)
        {
            timer = 0;
            RightMove();
        }

    }
    void InitData()
    {
        fingerActionSensitivity = Screen.width * 0.05f;
        fingerBeginX = 0;
        fingerBeginY = 0;
        fingerCurrentX = 0;
        fingerCurrentY = 0;
        fingerSegmentX = 0;
        fingerSegmentY = 0;
    }


    public void UpdateChild()
    {
        InitSprites();
        InitData();

    }
}

相關文章