最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

HexMap學(xué)習(xí)筆記(二)——單元格顏色混合

2019-02-19 17:46 作者:皮皮關(guān)做游戲  | 我要投稿

作者:沈琰


前言

這里是HexMap系列教程的第二篇翻譯,難度與上一篇相當(dāng)。

本篇主要內(nèi)容是對(duì)單元格邊界做一個(gè)顏色混合,用到了更為細(xì)致的三角剖分方式和一般很少用到的頂點(diǎn)顏色的應(yīng)用。

本篇原文地址:https://catlikecoding.com/unity/tutorials/hex-map/part-2/


本篇難度:★☆☆☆☆

單元格顏色混合

此教程是六邊形地圖的第二部分,上一篇教程中我們構(gòu)建了六邊形網(wǎng)格的基本結(jié)構(gòu)并實(shí)現(xiàn)了編輯單元格顏色的功能。現(xiàn)在每個(gè)單元格都是一個(gè)單色,在單元格之間的顏色轉(zhuǎn)換顯得很突兀。這次我們將引入一個(gè)過(guò)渡區(qū)域,讓相鄰單元格之間的顏色進(jìn)行混合。

類(lèi)似擦除顏料留下的污漬一般的單元格顏色過(guò)渡

1.相鄰單元格

在混合顏色之前,首先得知道哪些單元格是彼此相鄰的。每個(gè)單元格都有六個(gè)可以通過(guò)方向識(shí)別的相鄰單元格。這些方向分別是東北(NE)、東( E )、東南(SE)、西南(SW)、西(W)、西北(NW)。為此新建一個(gè)枚舉類(lèi)型放入腳本文件中。

什么是枚舉?
使用enum關(guān)鍵字來(lái)定義枚舉類(lèi)型,是有名字的有序列表。這種類(lèi)型的變量可以使用這些名稱中的一個(gè)作為它的值,每個(gè)名稱都對(duì)應(yīng)一個(gè)數(shù)字,默認(rèn)情況下從0開(kāi)始。當(dāng)你需要有限長(zhǎng)度的可命名有序列表時(shí),這些非常有用。
實(shí)際上枚舉就是簡(jiǎn)單的整數(shù)。你可以對(duì)它們進(jìn)行加、減操作,轉(zhuǎn)換成整數(shù)再轉(zhuǎn)回來(lái)。同樣也可以轉(zhuǎn)換成少數(shù)其他類(lèi)型,但整數(shù)是其基本類(lèi)型。
六個(gè)相鄰單元格,六個(gè)方向

在HexCell中添加一個(gè)數(shù)組來(lái)儲(chǔ)存相鄰單元格。雖然能設(shè)置其為公共字段,但基于為后面考慮還是設(shè)置為私有,并用一個(gè)方法為其提供方向參數(shù)來(lái)獲取它們。確保數(shù)組字段為序列化的以便能在代碼編譯后能顯示出來(lái)。

需要去儲(chǔ)存相鄰單元格的引用么?
我們也能通過(guò)坐標(biāo)去確認(rèn)并獲取相鄰單元格。但直接儲(chǔ)存引用關(guān)系更直接和方便一些,所以就這么做。

相鄰單元格的數(shù)組顯示在了腳本的檢視面板上。因?yàn)槊總€(gè)單元格可以有6個(gè)相鄰單元格,就把HexCell預(yù)制體上數(shù)組默認(rèn)長(zhǎng)度設(shè)置為6。

預(yù)制體為容納鄰居創(chuàng)建的容器

現(xiàn)在添加一個(gè)公共方法在每個(gè)方向上去獲取相鄰單元格。因?yàn)榉较蛎杜e轉(zhuǎn)換成的整數(shù)肯定是在0-5之間,所以這里不用去檢查數(shù)組下標(biāo)是否可能越界。

同樣添加一個(gè)方法去設(shè)置相鄰單元格。

相鄰單元格之間的相對(duì)關(guān)系是雙向的,所以當(dāng)在一個(gè)方向上設(shè)置了相鄰單元格,在反方向上也同樣成立。

相鄰單元格的相對(duì)方向是相反的

當(dāng)然,這是假設(shè)我們有一個(gè)方法能獲取指定方向的相反方向(Oppositie())的情況下。我們可以在HexDirection里去添加一個(gè)擴(kuò)展方法去實(shí)現(xiàn)這個(gè)功能。獲取相反方向相當(dāng)于在前三個(gè)方向上加上3,后三個(gè)方向上減去3。

什么是擴(kuò)展方法?
擴(kuò)展方法是一個(gè)靜態(tài)類(lèi)中的靜態(tài)方法,但使用起來(lái)像是某些類(lèi)型的實(shí)例方法。這個(gè)類(lèi)型可以是任何東西:自定義類(lèi)、接口、結(jié)構(gòu)體、原生數(shù)據(jù)結(jié)構(gòu)或者是枚舉。擴(kuò)展方法的第一個(gè)參數(shù)之前必須有this關(guān)鍵字,它定義方法將操作的類(lèi)型和實(shí)例的值。
這個(gè)特性允許我們?cè)谌魏螙|西上添加方法,就像是靜態(tài)方法的參數(shù)可以是任何類(lèi)型。在有節(jié)制適量使用的情況下這個(gè)特性非常方便。但過(guò)渡使用會(huì)造成代碼結(jié)構(gòu)的混亂。

1.1 連接相鄰單元格

我們可以在HexGrid.CreatCell里初始化單元格之間的相鄰關(guān)系。當(dāng)我們從左到右逐行查看單元格時(shí),我們知道已經(jīng)創(chuàng)建了哪些單元格。這些是我們可以連接的單元格。

最簡(jiǎn)單的是E-W向的連接,每一行的第一個(gè)沒(méi)有E向相鄰的單元格,而其他的都有。由于相鄰單元格是在遍歷到這里之前就創(chuàng)建好的,所以可以直接連接它們。

創(chuàng)建單元格時(shí)連接由東向西方向的單元格
東西方向的單元格已經(jīng)相連

還有另外兩個(gè)雙向連接需要建立,因?yàn)檫@些連接是在不同行之間,我們只能通過(guò)之前創(chuàng)建的行連接起來(lái)。這意味著第一行被完全跳過(guò)了。

由于每行之間的連接時(shí)呈鋸齒狀交錯(cuò),所以需要不同的處理方法。首先先處理偶數(shù)行,它們之間有SE方向的連接關(guān)系,先連接這個(gè)方向。

連接每行之前由西北到東南方向的單元格
"z&1"是什么意思?
大家都知道"&&"是布爾運(yùn)算符里的"與"運(yùn)算,"&"就是"按位與"。它們的執(zhí)行邏輯相同,但后者是對(duì)于每一位進(jìn)行運(yùn)算。
兩個(gè)Bit都是1,與運(yùn)算的結(jié)果就是1。例如:10101010 & 00001111結(jié)果是00001010。
從計(jì)算機(jī)原理層面上來(lái)說(shuō),所有的數(shù)字都是用二進(jìn)制表示的。二進(jìn)制中的1、2、3、4寫(xiě)作1、10、11、100。如你所見(jiàn),表示是否為偶數(shù)的最低有效位是第一位。
我們把二進(jìn)制的與運(yùn)算作為一個(gè)遮罩,忽略除了第一位之外的其他位數(shù),如果結(jié)果是0,那就表示這是一個(gè)偶數(shù)。

現(xiàn)在就可以連接SW方向的單元格了。除了每一行的第一個(gè)單元格,它們SW方向是空的。

奇數(shù)行遵循著相同的邏輯,除了鏡像關(guān)系。運(yùn)行完一次這個(gè)方法后,網(wǎng)格內(nèi)所有的單元格都關(guān)聯(lián)了起來(lái)。

所有的相鄰單元格都連接上了

當(dāng)然,不是每個(gè)單元格都精準(zhǔn)的與六個(gè)單元格相鄰。網(wǎng)格邊緣的單元格最少有兩個(gè),最多有5個(gè)相鄰單元格,這應(yīng)該是在之前就意識(shí)到的。

每個(gè)單元格所擁有的鄰居個(gè)數(shù)

2.顏色混合

顏色混合會(huì)使三角化每個(gè)單元格的過(guò)程更加復(fù)雜,所以我們把三角化的代碼單獨(dú)分開(kāi)。因?yàn)槲覀儸F(xiàn)在能通過(guò)方向獲取相鄰單元格了,所以在代碼里替換原來(lái)用坐標(biāo)獲取的部分。

獲取角度也換成用方向獲取,這樣應(yīng)該比用坐標(biāo)獲取好用。

但在這之前需要在HexMetrics里添加兩個(gè)靜態(tài)方法。這樣做還有個(gè)額外的好處:我們可以設(shè)置corners數(shù)組為私有變量了。

2.1 讓每個(gè)三角形有多種顏色

現(xiàn)在HexMesh.AddTriangleColor方法只有一個(gè)顏色參數(shù),所以每個(gè)三角形只能有一個(gè)固定的顏色。我們添加兩個(gè)參數(shù)讓三角形的每個(gè)頂點(diǎn)都有不同的顏色。

現(xiàn)在可以開(kāi)始混合顏色了!一開(kāi)始就簡(jiǎn)單的用相鄰單元格的顏色作為其它頂點(diǎn)的顏色。

又不幸地產(chǎn)生了一個(gè)空引用異常,因?yàn)椴皇敲總€(gè)單元格都有六個(gè)相鄰單元格。當(dāng)沒(méi)有鄰居時(shí)就用自己的顏色代替。

"??"是什么意思?
這被稱為空合并運(yùn)算符,簡(jiǎn)單來(lái)說(shuō)"a??b"即"a!=null?a:b"的簡(jiǎn)寫(xiě)。
這里有個(gè)小詭計(jì),因?yàn)閁nity在把一個(gè)東西與組件比較時(shí)會(huì)自定義,(注:Unity中判斷一個(gè)對(duì)象不為空時(shí)可以直接寫(xiě)成if(someThings),這在C#原本語(yǔ)法里是沒(méi)有的)而這個(gè)運(yùn)算符會(huì)繞過(guò)它并直接與null比較,不過(guò)這是銷(xiāo)毀對(duì)象時(shí)才需要考慮的問(wèn)題。
錯(cuò)誤的顏色混合
坐標(biāo)標(biāo)簽去哪了?
它還在那,不過(guò)截圖時(shí)把UI層隱藏了。


2.2 顏色平均化

顏色混合其效果了,不過(guò)顯然現(xiàn)在的效果不能接受。兩個(gè)單元格之間的邊界的顏色應(yīng)該是這兩者的平均值才對(duì)。

邊緣混合

現(xiàn)在我們混合了兩個(gè)邊界點(diǎn)上的顏色,依然得到了顏色分界線的形狀。這是因?yàn)榱呅蔚拿總€(gè)外部頂點(diǎn)總共有3個(gè)六邊共享。

三個(gè)相鄰單元格,四種顏色

這表示還得考慮上面和下面的相鄰單元格。最終得到的應(yīng)該是四種顏色,每組三種。

添加兩個(gè)額外的方法到HexDirectionExtension中,讓我們能方便的跳轉(zhuǎn)到上一個(gè)和下一個(gè)方向。

現(xiàn)在我們可以獲得所有的三個(gè)相鄰單元格,然后執(zhí)行兩次三向顏色混合。

角落混合

現(xiàn)在除了邊緣上的單元格,其他位置得到了正確的顏色變換。邊界單元格因?yàn)榕c丟失的單元格顏色不一致,所以仍然能看到那里的邊界顏色。但是總的來(lái)說(shuō),目前效果仍不理想,需要一個(gè)更好的策略。

3. 混合區(qū)域

混合六邊形的整個(gè)表面色導(dǎo)致雜亂的模糊效果,你再也不能清晰的識(shí)別出每一個(gè)單元格。我們能通過(guò)只混合靠近邊界的區(qū)域來(lái)改善這一點(diǎn),這可以讓內(nèi)部的六邊形保持固定的顏色。

顏色混合區(qū)域的固定核心

混合區(qū)域相對(duì)固定區(qū)域的占比會(huì)生成不同的視覺(jué)效果,我們把這個(gè)區(qū)域定于為外徑的一部分。先設(shè)定其為75%,這就新增了兩個(gè)常量,兩者加起來(lái)是100%。

利用新的要素,創(chuàng)建獲取內(nèi)部固定顏色的六邊形的方法。

現(xiàn)在修改HexMesh.Triangulate方法讓它變成獲取內(nèi)部固定色六邊形的角。先暫時(shí)不改變顏色。

中間的固定區(qū)域六邊形,沒(méi)有邊緣


3.1 三角化混合區(qū)域

現(xiàn)在通過(guò)細(xì)分三角形來(lái)填補(bǔ)空缺,它在每個(gè)方向都是一個(gè)梯形。我們可以用四邊形來(lái)表示,創(chuàng)建一個(gè)方法添加這個(gè)四邊形和它的顏色。

梯形邊緣

重寫(xiě)HexMesh.Triangulate方法,現(xiàn)在三角形獲取固定的顏色,梯形部分混合這個(gè)固定色和兩個(gè)角落上的顏色。

梯形邊緣顏色混合

3.2 邊界連接橋

現(xiàn)在看起來(lái)好些了,但是還沒(méi)完。兩個(gè)邊界的顏色混合受到了相鄰單元格邊界的影響。為了避免這一點(diǎn),我們要把梯形的兩個(gè)角切開(kāi)變成矩形?,F(xiàn)在它變成了連接相鄰單元格的橋,在側(cè)面留下了缺口。

邊緣連接橋

在一開(kāi)始就能通過(guò)v1和v2獲取v3和v4的位置,然后沿著橋移動(dòng)到邊緣就能計(jì)算出坐標(biāo)。v3和v4在邊緣上的偏移量可以通過(guò)取相鄰角的中點(diǎn)來(lái)獲取,然后乘以混合比例的常量。這些應(yīng)該是HexMetrics的范疇。

回到HexMesh里,把AddQuadColor的顏色參數(shù)改為兩個(gè)比較合理。

修改Triangulate,現(xiàn)在它就能在相鄰單元格之間創(chuàng)建正確的混合連接橋。

正確的連接橋顏色混合與角落的缺口

3.3 填充間隙

現(xiàn)在當(dāng)三個(gè)單元格交匯時(shí),通過(guò)切分梯形得到一個(gè)三角形的洞,下一步是把這些間隙填充回去。首先考慮與前一個(gè)相鄰單元格連接的三角形。它的第一個(gè)頂點(diǎn)具有單元格的顏色,第二個(gè)頂點(diǎn)的顏色是三色混合,最后一個(gè)頂點(diǎn)的顏色和連接橋顏色的一半相同。

快完成了

最后,另一個(gè)三角形也是一樣的方法,除了它是第二個(gè)頂點(diǎn)與連接橋相接,而不是第三個(gè)頂點(diǎn)。

完全填充

現(xiàn)在我們得到了不錯(cuò)的混合區(qū)域效果,我們可以指定任意大小,由你自己決定模糊還是直接的邊緣顏色過(guò)渡。你可能會(huì)注意到網(wǎng)格邊界附近的混合仍然是不正確的。還是暫時(shí)不管這個(gè)問(wèn)題,把注意力集中在另一件事上。

但是顏色轉(zhuǎn)換依然很難看?
這是線性顏色混合的極限了。事實(shí)上純色的效果不是很好,未來(lái)的教程中將會(huì)升級(jí)到地形材質(zhì)并做一些更漂亮的混合。

4.邊界合并

觀察一下網(wǎng)格的拓?fù)浣Y(jié)構(gòu),有哪些不同的形狀?如果我們忽略邊框,能識(shí)別出3種形狀:固定色的六邊形、兩種顏色混合的矩形和三種顏色混合的三角形,無(wú)論是否有三個(gè)單元格交匯都能看到。

能看到的三種形狀

所以每?jī)蓚€(gè)六邊形由一個(gè)矩形橋連接起來(lái),每三個(gè)六邊形由一個(gè)三角形連接起來(lái)。而我們現(xiàn)在用一種更復(fù)雜的方法在進(jìn)行三角剖分:用兩個(gè)四邊形連接一對(duì)六邊形,用三個(gè)三角形連接3個(gè)六邊形。這樣似乎有些過(guò)于復(fù)雜了,如果我們直接用單個(gè)形狀相連,甚至顏色平均都不需要了。這樣就能用更少的復(fù)雜性,更少的工作量,更少的三角形實(shí)現(xiàn)這個(gè)功能。

比需求更為復(fù)雜
我們?yōu)槭裁床辉谝婚_(kāi)始就這么做?
你可能會(huì)在你的一生中問(wèn)許多次這個(gè)問(wèn)題,但這是馬后炮。這是一個(gè)代碼以邏輯方式演進(jìn)的例子,直到獲得了新的見(jiàn)解,從而產(chǎn)生了新的方法。這樣的頓悟常常發(fā)生在你認(rèn)為你已經(jīng)搞定的時(shí)候。

4.1直接的連接橋

邊界的連接橋現(xiàn)在是兩個(gè)四邊形組合而成,要直接用一個(gè)四邊形連接到相鄰單元格,需要把橋的長(zhǎng)度增加一倍。這意味著不再需要平均化HexMetrics.GetBridge里的兩個(gè)角了,而變成直接相加并與混合區(qū)域占比常量相乘。

所有的連接橋都交叉重疊

現(xiàn)在一個(gè)橋直接連接兩個(gè)六邊形,但依然生成了兩個(gè)連接處,在每個(gè)方向上都有一個(gè)橋被覆蓋,所以現(xiàn)在兩個(gè)相鄰單元格只有一個(gè)需要?jiǎng)?chuàng)建連接橋。

先簡(jiǎn)化我們的三角化代碼,刪除所有邊緣三角形與顏色混合的部分。然后把添加四邊形連接橋的代碼移動(dòng)到新方法中。傳遞前兩個(gè)頂點(diǎn)到這個(gè)方法中,這樣就不需要再推導(dǎo)它們了。

現(xiàn)在可以很容易的限制三角化連接,處理NE方向的連接時(shí)受限只添加一個(gè)連接橋。

東北方向的連接橋

這樣看起來(lái)在只在前三個(gè)方向三角化連接橋就能包含所有的連接,這三個(gè)方向分別是NE、E和SE。

里面和邊界上的連接橋

相對(duì)于兩個(gè)單元格的連接就完成了,但是還有一些在網(wǎng)格邊緣無(wú)用的連接。讓我們通過(guò)修改TriangulateConnection中的代碼去掉它們。一旦發(fā)現(xiàn)沒(méi)有相鄰單元格方法就跳出去,所以不用再用當(dāng)前單元格代替不存在的相鄰單元格了。

只有里面的連接橋

4.2 三角形連接處

又來(lái)開(kāi)始填三角形的坑了,依然只需要在相鄰單元格存在的時(shí)候才執(zhí)行。

第三個(gè)頂點(diǎn)位置在哪?暫時(shí)用v2當(dāng)占位符,但那顯然不正確。因?yàn)槿切蔚拿總€(gè)頂點(diǎn)都連接在橋上,所以可以通過(guò)在下一個(gè)相鄰六邊形的連接橋上獲得。

再一次,顏色過(guò)渡完成

全搞定了?還沒(méi),現(xiàn)在要處理三角形重疊的問(wèn)題。因?yàn)槭敲咳齻€(gè)單元格共享一個(gè)三角形連接處,所以只需要在兩個(gè)方向添加連接三角形:NE和E方向。

下一期教程內(nèi)容是:https://catlikecoding.com/unity/tutorials/hex-map/part-3/

本期工程地址:https://github.com/tank1018702/Hex-Map-Learning/tree/BlendingCellColors


想系統(tǒng)學(xué)習(xí)游戲開(kāi)發(fā)的童鞋,歡迎訪問(wèn)?http://levelpp.com/??????????

游戲開(kāi)發(fā)攪基QQ群:869551769???

HexMap學(xué)習(xí)筆記(二)——單元格顏色混合的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
全州县| 高阳县| 谷城县| 中山市| 治县。| 樟树市| 博兴县| 土默特左旗| 屯门区| 革吉县| 安吉县| 望都县| 安徽省| 固安县| 蓬溪县| 交城县| 保靖县| 静乐县| 沅江市| 民勤县| 祁东县| 象山县| 尉犁县| 图木舒克市| 汝城县| 江北区| 隆安县| 林甸县| 忻城县| 清徐县| 龙井市| 南充市| 金沙县| 清新县| 云和县| 秦皇岛市| 屏山县| 栾川县| 普格县| 新干县| 安吉县|