Unity - PuzzleGame 6 (圓餅轉盤)

  旋轉圓餅圖遊戲?!其實也就是左右旋轉時的步數或角度不同,轉過去後會切換那個區塊的開關,遊戲的目的就是要把所有圓餅的區塊都打開。

  類似的規則很多,左右轉的差異也不一定是2或3,乍看之下會容易被圓餅搞混,事實上是可以把它想像一條直線有8個格子,前進跟後退的步數不同而已。



  製作使用的Unity版本為5.4.1 f1。


  實作測試(WebGL build,網頁跑起來有時候會頓一下滿怪的)  (滑鼠點擊左右按鈕旋轉轉盤,當轉盤全部點亮就遊戲結束)




1、區塊

  先來製作一個圓餅區塊的圖片,因為等下打算做成8個開關,所以先畫一個圓形然後切成8等分,接著把圖片匯入到Unity裡面。

  接著要來編輯圖片的Pivot Point,所以打開該圖片的Sprite Editor,把這張區塊圖的Pivot Point移動到尖端再往下一點的位置,因為我想要讓等下變成圓餅圖後每個區塊之間會有一點空隙。

  調整完畢後記得Apply貯存一下。






2、圓餅

  接著用剛剛做好的區塊圖拉到場景上並且複製出8個相同的物件,每個區塊的Z軸角度稍微調整一下,因為是8等分,所以每個區塊會差異45度角。

  從這張圖片來看,1的圖Z軸是0度,然後2的圖片Z軸是-45度,3的圖片是-90度,依此類推把8張圖轉完後就可以得到一張圓餅啦,圓餅的中間就是剛剛Pivot point的位置,因為稍微外推了一點,所以這張圓餅的每個區塊之間很明顯就可以看到有空隙來區隔了。






3、板子

  開始來製作板子Component,同樣這次也是讓所有的判斷都寫在這裡,UI點擊按鈕後呼叫裡面的旋轉方法,然後去旋轉設定好的圓餅物件到正確的角度。


public class Board : MonoBehaviour
{
    public GameObject piePanel; //包含所有區塊的圓餅物件
    public float speed = 1; //圓餅旋轉的速度
    public SpriteRenderer[] pie; //圓餅區塊的每個sprite物件

    private int[] values; //每個區塊的欄位數值
    private int currentIndex = 0; //當前的指標位置
    private bool isRotating = false; //使否正在旋轉

    void Start()
    {
        StartNewGame();
    }

    public void StartNewGame()
    {
        values = new int[8]; //這邊圓餅切成8等分,所以宣告8個
        currentIndex = Random.Range(0, 8); //隨機設定當前紅色箭頭所指的指標位置
        for (int i = 0; i < values.Length; ++i)
        {
            //亂數調整該位置的開關
            values[i] = (currentIndex == i) ? 1 : 1 - (Random.Range(0, 2) * 2);
            //調整對應的圓餅圖片的明暗
            pie[i].color = (values[i] == 1) ? new Color32(255, 255, 255, 255) : new Color32(86, 86, 86, 255); //這邊設定打開的時候區塊是白色,關閉的時候是灰黑色
        }

        //依據目前的指標位置把圓餅圖的Z軸設定到正確的位置
        float initAngleZ = currentIndex * 45;
        piePanel.transform.eulerAngles = new Vector3(0, 0, initAngleZ);
    }

    //圓餅向左邊旋轉,UI製作一個Button然後把Button的OnClick新增一個事件並且呼叫這個Method,需要輸入的參數就是步數
    public void RotateLeft(int value)
    {
        if (isRotating) return;
        StartCoroutine(RotateCoroutine(value));
    }

    //圓餅向右邊旋轉,UI製作一個Button然後把Button的OnClick新增一個事件並且呼叫這個Method,需要輸入的參數就是步數
    public void RotateRight(int value)
    {
        if (isRotating) return;
        StartCoroutine(RotateCoroutine(-value));
    }

    //製作一個簡單的Coroutine來旋轉圓餅
    private IEnumerator RotateCoroutine(int value)
    {
        isRotating = true;

        float rotateZ = value * 45; //依據步數來計算總共要旋轉的角度,往右旋轉的話是負的
        float currentZ = currentIndex * 45; //依據當前的Index計算現在的角度
        float targetZ = currentZ + rotateZ; //現在的角度加上要旋轉的角度就是最終的角度
        
        while(true)
        {
            //開始依據時間計算Z的變動,同時設定調整圓餅物件的角度
            currentZ = Mathf.MoveTowards(currentZ, targetZ, 45 * speed * Time.deltaTime);
            piePanel.transform.eulerAngles = new Vector3(0, 0, currentZ);

            //當目前角度差不多接近的時候,設定一個容許的誤差值,這邊是0.1,也可以用成public就可以在inspector裡面調
            if (Mathf.Abs(targetZ - currentZ) < 0.1f)
                break;
            yield return null;
        }
        piePanel.transform.eulerAngles = new Vector3(0, 0, targetZ);

        //旋轉完畢,就需要把當前的index指標調整到正確的位置,同時切換int[]裡面數值的正負(用來代表開關)
        currentIndex = ((currentIndex + value) + 8) % 8;
        values[currentIndex] = -values[currentIndex];

        //調整對應該index的圓餅圖片的明暗
        pie[currentIndex].color = (values[currentIndex] == 1) ? new Color32(255, 255, 255, 255) : new Color32(86, 86, 86, 255);

        //檢查遊戲是否結束(全部圓餅都打開了),因為圓餅打開的數值是1,關閉的數值是-1,所以全部加總起來等於8就結束了
        int totalValue = 0;
        foreach (int val in values) totalValue += val;
        if(totalValue == values.Length)
        {
            Debug.Log("Game Over");
            //這邊製作遊戲結束的呼叫
        }

        isRotating = false;
    }
}







4、設定

  最後把Board Component放進場景中,把每個區塊的Sprite設定進去,這邊順序跟前一張圖的順序一樣,然後在12點鐘的方向加一個紅色箭頭來表示目前的指標位置。



  到此為止就結束了,接下來就是製作UI的按鈕,然後讓按鈕點下去的時候呼叫Board裡面的RotateLeft或RotateRight就好了,不過製作UI就不在這邊說明了。





  也算是滿常見的遊戲機制,我這邊的實作用了亂數開場,所以有時候可能只要轉個一兩步就結束了,有時候可能要轉個很多次才會結束,這個的話可以改寫成預先設定版面的狀態,就不會有這樣的問題了。

  如果有任何錯誤歡迎提出。

No comments:

Post a Comment