通常在旋轉的階段是非常簡單的,只要照著順序轉就好,因此遊戲通常會把密碼順序的提示給放在不同的地方,玩家需要拼湊出密碼的組合之後才能解開這個鎖,而尋找提示的過程又可以加入其他不同類型的謎題來增加阻礙。
製作使用的Unity版本為5.4.1 f1。
實作測試(WebGL build) (這邊簡化遊戲,一開始就會把密碼的組合顯示在畫面上,依據L或R,來把轉盤往左或往右旋轉),滑鼠點住轉盤不放就可以開始旋轉,這邊因為用亂數決定的關係,所以有可能會遇到連續兩次都同方向同數值,就要往那個方向旋轉一圈再到同數值才行。
1、轉盤
先製作一個金庫轉盤的圖片,這邊我直接從網路上擷取一張圖片來用,直接把轉盤放在場景上,建立一個空的物件來裝轉盤跟指標,這邊指標判斷的位置是在12點鐘的方向,所以在那邊加了一條紅色的線。
接著來製作一個放在轉盤上的Component,這個Component用來判斷滑鼠是不是點到轉盤上(所以給這個class加上RequireComponent[typeof(CircleCollider2D)]的屬性),同時計算轉盤旋轉的角度,以及當滑鼠放開的時候告訴Board現在轉盤往哪個方向轉到多少刻度。
[RequireComponent(typeof(CircleCollider2D))] //因為轉盤是圓形的且需要判斷滑鼠的點擊,所以這邊加上一個Require public class SafeDial : MonoBehaviour { public System.ActiondialInput; //做個簡單的轉盤輸入的delegate //每個區塊的夾角,這邊圖片的小刻度不看只使用上面的10個數字(所以360 / 10 = 36) //除非轉盤的數字數量會變動,因為這邊是固定的所以就就直接用了 private int blockAngles = 36; private float totalRotate; //轉盤旋轉時總共轉的角度 void OnMouseDown() { StartCoroutine(RotatingDial()); } void OnMouseUp() { StopAllCoroutines(); //滑鼠放開,檢查轉盤現在的角度,讓它往最接近的刻度移動 int num = Mathf.RoundToInt(this.transform.localEulerAngles.z / blockAngles); Vector3 rotation = this.transform.localEulerAngles; rotation.z = num * blockAngles; float roundAngle = this.transform.localEulerAngles.z - rotation.z; this.transform.localEulerAngles = rotation; totalRotate = Mathf.RoundToInt(totalRotate + roundAngle); if (totalRotate == 0) //總旋轉的角度是0,沒有移動 return; if(totalRotate > 360 || totalRotate < -360) { //轉超過一圈,看是照樣接受或是就當作本次不算,這邊就忽略 } else { //把旋轉的方向跟刻度轉成字串送出 dialInput.Invoke(((totalRotate > 0) ? "R" : "L") + Mathf.Abs((num % 10) * 10).ToString()); } } private IEnumerator RotatingDial() { float preAngle = this.transform.localEulerAngles.z; Vector3 preMousePos = Input.mousePosition; totalRotate = 0; while (true) { //基本三角點 Vector2 dialWorldPos = new Vector2(this.transform.position.x, this.transform.position.y); Vector2 mouseInitWorldPos = Camera.main.ScreenToWorldPoint(preMousePos); Vector2 mouseCurrWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); //計算前一tick跟此tick滑鼠位置的夾角 float angle = Vector2.Angle(mouseInitWorldPos - dialWorldPos, mouseCurrWorldPos - dialWorldPos); Vector3 cross = Vector3.Cross(mouseInitWorldPos - dialWorldPos, mouseCurrWorldPos - dialWorldPos); if (cross.z > 0) angle = -angle; this.transform.localEulerAngles = new Vector3(0, 0, preAngle - angle); //調整圖片新的角度 totalRotate += angle; //累積總旋轉的角度 preMousePos = Input.mousePosition; //重設滑鼠位置紀錄 preAngle = this.transform.localEulerAngles.z; //重設角度紀錄 yield return null; } } }
這樣子這個Component就做完了,這邊暫時不需要放到物件上,因為我在Board初始化的時候會Add上去,那如果要預先手動把這個Component放到轉盤物件上的話,Board那邊的AddComponent就可以改掉,改為GetComponent。
2、板子
開始來製作板子Component,主要遊戲的初始化,跟遊戲是否結束的判斷都在這邊運作,轉盤的輸入這邊我們就視它為一個連續數據,只看最後輸入的四次,來跟設定的密碼做比對。
public class Board : MonoBehaviour { public GameObject dial; //轉盤物件 public int passLength = 4; //密碼長度(轉動的次數) private string passCombination; //正確密碼組合的字串 private string[] inputValues; //密碼盤輸入的紀錄 private int inputIndex; void Start() { SafeDial safeDial = dial.AddComponent<SafeDial>(); //加上給轉盤用的Component safeDial.dialInput = DialInput; //設定回呼的委派 InitGame(); } //初始化遊戲所需的參數 public void InitGame() { dial.GetComponent<CircleCollider2D>().enabled = true; //如果有重新遊戲的需求,在呼叫的時候啟動,避免因為遊戲結束時的關閉造成無法開下一場 inputIndex = 0; inputValues = new string[passLength]; passCombination = string.Empty; for (int i = 0; i < passLength; ++i) { //+往右轉 -往左轉 //這邊是隨機決定左右,有可能出現都是左或都是右的情況,也可以改為不會有連續兩個同方向的 int direction = (1 - (Random.Range(0, 2) * 2)); int passValue = Random.Range(0, 10); digiTexts[i].text = (direction > 0 ? "R" : "L") + (passValue * 10).ToString(); passCombination += (direction > 0 ? "R" : "L") + (passValue * 10).ToString(); } } //轉盤輸入的數值,用string[]記錄下來每次的輸入 private void DialInput(string value) { inputValues[inputIndex] = value; string result = ""; for(int i = 0; i < passLength; ++i) { int index = (inputIndex + 1 + i) % passLength; result += inputValues[index]; } inputIndex = (inputIndex + 1 + passLength) % passLength; //判斷答案是否正確,只要最後輸入4次的數值跟密碼相同,就遊戲結束 if (result.Equals(passCombination)) { Debug.Log("Game Over"); //停止Collider避免讓滑鼠還可以點 dial.GetComponent<CircleCollider2D>().enabled = false; } } }
3、設定
這邊在剛剛轉盤跟線段的父物件上掛上這個Board component,然後把轉盤的Sprite拉進去,設定好密碼長度,這邊用4段。
基本上就完成了,不過這邊是看不到密碼的,所以可以把Board物件裡面的passCombination取出來用,不過這邊是一整串的並不好做為顯示,或是額外用個陣列來記錄,然後可以讓別的地方來讀取這個資訊,不然的話密碼沒有任何的提示這樣遊戲也沒辦法玩了。
正常來說應該是每次轉的方向會跟前一次相反,如果以四次來說就是左右左右或右左右左,不過這邊不是真實的轉盤同時也只是測試而已,所以密碼方向跟刻度就用隨機組合了。就如同一開始說的,通常到了轉的時候就是很單純的轉動到特定刻度而已,所以有可能是把密碼的提示藏到別的地方,也有可能提示明顯但是有編碼過,玩家要經過解碼才知道正確的答案,當然還有更多增加麻煩的方式就是了。
如果有任何錯誤歡迎提出。
No comments:
Post a Comment