類似的規則很多,左右轉的差異也不一定是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