<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 Cocos Creator 做一個(gè)物理畫(huà)線游戲!支持 UGC 關(guān)卡創(chuàng)作和微信關(guān)卡分享

          共 4356字,需瀏覽 9分鐘

           ·

          2022-11-29 23:43

          引言:3D 跑酷游戲3D 三消游戲之后,本次孫二喵帶來(lái)了一個(gè) 2D 物理畫(huà)線游戲源碼,使用 Cocos Creator 3.6.2 開(kāi)發(fā)。源碼見(jiàn)文末。


          演示效果


          物理畫(huà)線是一種比較經(jīng)典的 2D 游戲玩法,這幾年也出了一系列的爆款產(chǎn)品。本文將從立項(xiàng)、游戲邏輯和具體功能點(diǎn)的實(shí)現(xiàn),來(lái)講解如何基于 Cocos Creator 3.x 開(kāi)發(fā)一款物理畫(huà)線游戲,并實(shí)現(xiàn) UGC 關(guān)卡創(chuàng)作和微信關(guān)卡分享。


          立項(xiàng)與準(zhǔn)備


          游戲立項(xiàng)


          游戲的核心玩法是玩家通過(guò)畫(huà)線保護(hù)自己的小雞,讓其免受黑洞中掉下的障礙小雞、或地圖上的其他障礙傷害。


          游戲關(guān)卡


          考慮到制作成本,游戲美術(shù)使用了簡(jiǎn)單的手繪風(fēng)格,用 paletton 選擇類(lèi)似紙張的顏色,拖動(dòng)色盤(pán),把比較順眼的方案保存起來(lái),確定游戲整體的風(fēng)格。



          色板中用到的顏色統(tǒng)一可以使用圓角矩形縮到最小(比如 15px,就輸出成 15+15+2=32px,預(yù)留2個(gè) px 給九宮格拉伸用),游戲所有的 UI 框架加起來(lái)就只有幾 KB,減少顯存的同時(shí),還可以提高加載速度。



          考慮到 spine 專業(yè)版數(shù)千元的價(jià)格,游戲內(nèi)的動(dòng)畫(huà)效果統(tǒng)一使用了 Cocos 內(nèi)置的動(dòng)畫(huà)編輯器+序列幀動(dòng)畫(huà)。序列幀動(dòng)畫(huà)使用 PS 制作,在畫(huà)好我們的角色后,PS 內(nèi)復(fù)制數(shù)個(gè)分組,調(diào)整角色的五官,輸出序列幀,一些相似的做了剔除,減少動(dòng)畫(huà)的體積占用。



          在 Cocos 內(nèi)制作序列幀動(dòng)畫(huà)比較簡(jiǎn)單。幀動(dòng)畫(huà)使用30幀,新建好動(dòng)畫(huà),并在精靈上面創(chuàng)建好動(dòng)畫(huà)組件,在對(duì)應(yīng)的關(guān)鍵幀替換圖片即可。



          制作好的序列幀動(dòng)畫(huà)無(wú)需進(jìn)行合并,拖入到一個(gè)文件夾內(nèi),使用 Cocos 自帶的自動(dòng)圖集打包即可。



          自定義網(wǎng)格背景


          考慮到游戲的背景是一個(gè)紙上世界、同時(shí)需要支持 UGC 和簡(jiǎn)單的 AI,我們需要一個(gè)圖片背景+網(wǎng)格。然而使用圖片背景+網(wǎng)格圖片不夠靈活,同時(shí)做出來(lái)的效果會(huì)比較死板,缺少隨機(jī)性,因此我從 shadertoy 上移植了一個(gè)紙張網(wǎng)格的效果。


          原 shader 的 for 循環(huán)比較多,且風(fēng)格比較寫(xiě)實(shí),這里進(jìn)行了一定的簡(jiǎn)化。



          這里把 shader 中常用的屬性都進(jìn)行了暴露,整體風(fēng)格調(diào)整到和色卡一致。



          游戲內(nèi)的3個(gè)場(chǎng)景(游戲界面、游戲內(nèi)、游戲編輯)都用到了這個(gè) shader 的圖片作為背景,這里使用精靈圖自帶的顏色 a_color 來(lái)控制網(wǎng)格顏色。



          并使用了簡(jiǎn)單的腳本接受全局事件,可以修改網(wǎng)格的顏色(這里只修改了透明度)。



          效果如下:



          考慮到游戲的 UGC 地圖編輯需要使用到格子,Astar 網(wǎng)格導(dǎo)航也需要。以圖片的視覺(jué)方向?yàn)槔聢D左是在 shader 里 uv 的 xy 方向,下圖右是 astar 算法的格子序號(hào)從小到大。



          所以我們需要在 shader 里對(duì)格子進(jìn)行轉(zhuǎn)換。



          同時(shí)考慮到算法簡(jiǎn)單,這里不做屏幕分辨率的適配了,默認(rèn)的設(shè)計(jì)分辨率是 750x1334,支持的最大顯示高度是 750x2.2倍=1650(絕大多數(shù)全面屏手機(jī)的最大高度)。


          uv 統(tǒng)一后,我們需要設(shè)置一下網(wǎng)格顯示,默認(rèn)黃色是安全區(qū)域坐標(biāo),表示可以放置物體或者有物體,紅色是危險(xiǎn)區(qū)域,表示不可以放置物體。



          定義好顏色和顏色的順序,在 shader 中使用簡(jiǎn)單的 aabb 四個(gè)方向進(jìn)行判斷,在范圍內(nèi)的就會(huì)把顏色改成黃色安全色或者紅色警告色。



          同時(shí) shader 把 worley 褶皺效果也加進(jìn)材質(zhì)的宏里,方便自定義開(kāi)關(guān)。



          如果需要使用自己的圖片作為背景,可以打開(kāi) Use_Texture 的宏,使用 750x1650 的背景拖即可。


          有了上述的準(zhǔn)備工作,我們就可以開(kāi)始地圖編輯器的制作了。


          地圖編輯


          在地圖編輯之前,我們先確定整體的網(wǎng)格大小為75像素,設(shè)計(jì)的最大分辨率是 750x1650,也就是 10x22 個(gè)格子,這里定義一個(gè)全局的 class 去記錄下這些配置。



          每個(gè)物品的格子數(shù)量,可以用物體的圖片長(zhǎng)和寬分別除以75,然后四舍五入。


          如尖刺,是 60x148 分辨率,正好是 1*2 個(gè)格子


          這部分?jǐn)?shù)據(jù)我們?cè)诔跏蓟矬w時(shí)候會(huì)提前處理,避免重復(fù)計(jì)算。



          接下來(lái)根據(jù)格子的奇數(shù)或者偶數(shù)決定落點(diǎn)的位置,可以分為 x 和 y 兩周軸向分開(kāi)處理。


          如果是偶數(shù)就不需要做偏移,在格子中間落點(diǎn)即可,如果是奇數(shù),需要偏移1個(gè)格子單位,同時(shí)偶數(shù)的格子用 Math.floor 求最小的整數(shù)格子,奇數(shù)用 Math.round 四舍五入求最近的格子。



          檢測(cè)上使用了 map 做查詢,當(dāng)檢測(cè)到數(shù)據(jù)時(shí)候我們要把有碰撞的格子范圍乘0.1,這樣格子的 x 范圍從 0-10,變成了 0-1,y 范圍從 0-22,變成了 0-2.2,正好和我們 shader 的 uv 對(duì)應(yīng)(shader 內(nèi)部對(duì)原始的 uv.y 也乘了2.2,并不是 0-1了)。



          當(dāng)我們檢測(cè)到碰撞體時(shí)候,當(dāng)前物體的周?chē)蜁?huì)變紅,存在碰撞體的周?chē)恢脮?huì)表黃。


          游戲內(nèi)定義了幾種物體的名字的枚舉,當(dāng)他們的名字一致時(shí)候,初始化時(shí)候就會(huì)標(biāo)記為是畫(huà)線工具,刪除工具或者旋轉(zhuǎn)工具,當(dāng)使用這些工具檢測(cè)到結(jié)果時(shí)候,就會(huì)對(duì)選中物體標(biāo)亮并進(jìn)行對(duì)應(yīng)操作。


          當(dāng)保存關(guān)卡時(shí)候,我們只需要記錄物件的格子開(kāi)始和結(jié)束范圍,也就是之前 map 保存的數(shù)據(jù),同時(shí)記錄物件的 scale.x 和 scale.y 記錄左右和上下方向的旋轉(zhuǎn),保存為 json 數(shù)據(jù),再把 json 數(shù)據(jù) Stringify 即可。



          在地圖編輯器和游戲內(nèi)讀取關(guān)卡都采用相同的邏輯,如果是 runtime 時(shí)候,我們會(huì)順便初始化一下 Astar Graph 里的網(wǎng)格權(quán)重。



          這樣即便是在復(fù)雜的關(guān)卡中,障礙小雞也可以精準(zhǔn)定位我們的游戲角色。



          玩法核心邏輯


          畫(huà)線算法


          下面介紹游戲的核心邏輯部分。


          游戲的核心邏輯是使用 Graphics 畫(huà)線,并把畫(huà)線的路徑點(diǎn)記錄下來(lái),同時(shí)我們的地圖編輯器也會(huì)使用到這個(gè)功能來(lái)畫(huà)輔助線。


          這里使用了曼哈頓距離來(lái)記錄移動(dòng)的距離。當(dāng)距離大于設(shè)定值,我們就會(huì)存儲(chǔ)一次路徑點(diǎn),同時(shí)使用 graphics 繪制一次路徑。



          游戲環(huán)境和編輯器環(huán)境使用了不同的長(zhǎng)度設(shè)置,編輯器會(huì)更短,來(lái)保證儲(chǔ)存的關(guān)卡長(zhǎng)度足夠小。


          畫(huà)線的第一個(gè)點(diǎn),我們使用了開(kāi)銷(xiāo)最低的 testPoint,記錄是否存在碰撞體。第二個(gè)點(diǎn)開(kāi)始,從上個(gè)點(diǎn)到當(dāng)前點(diǎn)發(fā)射一條射線進(jìn)行檢測(cè)。



          需要注意的是,這里的坐標(biāo)點(diǎn)需要使用物體的世界坐標(biāo)。


          當(dāng)畫(huà)線結(jié)束,就可以根據(jù)路徑點(diǎn)去生成碰撞體。這里直接使用了 polygon 多邊形生成碰撞體,已經(jīng)生成的碰撞體在關(guān)卡開(kāi)始的時(shí)候,會(huì)回收使用到的 vec2 類(lèi),減少 GC。


          我們首先把每2個(gè)點(diǎn)連成一條線,再對(duì)比每條線之間方向向量的斜率。考慮到性能,這里沒(méi)有使用三角函數(shù),斜率在一定范圍內(nèi),就判斷為是平行的,只會(huì)去推第二條線的最后一個(gè)點(diǎn)。



          這樣我們參與計(jì)算的路徑點(diǎn)就可以減少 30%-40%,我們用優(yōu)化過(guò)的路徑點(diǎn)再來(lái)算需要生成的 polygon 多邊形,這里把起始點(diǎn)定為1,結(jié)束點(diǎn)定為2,其他中間點(diǎn)是0。


          先計(jì)算出2個(gè)點(diǎn)之前的方向向量。



          再計(jì)算方向向量上,2個(gè)垂直方向的向量,分別乘以我們線段一半的寬度,最后起始點(diǎn)和結(jié)束點(diǎn)分辨加上這2個(gè)向量,就可以得到3個(gè)或者4個(gè)路徑點(diǎn),可以構(gòu)建出一個(gè)三角形或者平行四邊形(考慮到起始點(diǎn)和結(jié)束點(diǎn)可能貼邊,這里使用了三角形,避免碰撞沖突的修正)。


          生成了多邊形的路徑點(diǎn)后,我們需要額外 apply() 一下,我們所有的 vec2 都從 VecPool 單例內(nèi)存儲(chǔ),減少 GC。


          這里額外支持了 Graphic 的自定義材質(zhì),玩家可以在游戲內(nèi)更換畫(huà)筆的顏色。



          我們把材質(zhì)的顏色和材質(zhì)名在入口腳本里進(jìn)行配置,商店和 gameplay 根據(jù)配置進(jìn)行加載即可。



          感謝社區(qū)大佬的 Shader~



          狀態(tài)機(jī)


          畫(huà)好線后,就可以通知障礙出發(fā)去攻擊我們的角色了。



          這里使用了 Cocos 原本的 update,當(dāng)切換狀態(tài)時(shí)候會(huì)先執(zhí)行 onEnter 方法,再執(zhí)行 onUpdate 方法,這里可以把當(dāng)前狀態(tài)和之前狀態(tài)傳入,方便做邏輯切換,這里會(huì)記錄下 dt 和 duration 時(shí)長(zhǎng),方便繼承狀態(tài)機(jī)的類(lèi)使用。


          小黑子的 AI 繼承了 FSM 狀態(tài)機(jī),整個(gè)狀態(tài)比較簡(jiǎn)單,只有尋路和攻擊兩個(gè)狀態(tài)。



          尋路階段使用了 Astar 算法,每找到一個(gè)路徑點(diǎn),就會(huì)向下一個(gè)路徑點(diǎn)前進(jìn),尋路時(shí)候會(huì)使用人物的方向向量乘以一定距離,來(lái)檢測(cè)是否存在物理畫(huà)線。



          當(dāng)檢測(cè)到物理畫(huà)線的時(shí)候就會(huì)對(duì)物理畫(huà)線的 rigidbody2d 進(jìn)行攻擊,對(duì) rigidbody2d 施加速度向量,就可以出現(xiàn)線條被抬起來(lái)的行為了。



          我們會(huì)在 x 方向上做左右的隨機(jī),y 方向以向上圍住,也會(huì)隨機(jī)一定的數(shù)值。



          小雞的狀態(tài)機(jī)就相對(duì)比較簡(jiǎn)單,只有基本的碰撞檢測(cè),當(dāng)檢測(cè)到危險(xiǎn)的碰撞體就會(huì)觸發(fā)受傷然后游戲失敗。



          尋路導(dǎo)航


          這里使用到了和之前 EasyNavmesh 同款的 A* 導(dǎo)航算法,不同的是我們使用了一個(gè)單例進(jìn)行管理。



          這里把 Astar 翻譯成了 TS 版本,方法都加了強(qiáng)類(lèi)型判斷,同時(shí)把距離算法改成了曼哈頓距離。



          游戲內(nèi) FSM 同樣使用了曼哈頓距離,當(dāng)我們的路徑點(diǎn)走完,且離目標(biāo)超過(guò)2個(gè)格子距離時(shí)候就會(huì)再次尋路一次。



          到這里整個(gè)游戲大的邏輯就分解完了,下面介紹一下游戲關(guān)卡分享的邏輯。


          關(guān)卡分享邏輯


          游戲內(nèi)拍照


          游戲內(nèi)把物體和 UI 分辨分成了 Default 和 UI_2D 分組,并創(chuàng)建了2個(gè)相機(jī),Screencam 平時(shí)的可見(jiàn)分組為空,只有當(dāng)拍照時(shí)候才能看到 Default 分組。



          截圖后一瞬間,我們會(huì)讀取相機(jī) RenderTexture 的像素點(diǎn),并把角色的偏移量傳進(jìn)來(lái),保證截圖范圍不會(huì)太大,同時(shí)保證相機(jī)對(duì)著角色不會(huì)出框。



          關(guān)卡分享邏輯


          關(guān)卡分享并沒(méi)有使用云服務(wù)器,這里使用了微信分享里的 query 參數(shù),query 最大可以存儲(chǔ)2048長(zhǎng)度的 string(測(cè)試中4096也可以跑,擔(dān)心部分手機(jī)可能存在兼容問(wèn)題,這里最大設(shè)置成了2046)。



          我們?cè)诜窒頃r(shí)候可以把當(dāng)前關(guān)卡都轉(zhuǎn)換成 string,放到 query 里。



          當(dāng)我們分享給其他玩家,其他玩家打開(kāi)后,在游戲初始化和微信 onshow 時(shí)候就會(huì)檢測(cè)到是否有對(duì)應(yīng)的 query。


          微信的 getLaunchOption 是第一次進(jìn)入游戲時(shí)候會(huì)有的,wx.onShow 是后臺(tái)切換回來(lái)觸發(fā)的時(shí)間,當(dāng)檢測(cè)到 query 且 query 內(nèi)的關(guān)卡數(shù)據(jù)有效,就可以初始化這個(gè)關(guān)卡了。



          游戲內(nèi)顯示好友 UGC 關(guān)卡效果:



          資源鏈接


          • 源碼下載:

          https://store.cocos.com/app/detail/4240


          • 在線體驗(yàn):

          http://learncocos.com/chick


          • 論壇專貼:

          https://forum.cocos.org/t/topic/142673


          demo 源碼現(xiàn)已發(fā)布到 Cocos Store,希望可以對(duì)大家有所幫助!如有疑問(wèn)或者其他想交流的,歡迎移步論壇專貼。


          往期精彩

          瀏覽 167
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99精品免费视频 | 国产高清无码在线观看视频 | 亚洲操B在线看 | 国产成人黄色毛片不卡在线看 | 精品一区二区三区四 |