激情六月丁香婷婷|亚洲色图AV二区|丝袜AV日韩AV|久草视频在线分类|伊人九九精品视频|国产精品一级电影|久草视频在线99|在线看的av网址|伊人99精品无码|午夜无码视频在线

高校合作1:010-59833514 ?咨詢(xún)電話:400-810-1418 服務(wù)與監(jiān)督電話:400-810-1418轉(zhuǎn)接2

js能開(kāi)發(fā)大型游戲嗎(如何用 JavaScript+Canvas 開(kāi)發(fā)一款超級(jí)燒腦小游戲?)

發(fā)布時(shí)間:2023-11-27 12:17:49 瀏覽量:113次

?如何用 JavaScript+Canvas 開(kāi)發(fā)一款超級(jí)燒腦小游戲?

js能開(kāi)發(fā)大型游戲嗎(如何用 JavaScript+Canvas 開(kāi)發(fā)一款超級(jí)燒腦小游戲?)

作者 | huangjianke

責(zé)編 | 伍杏玲

出品 | CSDN(ID:CSDNnews)

【CSDN 編者按】據(jù)微信最新數(shù)據(jù),微信小游戲累計(jì)注冊(cè)用戶(hù)量已突破10億。那么初學(xué)者如何開(kāi)發(fā)一款好玩又燒腦的微信小游戲呢?本文作者將詳細(xì)為大家講解。

“啟邏輯之高妙,因想象而自由?!睂盈B拼圖Plus是一款需要空間想象力和邏輯推理能力完美結(jié)合的微信小游戲,偶消奇不消,在簡(jiǎn)單的游戲規(guī)則下卻有著無(wú)數(shù)種可能性,需要你充分發(fā)揮想象力去探索,看似簡(jiǎn)單卻具有極大的挑戰(zhàn)性和趣味性,Talk is cheap. Show me the code!

層疊拼圖Plus微信小游戲采用JavaScript+Canvas實(shí)現(xiàn),沒(méi)有使用任何游戲引擎,對(duì)于初學(xué)者來(lái)說(shuō),也比較容易入門(mén)。下面是小游戲頁(yè)面:

繪圖模糊的原因知道了,在微信小游戲里面又該如何解決呢?

可以看到,我們先通過(guò) wx
.getSystemInfoSync.pixelRatio 獲取設(shè)備的像素比ratio,然后將在屏 Canvas 的寬度和高度按照所獲取的像素比ratio進(jìn)行放大,在繪制文字、圖片的時(shí)候,坐標(biāo)點(diǎn) x、y 和所要繪制圖形的 width、height均需要按照像素比 ratio 進(jìn)行縮放,這樣我們就可以清晰的在高清屏中繪制想要的文字、圖片。

可參考微信官方縮放策略調(diào)整

另外,需要注意的是,這里的 canvas 是由 weapp-adapter 預(yù)先調(diào)用 wx.createCanvas 創(chuàng)建一個(gè)上屏 Canvas,并暴露為一個(gè)全局變量 canvas。

在游戲畫(huà)布內(nèi),我們以左上角為坐標(biāo)原點(diǎn) {x: 0, y: 0} ,一個(gè)多邊形包含多個(gè)單位長(zhǎng)度的平面坐標(biāo)點(diǎn),如:[{ x: 1, y: 3 }, { x: 5, y: 3 }, { x: 3, y: 5 }] 表示為一個(gè)三角形的區(qū)域,需要注意的是,x、y 并不是真實(shí)的平面坐標(biāo)值,而是通過(guò)屏幕寬度計(jì)算出來(lái)的單位長(zhǎng)度,在畫(huà)布內(nèi)的真實(shí)坐標(biāo)值則為 {x: x * itemWidth, y: y * itemWidth} 。

繪制多邊形代碼實(shí)現(xiàn)如下:

使用:

效果如下圖:

CanvasRenderingContext2D其他使用方法可參考:CanvasRenderingContext2D API 列表

有經(jīng)驗(yàn)的同學(xué),也許一眼就發(fā)現(xiàn)了,1 + 1 = 0 剛好符合通過(guò)異或運(yùn)算得出的結(jié)果。當(dāng)然,細(xì)心的同學(xué)也可能已經(jīng)發(fā)現(xiàn),上文有一句特殊的代碼:
this.ctx.globalCompositeOperation = 'xor',也正是通過(guò)設(shè)置 CanvasContext 的 globalCompositeOperation 屬性值為 xor 便實(shí)現(xiàn)了「偶消奇不消」的神奇效果。

globalCompositeOperation 是指 在繪制新形狀時(shí)應(yīng)用的合成操作的類(lèi)型,其他效果可參考:globalCompositeOperation 示例

講到這里,我們已經(jīng)知道如何在Canvas畫(huà)布內(nèi)繪制出偶消奇不消效果的層疊圖形了,接下來(lái)我們來(lái)看下玩家如何移動(dòng)選中的圖形。我們發(fā)現(xiàn)繪制出的圖形對(duì)象并沒(méi)有提供點(diǎn)擊事件綁定之類(lèi)的操作,那又如何判斷玩家選中了哪個(gè)圖形呢?這里我們就需要去實(shí)現(xiàn)如何判斷玩家觸摸事件的x,y坐標(biāo)在哪個(gè)多邊形圖形內(nèi)部區(qū)域,從而判斷出玩家選中的是哪一個(gè)多邊形圖形。

判斷一個(gè)點(diǎn)是否在任意多邊形內(nèi)部有多種方法,比如:

  • 射線法

  • 面積判別法

  • 叉乘判別法

  • 回轉(zhuǎn)數(shù)法

  • ...

在層疊拼圖Plus小游戲內(nèi),采用的是回轉(zhuǎn)數(shù)法來(lái)判斷玩家觸摸點(diǎn)是否在多邊形內(nèi)部?;剞D(zhuǎn)數(shù)是拓?fù)鋵W(xué)中的一個(gè)基本概念,具有很重要的性質(zhì)和用途。當(dāng)然,展開(kāi)討論回轉(zhuǎn)數(shù)的概念并不在該文的討論范圍內(nèi),我們僅需了解一個(gè)概念:當(dāng)回轉(zhuǎn)數(shù)為 0 時(shí),點(diǎn)在閉合曲線外部。

圖源:http://www.html-js.com/article/1538

上面面這張圖動(dòng)態(tài)演示了回轉(zhuǎn)數(shù)的概念:圖中紅色曲線關(guān)于點(diǎn)(人所在位置)的回轉(zhuǎn)數(shù)為 2。

對(duì)于給定的點(diǎn)和多邊形,回轉(zhuǎn)數(shù)應(yīng)該怎么計(jì)算呢?

  • 用線段分別連接點(diǎn)和多邊形的全部頂點(diǎn)

圖源:http://www.html-js.com/article/1538

  • 計(jì)算所有點(diǎn)與相鄰頂點(diǎn)連線的夾角

圖源:http://www.html-js.com/article/1538

  • 計(jì)算所有夾角和。注意每個(gè)夾角都是有方向的,所以有可能是負(fù)值

圖源:http://www.html-js.com/article/1538

最后根據(jù)角度累加值計(jì)算回轉(zhuǎn)數(shù)。360°(2π)相當(dāng)于一次回轉(zhuǎn)。

在使用 JavaScript 實(shí)現(xiàn)時(shí),需要注意以下問(wèn)題:

  • JavaScript 的數(shù)只有 64 位雙精度浮點(diǎn)這一種。對(duì)于三角函數(shù)產(chǎn)生的無(wú)理數(shù),浮點(diǎn)數(shù)計(jì)算不可避免會(huì)造成一些誤差,因此在最后計(jì)算回轉(zhuǎn)數(shù)需要做取整操作。

  • 通常情況下,平面直角坐標(biāo)系內(nèi)一個(gè)角的取值范圍是 -π 到 π 這個(gè)區(qū)間,這也是 JavaScript 三角函數(shù) Math.atan2 返回值的范圍。但 JavaScript 并不能直接計(jì)算任意兩條線的夾角,我們只能先計(jì)算兩條線與 x 正軸夾角,再取兩者差值。這個(gè)差值的結(jié)果就有可能超出 -π 到 π 這個(gè)區(qū)間,因此我們還需要處理差值超出取值區(qū)間的情況。

代碼實(shí)現(xiàn):

js能開(kāi)發(fā)大型游戲嗎(如何用 JavaScript+Canvas 開(kāi)發(fā)一款超級(jí)燒腦小游戲?)

通過(guò)前面的介紹我們可以知道,判斷游戲結(jié)果是否正確其實(shí)就是比對(duì)玩家組合圖形的 xor 結(jié)果與目標(biāo)圖形的 xor 結(jié)果。那么如何求多個(gè)多邊形 xor 的結(jié)果呢?polygon-clipping 正是為此而生的。它不僅支持 xor 操作,還有其他的比如:union, intersection, difference 等操作。在層疊拼圖Plus游戲內(nèi)通過(guò) polygon-clipping 又是怎樣實(shí)現(xiàn)游戲結(jié)果判斷的呢?

  • 目標(biāo)圖形

多邊形平面坐標(biāo)點(diǎn)集合:

獲取 多個(gè)多邊形 xor 結(jié)果:

xor結(jié)果:

同理計(jì)算出玩家操作圖形的xor結(jié)果進(jìn)行比對(duì)即可得出答案正確與否。

需要注意的是,獲取玩家的 xor 結(jié)果并不能直接拿來(lái)與目標(biāo)圖形xor 結(jié)果進(jìn)行比較,我們需要將xor 的結(jié)果以左上角為參考點(diǎn)將圖形平移至原點(diǎn)內(nèi),然后再進(jìn)行比較,如果結(jié)果一致,則代表玩家答案正確。

在看本章節(jié)內(nèi)容之前,建議先瀏覽一遍排行榜相關(guān)的官方文檔:好友排行榜、關(guān)系鏈數(shù)據(jù),以便對(duì)相關(guān)內(nèi)容有個(gè)大概的了解。

  • 開(kāi)放數(shù)據(jù)域

開(kāi)放數(shù)據(jù)域是一個(gè)封閉、獨(dú)立的 JavaScript 作用域。要讓代碼運(yùn)行在開(kāi)放數(shù)據(jù)域,需要在 game.json 中添加配置項(xiàng) openDataContext 指定開(kāi)放數(shù)據(jù)域的代碼目錄。添加該配置項(xiàng)表示小游戲啟用了開(kāi)放數(shù)據(jù)域,這將會(huì)導(dǎo)致一些限制。

  • 在游戲內(nèi)使用 wx.setUserCloudStorage(obj) 對(duì)玩家游戲數(shù)據(jù)進(jìn)行托管。

  • 在開(kāi)放數(shù)據(jù)域內(nèi)使用 wx.getFriendCloudStorage(obj)拉取當(dāng)前用戶(hù)所有同玩好友的托管數(shù)據(jù)

  • 展示關(guān)系鏈數(shù)據(jù)

如果想要展示通過(guò)關(guān)系鏈 API 獲取到的用戶(hù)數(shù)據(jù),如繪制排行榜等業(yè)務(wù)場(chǎng)景,需要將排行榜繪制到 sharedCanvas 上,再在主域?qū)?sharedCanvas 渲染上屏。

sharedCanvas 是主域和開(kāi)放數(shù)據(jù)域都可以訪問(wèn)的一個(gè)離屏畫(huà)布。在開(kāi)放數(shù)據(jù)域調(diào)用 wx.getSharedCanvas 將返回 sharedCanvas。

在主域中可以通過(guò)開(kāi)放數(shù)據(jù)域?qū)嵗L問(wèn) sharedCanvas,通過(guò) drawImage 方法可以將 sharedCanvas 繪制到上屏畫(huà)布。

sharedCanvas 本質(zhì)上也是一個(gè)離屏 Canvas,而重設(shè) Canvas 的寬高會(huì)清空 Canvas 上的內(nèi)容。所以要通知開(kāi)放數(shù)據(jù)域去重繪 sharedCanvas。

需要注意的是:sharedCanvas 的寬高只能在主域設(shè)置,不能在開(kāi)放數(shù)據(jù)域中設(shè)置。

一款能讓人心情愉悅的游戲,性能問(wèn)題必然不能成為絆腳石。那么可以從哪些方面對(duì)游戲進(jìn)行性能優(yōu)化呢?

在層疊拼圖Plus小游戲內(nèi),針對(duì)需要大量使用且繪圖繁復(fù)的靜態(tài)場(chǎng)景,都是使用離屏 Canvas進(jìn)行繪制的,如首頁(yè)網(wǎng)格背景、關(guān)卡列表、排名列表等。在微信內(nèi) wx.createCanvas 首次調(diào)用創(chuàng)建的是顯示在屏幕上的畫(huà)布,之后調(diào)用創(chuàng)建的都是離屏畫(huà)布。初始化時(shí)將靜態(tài)場(chǎng)景繪制完備,需要時(shí)直接拷貝離屏Canvas的圖像即可。Canvas 繪制本身就是不斷的更新幀從而達(dá)到動(dòng)畫(huà)的效果,通過(guò)使用離屏 Canvas,就大大減少了一些靜態(tài)內(nèi)容在上屏Canvas的繪制,從而提升了繪制性能。

內(nèi)存優(yōu)化

玩家在游戲過(guò)程中拖動(dòng)方塊的移動(dòng)其實(shí)就是不斷更新多邊形圖形的坐標(biāo)信息,然后不斷的清空畫(huà)布再重新繪制,可以想象,這個(gè)繪制是非常頻繁的,按照普通的做法就需要不斷去創(chuàng)建多個(gè)新的 Block 對(duì)象。針對(duì)游戲中需要頻繁更新的對(duì)象,我們可以通過(guò)使用對(duì)象池的方法進(jìn)行優(yōu)化,對(duì)象池維護(hù)一個(gè)裝著空閑對(duì)象的池子,如果需要對(duì)象的時(shí)候,不是直接new,而是從對(duì)象池中取出,如果對(duì)象池中沒(méi)有空閑對(duì)象,則新建一個(gè)空閑對(duì)象,層疊拼圖Plus小游戲內(nèi)使用的是官方demo內(nèi)已經(jīng)實(shí)現(xiàn)的對(duì)象池類(lèi),實(shí)現(xiàn)如下:

垃圾回收

小游戲中,JavaScript 中的每一個(gè) Canvas 或 Image 對(duì)象都會(huì)有一個(gè)客戶(hù)端層的實(shí)際紋理儲(chǔ)存,實(shí)際紋理儲(chǔ)存中存放著 Canvas、Image 的真實(shí)紋理,通常會(huì)占用相當(dāng)一部分內(nèi)存。

每個(gè)客戶(hù)端實(shí)際紋理儲(chǔ)存的回收時(shí)機(jī)依賴(lài)于 JavaScript 中的 Canvas、Image 對(duì)象回收。在 JavaScript 的 Canvas、Image 對(duì)象被回收之前,客戶(hù)端對(duì)應(yīng)的實(shí)際紋理儲(chǔ)存不會(huì)被回收。通過(guò)調(diào)用 wx.triggerGC 方法,可以加快觸發(fā) JavaScriptCore Garbage Collection(垃圾回收),從而觸發(fā) JavaScript 中沒(méi)有引用的 Canvas、Image 回收,釋放對(duì)應(yīng)的實(shí)際紋理儲(chǔ)存。

但 GC 具體觸發(fā)時(shí)機(jī)還要取決于 JavaScriptCore 自身機(jī)制,并不能保證調(diào)用 wx.triggerGC 能馬上觸發(fā)回收,層疊拼圖Plus小游戲在每局游戲開(kāi)始或結(jié)束都會(huì)觸發(fā)一下,及時(shí)回收內(nèi)存垃圾,以保證最良好的游戲體驗(yàn)。

對(duì)于游戲來(lái)說(shuō),每幀 16ms 是極其寶貴的,如果有一些可以異步處理的任務(wù),可以放置于 Worker 中運(yùn)行,待運(yùn)行結(jié)束后,再把結(jié)果返回到主線程。Worker 運(yùn)行于一個(gè)單獨(dú)的全局上下文與線程中,不能直接調(diào)用主線程的方法,Worker 也不具備渲染的能力。Worker與主線程之間的數(shù)據(jù)傳輸,雙方使用 Worker.postMessage 來(lái)發(fā)送數(shù)據(jù),Worker.onMessage 來(lái)接收數(shù)據(jù),傳輸?shù)臄?shù)據(jù)并不是直接共享,而是被復(fù)制的。

需要注意的是:Worker 最大并發(fā)數(shù)量限制為 1 個(gè),創(chuàng)建下一個(gè)前請(qǐng)用 Worker.terminate 結(jié)束當(dāng)前 Worker

其他 Worker相關(guān)的內(nèi)容請(qǐng)參考微信官方文檔:多線程 Worker

短短的一篇文章,定不能將層疊拼圖Plus小游戲的前前后后講明白講透徹。其實(shí)最讓人心累的還是軟著的申請(qǐng)過(guò)程,由于各種原因前前后后花了將近三個(gè)月的時(shí)間,后續(xù)可以給大家分享軟著申請(qǐng)相關(guān)的內(nèi)容,希望可以幫助到需要的童鞋。

江湖不遠(yuǎn),我們游戲里見(jiàn)!

作者簡(jiǎn)介:huangjianke,高級(jí)iOS開(kāi)發(fā)/前端開(kāi)發(fā)工程師,五年開(kāi)發(fā)經(jīng)驗(yàn)。

需要體驗(yàn)小游戲的童鞋可在微信小程序搜索層疊拼圖Plus。

【END】

js能開(kāi)發(fā)大型游戲嗎(如何用 JavaScript+Canvas 開(kāi)發(fā)一款超級(jí)燒腦小游戲?)

熱門(mén)課程推薦

熱門(mén)資訊

請(qǐng)綁定手機(jī)號(hào)

x

同學(xué)您好!

您已成功報(bào)名0元試學(xué)活動(dòng),老師會(huì)在第一時(shí)間與您取得聯(lián)系,請(qǐng)保持電話暢通!
確定