我想先從簡單又算經典的九宮格總和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