者 | huangjianke
責編 | 伍杏玲
出品 | CSDN(ID:CSDNnews)
【CSDN 編者按】據微信最新數據,微信小游戲累計注冊用戶量已突破10億。那么初學者如何開發一款好玩又燒腦的微信小游戲呢?本文作者將詳細為大家講解。
“啟邏輯之高妙,因想象而自由。”層疊拼圖Plus是一款需要空間想象力和邏輯推理能力完美結合的微信小游戲,偶消奇不消,在簡單的游戲規則下卻有著無數種可能性,需要你充分發揮想象力去探索,看似簡單卻具有極大的挑戰性和趣味性,Talk is cheap. Show me the code!
層疊拼圖Plus微信小游戲采用JavaScript+Canvas實現,沒有使用任何游戲引擎,對于初學者來說,也比較容易入門。下面是小游戲頁面:
Canvas 繪圖時,會從兩個物理像素的中間位置開始繪制并向兩邊擴散 0.5 個物理像素。當設備像素比為 1 時,一個 1px 的線條實際上占據了兩個物理像素(每個像素實際上只占一半),由于不存在 0.5 個像素,所以這兩個像素本來不應該被繪制的部分也被繪制了,于是 1 物理像素的線條變成了 2 物理像素,視覺上就造成了模糊
繪圖模糊的原因知道了,在微信小游戲里面又該如何解決呢?
可以看到,我們先通過 wx.getSystemInfoSync.pixelRatio 獲取設備的像素比ratio,然后將在屏 Canvas 的寬度和高度按照所獲取的像素比ratio進行放大,在繪制文字、圖片的時候,坐標點 x、y 和所要繪制圖形的 width、height均需要按照像素比 ratio 進行縮放,這樣我們就可以清晰的在高清屏中繪制想要的文字、圖片。
可參考微信官方縮放策略調整
另外,需要注意的是,這里的 canvas 是由 weapp-adapter 預先調用 wx.createCanvas 創建一個上屏 Canvas,并暴露為一個全局變量 canvas。
任意一個多邊形圖形,是由多個平面坐標點所組成的圖形區域。
在游戲畫布內,我們以左上角為坐標原點 {x: 0, y: 0} ,一個多邊形包含多個單位長度的平面坐標點,如:[{ x: 1, y: 3 }, { x: 5, y: 3 }, { x: 3, y: 5 }] 表示為一個三角形的區域,需要注意的是,x、y 并不是真實的平面坐標值,而是通過屏幕寬度計算出來的單位長度,在畫布內的真實坐標值則為 {x: x * itemWidth, y: y * itemWidth} 。
繪制多邊形代碼實現如下:
使用:
效果如下圖:
CanvasRenderingContext2D其他使用方法可參考:CanvasRenderingContext2D API 列表
1 + 1 = 0,是層疊拼圖Plus小游戲玩法的精髓所在。
有經驗的同學,也許一眼就發現了,1 + 1 = 0 剛好符合通過異或運算得出的結果。當然,細心的同學也可能已經發現,上文有一句特殊的代碼:this.ctx.globalCompositeOperation = 'xor',也正是通過設置 CanvasContext 的 globalCompositeOperation 屬性值為 xor 便實現了「偶消奇不消」的神奇效果。
globalCompositeOperation 是指 在繪制新形狀時應用的合成操作的類型,其他效果可參考:globalCompositeOperation 示例
當回轉數為 0 時,點在閉合曲線外部。
講到這里,我們已經知道如何在Canvas畫布內繪制出偶消奇不消效果的層疊圖形了,接下來我們來看下玩家如何移動選中的圖形。我們發現繪制出的圖形對象并沒有提供點擊事件綁定之類的操作,那又如何判斷玩家選中了哪個圖形呢?這里我們就需要去實現如何判斷玩家觸摸事件的x,y坐標在哪個多邊形圖形內部區域,從而判斷出玩家選中的是哪一個多邊形圖形。
判斷一個點是否在任意多邊形內部有多種方法,比如:
射線法
面積判別法
叉乘判別法
回轉數法
...
在層疊拼圖Plus小游戲內,采用的是回轉數法來判斷玩家觸摸點是否在多邊形內部。回轉數是拓撲學中的一個基本概念,具有很重要的性質和用途。當然,展開討論回轉數的概念并不在該文的討論范圍內,我們僅需了解一個概念:當回轉數為 0 時,點在閉合曲線外部。
圖源:http://www.html-js.com/article/1538
上面面這張圖動態演示了回轉數的概念:圖中紅色曲線關于點(人所在位置)的回轉數為 2。
對于給定的點和多邊形,回轉數應該怎么計算呢?
用線段分別連接點和多邊形的全部頂點
圖源:http://www.html-js.com/article/1538
計算所有點與相鄰頂點連線的夾角
圖源:http://www.html-js.com/article/1538
計算所有夾角和。注意每個夾角都是有方向的,所以有可能是負值
圖源:http://www.html-js.com/article/1538
最后根據角度累加值計算回轉數。360°(2π)相當于一次回轉。
在使用 JavaScript 實現時,需要注意以下問題:
JavaScript 的數只有 64 位雙精度浮點這一種。對于三角函數產生的無理數,浮點數計算不可避免會造成一些誤差,因此在最后計算回轉數需要做取整操作。
通常情況下,平面直角坐標系內一個角的取值范圍是 -π 到 π 這個區間,這也是 JavaScript 三角函數 Math.atan2 返回值的范圍。但 JavaScript 并不能直接計算任意兩條線的夾角,我們只能先計算兩條線與 x 正軸夾角,再取兩者差值。這個差值的結果就有可能超出 -π 到 π 這個區間,因此我們還需要處理差值超出取值區間的情況。
代碼實現:
探索的過程固然精彩,而結果卻更令我們期待
通過前面的介紹我們可以知道,判斷游戲結果是否正確其實就是比對玩家組合圖形的 xor 結果與目標圖形的 xor 結果。那么如何求多個多邊形 xor 的結果呢?polygon-clipping 正是為此而生的。它不僅支持 xor 操作,還有其他的比如:union, intersection, difference 等操作。在層疊拼圖Plus游戲內通過 polygon-clipping 又是怎樣實現游戲結果判斷的呢?
目標圖形
多邊形平面坐標點集合:
獲取 多個多邊形 xor 結果:
xor結果:
同理計算出玩家操作圖形的xor結果進行比對即可得出答案正確與否。
需要注意的是,獲取玩家的 xor 結果并不能直接拿來與目標圖形xor 結果進行比較,我們需要將xor 的結果以左上角為參考點將圖形平移至原點內,然后再進行比較,如果結果一致,則代表玩家答案正確。
有人的地方就有江湖,有江湖的地方就有排行
在看本章節內容之前,建議先瀏覽一遍排行榜相關的官方文檔:好友排行榜、關系鏈數據,以便對相關內容有個大概的了解。
開放數據域
開放數據域是一個封閉、獨立的 JavaScript 作用域。要讓代碼運行在開放數據域,需要在 game.json 中添加配置項 openDataContext 指定開放數據域的代碼目錄。添加該配置項表示小游戲啟用了開放數據域,這將會導致一些限制。
在游戲內使用 wx.setUserCloudStorage(obj) 對玩家游戲數據進行托管。
在開放數據域內使用 wx.getFriendCloudStorage(obj)拉取當前用戶所有同玩好友的托管數據
展示關系鏈數據
如果想要展示通過關系鏈 API 獲取到的用戶數據,如繪制排行榜等業務場景,需要將排行榜繪制到 sharedCanvas 上,再在主域將 sharedCanvas 渲染上屏。
sharedCanvas 是主域和開放數據域都可以訪問的一個離屏畫布。在開放數據域調用 wx.getSharedCanvas 將返回 sharedCanvas。
在主域中可以通過開放數據域實例訪問 sharedCanvas,通過 drawImage 方法可以將 sharedCanvas 繪制到上屏畫布。
sharedCanvas 本質上也是一個離屏 Canvas,而重設 Canvas 的寬高會清空 Canvas 上的內容。所以要通知開放數據域去重繪 sharedCanvas。
需要注意的是:sharedCanvas 的寬高只能在主域設置,不能在開放數據域中設置。
性能優化,簡而言之,就是在不影響系統運行正確性的前提下,使之運行地更快,完成特定功能所需的時間更短。
一款能讓人心情愉悅的游戲,性能問題必然不能成為絆腳石。那么可以從哪些方面對游戲進行性能優化呢?
在層疊拼圖Plus小游戲內,針對需要大量使用且繪圖繁復的靜態場景,都是使用離屏 Canvas進行繪制的,如首頁網格背景、關卡列表、排名列表等。在微信內 wx.createCanvas 首次調用創建的是顯示在屏幕上的畫布,之后調用創建的都是離屏畫布。初始化時將靜態場景繪制完備,需要時直接拷貝離屏Canvas的圖像即可。Canvas 繪制本身就是不斷的更新幀從而達到動畫的效果,通過使用離屏 Canvas,就大大減少了一些靜態內容在上屏Canvas的繪制,從而提升了繪制性能。
內存優化
玩家在游戲過程中拖動方塊的移動其實就是不斷更新多邊形圖形的坐標信息,然后不斷的清空畫布再重新繪制,可以想象,這個繪制是非常頻繁的,按照普通的做法就需要不斷去創建多個新的 Block 對象。針對游戲中需要頻繁更新的對象,我們可以通過使用對象池的方法進行優化,對象池維護一個裝著空閑對象的池子,如果需要對象的時候,不是直接new,而是從對象池中取出,如果對象池中沒有空閑對象,則新建一個空閑對象,層疊拼圖Plus小游戲內使用的是官方demo內已經實現的對象池類,實現如下:
垃圾回收
小游戲中,JavaScript 中的每一個 Canvas 或 Image 對象都會有一個客戶端層的實際紋理儲存,實際紋理儲存中存放著 Canvas、Image 的真實紋理,通常會占用相當一部分內存。
每個客戶端實際紋理儲存的回收時機依賴于 JavaScript 中的 Canvas、Image 對象回收。在 JavaScript 的 Canvas、Image 對象被回收之前,客戶端對應的實際紋理儲存不會被回收。通過調用 wx.triggerGC 方法,可以加快觸發 JavaScriptCore Garbage Collection(垃圾回收),從而觸發 JavaScript 中沒有引用的 Canvas、Image 回收,釋放對應的實際紋理儲存。
但 GC 具體觸發時機還要取決于 JavaScriptCore 自身機制,并不能保證調用 wx.triggerGC 能馬上觸發回收,層疊拼圖Plus小游戲在每局游戲開始或結束都會觸發一下,及時回收內存垃圾,以保證最良好的游戲體驗。
對于游戲來說,每幀 16ms 是極其寶貴的,如果有一些可以異步處理的任務,可以放置于 Worker 中運行,待運行結束后,再把結果返回到主線程。Worker 運行于一個單獨的全局上下文與線程中,不能直接調用主線程的方法,Worker 也不具備渲染的能力。Worker與主線程之間的數據傳輸,雙方使用 Worker.postMessage 來發送數據,Worker.onMessage 來接收數據,傳輸的數據并不是直接共享,而是被復制的。
需要注意的是:Worker 最大并發數量限制為 1 個,創建下一個前請用 Worker.terminate 結束當前 Worker
其他 Worker
相關的內容請參考微信官方文檔:多線程 Worker
短短的一篇文章,定不能將層疊拼圖Plus小游戲的前前后后講明白講透徹。其實最讓人心累的還是軟著的申請過程,由于各種原因前前后后花了將近三個月的時間,后續可以給大家分享軟著申請相關的內容,希望可以幫助到需要的童鞋。
江湖不遠,我們游戲里見!
作者簡介:huangjianke,高級iOS開發/前端開發工程師,五年開發經驗。
需要體驗小游戲的童鞋可在微信小程序搜索層疊拼圖Plus。
【END】
上有很多有助于學習CSS的游戲,本文收集了一些非常實用的免費CSS游戲,希望這些游戲可以幫助你再次體驗CSS的樂趣!
作者 | Andreas Müller
譯者 | 彎月,責編 | 郭芮
出品 | CSDN(ID:CSDNnews)
以下為譯文:
我必須承認,我的記性不是很好。特別是我記不住CSS,例如Flexbox布局等。flex容器的屬性justify-content可以有12種以上的不同值,其中許多可以與關鍵字safe或unsafe組合。詳細說明可以參照這篇文章《CSS技巧:flexbox的完整指南》(https://css-tricks.com/snippets/css/a-guide-to-flexbox/),這個頁面只有兩列,高度卻超過了2萬像素,雖然文章題目表明這是一篇完整的指南,但實際上文中并沒有覆蓋到所有內容。
最近,我在偶然間發現了一款塔防式的flexbox教學游戲,這款游戲真的是……
等等,你說什么?
你沒聽錯,事實證明,網上的確有很多有助于學習CSS的游戲。我收集了一些非常實用的免費CSS游戲,希望這些游戲也可以幫助你再次體驗CSS的樂趣!
Flexbox Defense
上述我提到的就是這款游戲。它涵蓋了flex的屬性align-items、justify-content、flex-direction、align-self和order,游戲本身總共有12關。特別是最后4關非常有趣,而且難度也很高。
游戲地址:http://www.flexboxdefense.com
代碼庫:https://github.com/channingallen/tower-defense
作者:Channing Allen
Flexbox Froggy
這也是一款涉及Flexbox的游戲,它涵蓋的flex屬性更多:align-items、justify-content、align-content、flex-direction、align-self、flex-wrap和flex-flow,而且游戲總共有24關,如果你打通關了,別忘了告訴我啊。
游戲地址:https://flexboxfroggy.com
代碼庫:https://github.com/thomaspark/flexboxfroggy
作者:Codepip
Grid Garden
這款游戲總共有28關,你可以從中學習CSS網格布局。它涵蓋了以下網格屬性:grid-column-start、grid-column-end、grid-column、grid-row-start、grid-row-end、grid-row、grid-area、order、grid-template-columns、grid-template-rows以及grid-template。
游戲地址:https://cssgridgarden.com
代碼庫:https://github.com/thomaspark/gridgarden
作者:Codepip
CSS Diner
這是一款有關各種CSS選擇器的小游戲,總共有32關,打通關后你就可以自詡為CSS選擇器專家了,而且你會越玩越餓。
游戲地址:http://flukeout.github.io
代碼庫:https://github.com/flukeout/css-diner
作者:Luke Pacholski
Unfold
這不完全是一款游戲,更像是一個有關CSS 3D變換的交互式演示。你可能會覺得無聊,但請相信我,游戲里面的動畫非常燃,而且你肯定會覺得純CSS不可能做出這樣的效果。
游戲地址:https://rupl.github.io/unfold
代碼庫:https://github.com/rupl/unfold
作者:Chris Ruppel
Roadmap
你需要一定的技巧和速度才能打通關這款游戲,但游戲本身是只用CSS和HTML制作的。它并非直接地講解了CSS,而且通過研究源代碼學習了很多有關clip-path、transform和帶有@keyframes的動畫知識!請在下方留言,告訴我們你總共嘗試了幾次才通關,我試了8次!
游戲地址:http://victordarras.fr/cssgame
作者:Victor Darras
Carnival
你需要在8秒內擊中所有目標!這是一款很不錯的CSS小游戲,使用了復選框和CSS動畫。
游戲地址:https://codepen.io/una/pen/NxZaNr
作者:Una Kravets
Tic-Tac-Toe (井字棋游戲)
這是一款經典的小游戲。這款純CSS的井字棋游戲只有2關,也使用了復選框和CSS動畫。
游戲地址:https://codepen.io/alvaromontoro/pen/BexWOw
作者:Alvaro Montoro
Flexbox Zombies
這款游戲帶有故事情節,你可以從中學習如何使用Flexbox和弩來打僵尸。這款游戲需要注冊。
游戲地址:https://mastery.games/p/flexbox-zombies
價格:179美元
作者:Dave Geddes
Service Workies
在這款冒險游戲中,你可以學習如何避免PWA的陷阱。你可以提高自己的技術力,并與游戲中的角色一起成長。也許你可以試著殺死在可憐的村子里肆虐了幾個世紀的兇猛野獸!這款游戲需要注冊。
游戲地址:https://serviceworkies.com
價格:179美元
作者:Dave Geddes
Grid Critters
在這款游戲中,你掌握CSS Grid的旅程始于這位神秘的Grid勇士。你的任務是使用強大的Grid工具來拯救外星生物,使其免于滅絕。這款游戲需要注冊。
游戲地址:https://gridcritters.com
價格:179美元
作者:Dave Geddes
總結
不論你是初學者還是專家,我都希望你能夠在玩游戲的同時又能學習一些有關CSS的知識!另外,你可以在Codepen上找到很多只用HTML和CSS創建的非常很棒的游戲。
你還知道哪些非常有趣的學習CSS的游戲?請在下方留言。
原文:https://dev.to/devmount/8-games-to-learn-css-the-fun-way-4e0f
本文為 CSDN 翻譯,轉載請注明來源出處。
【END】
*請認真填寫需求信息,我們會在24小時內與您取得聯系。