2016年8月3日 星期三

【Unity】轉珠系統製作Part.2 - 珠子相連判斷

Part.1    Part.3

在上一篇我們生成了盤面上的珠子,並且隨機給了珠子屬性,接著我們需要把同屬性且相連的珠子分成同群組,方便日後計算combo,下圖是這次的目標。
將同屬性相連的珠子分成同一個群組,並且附上編號。

首先要對Orb與PuzzleSystem腳本追加變數。
Orb腳本新增的變數。
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
public class Orb : MonoBehaviour
{
    .
    .
    .
    public List<Orb> linkOrbs = new List<Orb>();
    public bool group = false;
    public Text groupNum;
    void Start()
    {
        .
        .
        .
    }
} 
linkOrbs用來儲存與自己相鄰珠子的Orb腳本,也就是上下左右的珠子,如下圖。
group是用來判斷該珠子是否已經被分配群組。
groupNum會顯示編號,使用Text物件
Text新增在珠子預設物件下,滑鼠拖曳帶入,Text字體大小、顏色容易辨識就好。

在PuzzleSystem腳本中新增變數與設定變數。
using UnityEngine;
using System.Collections.Generic;
public class PuzzleSystem : MonoBehaviour
{
    .
    .
    .
    public List<Orb> orbs = new List<Orb>();////(1)
    public List<List<Orb>> orbGroups = new List<List<Orb>>();
    void Start()
    {
        InitGrid();
    }
    void InitGrid()
    {
        .
        .
        .
        for (int r = 0; r < rowCount; r++)
        {
            for (int c = 0; c < columnCount; c++)
            {
                .
                .
                .
                orbs.Add(orb);////(2)
            }
        }
        for(int index = 0; index < orbs.Count; index++)////(3)
        {
            if (orbs[index].column != columnCount - 1)////(4)
                orbs[index].linkOrbs.Add(orbs[index + 1]);
            if(orbs[index].row != rowCount - 1)
                orbs[index].linkOrbs.Add(orbs[index + columnCount]);
            if (orbs[index].column != 0)
                orbs[index].linkOrbs.Add(orbs[index - 1]);
            if (orbs[index].row != 0)
                orbs[index].linkOrbs.Add(orbs[index - columnCount]);
        }
    }
    .
    .
    .
}
(1)PuzzleSystem中要新增兩個List,orbs一維List會儲存盤面中所有珠子的Orb腳本。
orbGroups二維陣列會儲存珠子的群組。
(2)在產生盤面的迴圈中,把當前的珠子腳本新增到orbs一維List中。
(3)最後在InitGrid函式結束前,設定珠子腳本下的linkOrbs,依序為右、上、左、下的珠子。
(4)透過if判斷排除四邊與角落的連結,例如最下一列的珠子不會有下面珠子的連結,最右一行不會有右邊珠子的連結。

做好上面的前置動作後,可以開始把珠子分群組。
在PuzzleSystem腳本中宣告分群函式。

using UnityEngine;
using System.Collections.Generic;
public class PuzzleSystem : MonoBehaviour
{
    .
    .
    .
    public List<Orb> orbs = new List<Orb>();
    public List<List<Orb>> orbGroups = new List<List<Orb>>();
    void Start()
    {
        InitGrid();
        OrbGroup();
    }
    .
    .
    .
    void FindMembers(Orb orb, int groupNum) {}////(1)
    void OrbGroup()////(2)
    {
        orbGroups.Clear();
        foreach (Orb orb in orbs)////(3)
        {
            if (orb.group == false)////(4)
            {
                orbGroups.Add(new List<Orb>());////(5)
                int groupNum = orbGroups.Count - 1;////(6)
                orbGroups[groupNum].Add(orb);////(7)
                orb.group = true;////(8)
                orb.groupNum.text = (groupNum).ToString();////(9)
                FindMembers(orb, groupNum);////(10)
            }
        }
    }
}
新增函式FindMembers與OrbGroup
(1)FindMembers的參數為Orb腳本元件與整數的群組編號,至於函數中要執行的動作稍後再談。
(2)OrbGroup函式會在Start中呼叫,在InitGrid函式之後執行。
(3)使用迴圈找沒有加入群組的珠子。
(4)當orb.group == false成立,代表找到沒加入群組的珠子,執行條件式中的程式。
(5)建立新的珠子List,並新增到orbGroups中。
(6)宣告群組編號groupNum,並將數值設定為新增List的編號。
(7)將目前這顆沒有群組的珠子加入這個新增的List。
(8)將當前的珠子group設為true,表示它已經被加到某個群組中。
(9)設定Text元件的顯示文字,文字內容為群組編號
(9)呼叫FindMembers函式,帶入參數為當前的珠子和編號。

到這裡可以先執行看看。
可以看到每個珠子都被給了一個群組編號,表示群組建立是成功的,接著我們要透過FindMembers函式內容找到同群組的珠子。
void FindMembers(Orb orb, int groupNum)
{
    foreach (Orb linkOrb in orb.linkOrbs)////(1)
    {
        if (linkOrb.type == orb.type && linkOrb.group == false)////(2)
        {
            orbGroups[groupNum].Add(linkOrb);////(3)
            linkOrb.group = true;
            linkOrb.groupNum.text = groupNum.ToString();
            FindMembers(linkOrb, groupNum);////(4)
        }
    }
}
(1)進入FindMembers函式,要搜尋的是與當前珠子相連的珠子,也就是linkOrbs。
(2)當相鄰珠子類型與當前珠子屬性相同,而且相鄰珠子又沒有加入群組時。
(3)加入當前的群組、設定group值、修改Text文字。
(4)再次呼叫FindMembers,這次要找的是這個相鄰珠子的linkOrbs,直到所有相連同屬性的珠子都加入群組為止。

以下是逐步執行的結果。
以上就是珠子相連判斷的說明,接著下一步就是消除珠子,而這篇做的相連判斷在消除時,會被歸類為同combo,當然這個做法有一個超有名的邏輯錯誤─W珠,這個問題就以後再說吧。
這次就到這裡。

2016/08/06修正:
進入OrbGroup函式第一行新增了orbGroups.Clear();,因為orbGroups會在之後重複使用,所以透過Clear來初始化群組。

沒有留言:

張貼留言

【自製小遊戲】水平思考猜謎(海龜湯)

遊戲連結 海龜湯的玩法是由出題者提出一個難以理解的事件,參與猜題者可以提出任何問題以試圖縮小範圍並找出事件背後真正的原因。但出題者僅能以「是」、「不是」或「沒有關係」來回答問題。 本遊戲蒐集各種論壇、平台的42個題目,提供給想玩海龜湯卻愁找不到題目的你們。 ...