我想先從簡單又算經典的九宮格總和15來做,機制很容易懂,就是九宮格的三個橫向、三個直向以及交叉對角線的總和都是15,記得第一次玩到這個的時候感覺有點難,不過在了解了以後其實是滿容易的,雖然版面排列不只一種,但是基本上都差不多就是了。
製作使用的Unity版本為5.2.2f1。
實作測試 (WebGL build,似乎會花點時間載入),用滑鼠拖拉數字方塊至九宮格上,直到各行列跟交叉線的總和都是15便完成遊戲
1、製作數字格子。
首先製作9個數字方塊物件,這邊用空白方塊圖片拉9個到場景中,這樣就有9個方塊Sprite物件,接著在每個方塊下放一個數字,這個數字當然就是1到9。
每個物件都加上一個Box Collider 2D的Component,因為之後要來使用內建的OnMouseDown()、OnMouseUp()來做簡易的拖拉擺放。
接著在每個物件上再加上一個自己做的Component,用來記錄這個格子代表的數字,以及拖曳的運作。
public class Unit : MonoBehaviour { public int number; //這個方塊代表的數字 private Vector3 startPosition; //紀錄起始位置 private bool isDrag; //是否拖曳中 void Start () { //紀錄方塊在開始時的位置,之後可以讓方塊回到這裡 startPosition = this.transform.position; } void Update () { //如果這個方塊在拖曳中,就讓它一直跟隨滑鼠 if (isDrag) { Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); //把滑鼠座標轉換為場景座標 this.transform.position = mousePos; } } //當滑鼠按下的時候 void OnMouseDown() { StopAllCoroutines(); //停止移動的Coroutine isDrag = true; //此物件拖曳中 //因為只有簡單一個機制,所以直接用Singleton來呼叫 Board.GetInstance().RemoveUnit(this); //嘗試移除板子上的這個物件,如果板子上沒有這個物件就忽略 } //當滑鼠放開 void OnMouseUp() { isDrag = false; //取消拖曳 //檢查放開的瞬間是否放在板子上 bool isOnBoard = false; RaycastHit2D[] hits = Physics2D.RaycastAll(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero); foreach (RaycastHit2D hit in hits) { //用Raycast的方式來檢查所有的Collider,只取Tag是Board的物件 if (hit.transform.tag == "Board") { //如果放開的時候滑鼠位置有碰到板子,就放到板子上 Board.GetInstance().AddUnit(this, hit.transform.gameObject); //同樣用Singleton方式呼叫 StartCoroutine("ReturnPosition", hit.transform.position); //把數字格子移動到板子格子的位置 isOnBoard = true; } } //如果滑鼠座標沒有接觸到板子,就送回起始位置 if(!isOnBoard) StartCoroutine("ReturnPosition", startPosition); } //簡單的移動位置方法 IEnumerator ReturnPosition(Vector3 pos) { Vector3 target = new Vector3(pos.x, pos.y, this.transform.position.z); while (true) { this.transform.position = Vector3.MoveTowards(this.transform.position, target, 10f * Time.deltaTime); if (this.transform.position == target) break; yield return null; } } //讓方塊移動回起始位置 public void ReturnStartPosition() { StopAllCoroutines(); StartCoroutine("ReturnPosition", startPosition); } }
2、製作九宮格板子。
數字方塊到這邊就簡單的做完了,接下來要製作九宮格版面的部分。
同樣使用空白方塊圖片拉9個Sprite物件到場景中,我這邊依照鍵盤的數字鍵來排列並且命名物件,同樣每個物件上都加上一個Box Collider 2D,到時候判斷滑鼠位置。這邊特別設定每個格子物件的Tag為Board,到時候用來判斷滑鼠座標的Raycast碰到的Collider是不是這個。
把所有方格都放到一個空白的Board之下,簡單做個整理,之後要整組調整位置也方便。接著這個Board物件上放上一個自己做的Component,算是做為整個遊戲的主要運作中心。
public class Board : MonoBehaviour { public GameObject[] positionObj; //九宮格板子的格子物件 private Unit[] unitArr; //數字格子物件陣列 private static Board instance; public static Board GetInstance() { if (instance == null) { instance = GameObject.FindObjectOfType<board>(); if (instance == null) instance = new GameObject().AddComponent<board>(); } return instance; } void Start () { unitArr = new Unit[9]; ReCalculate(); } //增加一個Unit物件到板子上,用板子格子的物件來判斷位置 public void AddUnit(Unit unit, GameObject boardObj) { int index = -1; //尋找板子格子 for (int i = 0; i < positionObj.Length; ++i) { if (boardObj == positionObj[i]) index = i; } if (index == -1) { //沒有這個位置物件,把Unit送回起始點 unit.ReturnStartPosition(); } else { //有這個位置物件,這個位置上已經有一個Unit了 if (unitArr[index] != null) { if (unitArr[index] != unit) { //把舊的Unit送回起始點,並把新的放上去 unitArr[index].ReturnStartPosition(); unitArr[index] = unit; } } else { //有這個位置物件,這個位置上是空的,直接把Unit設定上去 unitArr[index] = unit; } } ReCalculate(); //重新計算各行列總和 } //從板子上移除Unit物件 public void RemoveUnit(Unit unit) { for (int i = 0; i < unitArr.Length; ++i) { if (unit != null && unitArr[i] != null && unitArr[i].Equals(unit)) unitArr[i] = null; } ReCalculate(); //重新計算各行列總和 } //簡單計算行列總和 private void ReCalculate() { int n1 = (unitArr[0] == null) ? 0 : unitArr[0].number; int n2 = (unitArr[1] == null) ? 0 : unitArr[1].number; int n3 = (unitArr[2] == null) ? 0 : unitArr[2].number; int n4 = (unitArr[3] == null) ? 0 : unitArr[3].number; int n5 = (unitArr[4] == null) ? 0 : unitArr[4].number; int n6 = (unitArr[5] == null) ? 0 : unitArr[5].number; int n7 = (unitArr[6] == null) ? 0 : unitArr[6].number; int n8 = (unitArr[7] == null) ? 0 : unitArr[7].number; int n9 = (unitArr[8] == null) ? 0 : unitArr[8].number; //三個直的,三個橫的,加上交叉,總共有8個數值 int[] result = new int[8]; result[0] = n7 + n8 + n9; result[1] = n4 + n5 + n6; result[2] = n1 + n2 + n3; result[3] = n3 + n5 + n7; result[4] = n3 + n6 + n9; result[5] = n2 + n5 + n8; result[6] = n1 + n4 + n7; result[7] = n1 + n5 + n9; //判斷是否遊戲結束,只有其中一個不是15就不算完成遊戲 bool isGameOver = true; for (int i = 0; i < result.Length; ++i) { if (result[i] != 15) isGameOver = false; } if (isGameOver) { //顯示遊戲結束畫面 Debug.Log("Game Over"); } } }
完成了這個Component並且把它掛在Board物件上之後,在Inspector面板中把九宮格的格子依序放到PositionObj裡面,同時調整Z軸,稍稍往後移一點點,避免九宮格的Collider跟Unit物件重疊,因為Unit物件並不是用Raycast的方式判斷點擊,所以Collider重疊就會影響OnMouseDown的運作。
3、完成
到這邊遊戲的機制就算完成了,當然還有介面的製作、數字總和的顯示,不過這部分就要看自己的需求去製作了。
或許有些部分不是最好的方式,拖曳跟擺放的判斷當然也有其他的方式,不過這邊主要的目的在於簡單(偷懶)製作,同時利用Unity的功能來完成,希望是有達到這個目標就是了,如果有錯誤的話請告訴我。
No comments:
Post a Comment