Hilo开发H5小游戏踩坑笔记
第一次開發小游戲,用的是Hilo框架。由于項目開發時間比較緊張,對游戲和CANVAS都沒有了解過。代碼雖然寫的很爛,但是還是記錄下踩過的坑吧!本文為碎碎念模式,并不深入,寫錯的地方希望多多指點。
一、CANVAS橫屏適配處理
游戲是微信內的一款橫屏游戲。如果強制橫屏,提示用戶去控制橫豎屏開關并不友好。
解決方案,游戲場景做成如下圖紫色部分結構,游戲寬高和手機屏幕調換。如果手機為豎屏,那么將游戲旋轉90°即可。
注:所述【橫屏】為用戶打開了允許橫屏的開關并橫屏,真正的橫屏。
代碼如下所示:
let width = document.documentElement.clientWidth; let height = document.documentElement.clientHeight; let box = document.getElementsByTagName('canvas'); let style = ''; // 豎屏 if (width < height) {style += `width:${height}px;`;style += `height:${width}px;`;style += '-webkit-transform: rotate(90deg); transform: rotate(90deg);';// 注意旋轉中點的處理style += `-webkit-transform-origin: ${width / 2}px ${width / 2}px;`;style += `transform-origin: ${width / 2}px ${width / 2}px;`; }if (box.length) {box[0].style.cssText = style; } 復制代碼當用戶開啟了橫屏開關,如果用戶橫屏,那就將游戲場景旋轉0°即可,也就是恢復最初的樣子。如下:
// 橫屏 if (width > height) {style += `width:${width}px;`; // 注意旋轉后的寬高切換style += `height:${height}px;`;style += '-webkit-transform: rotate(0); transform: rotate(0);';style += '-webkit-transform-origin: 0 0;';style += 'transform-origin: 0 0;'; }if (box.length) {box[0].style.cssText = style; } 復制代碼橫屏沒想象那么順利,我們的游戲是在微信場景。當用戶開啟橫屏開關并橫屏后,微信內置瀏覽器頭也會占一大部分區域。這樣我們的游戲場景旋轉后明顯是顯示不全的。
解決方案就是利用Hilo的api resize下舞臺
// 解決微信橫屏瀏覽器頭部 導致高度變化的問題 this.stage.resize(height, width, true); 復制代碼最后有幾個注意點:
1、注意旋轉過程中的寬高切換2、注意單位適配問題3、注意微信瀏覽器頭,就因為這個頭的變化。整個游戲都需要處理,所以還是盡量不要自己處理。。。 復制代碼參考文章
二、點擊事件失效
如下圖所示,游戲結束場景的2個按鈕。
左側旋轉90°后變成右側橫屏,但是豎屏下的橫屏(也就是旋轉90°得來的)【再來一次】按鈕點擊事件會失效,但是點擊紅色區域(沒有按鈕,大致繪制并不精準)部分這個時間會被觸發。
而用戶橫屏(開啟了橫屏開關,自然橫屏)【再來一次】按鈕點擊事件不會失效。
繪制時坐標以游戲場景左上角為(0,0),而旋轉90°后坐標以游戲場景左下角為(0,0)。因為旋轉90°后游戲場景左下角變成了視覺上的左上角。因此豎屏下的橫屏點擊紅色區域生效就是因為,Hilo的點擊事件是綁定在元素繪制時坐標區域上(猜測,沒有看源碼)。旋轉后,按鈕的點擊事件生效區間就變成了根據繪制的x、y也就是紅色區域。
那么如何解決這個問題,如上圖所示,旋轉后的x、y如圖中藍色字所示。可以算出
// 再玩一次按鈕 const start = this.gameOverScene.getChildById('start'); // 再玩一次按鈕 新的x = 游戲畫布寬度 - 繪制的y - 按鈕的高度 const startNewX = this.width - start.y - start.height ; // 再玩一次按鈕 新的y = 繪制的x const startNewY = start.x; // 監聽舞臺點擊事件 this.stage.on(Hilo.event.POINTER_START, (e) => {// 利用新的x、y 和按鈕自身的高度和寬度 判斷是否點擊在按鈕區域if ((e.stageX > startNewX && e.stageX < startNewX + start.height) &&(e.stageY > startNewY && e.stageY < startNewY + start.width)) {// 在玩一次邏輯處理} )}; 復制代碼【再玩一次】按鈕點擊事件解決了,但是事情沒有那么簡單。
給另一個【分享】按鈕加上事件,what?無論橫屏還是豎屏點擊事件都不生效。至少【再玩一次】按鈕事件還是生效的,只是不準罷了。
原因,觀察上述圖。【分享】按鈕在初始化的過程中是在游戲畫布右側,也就是手機屏幕外部。經過測試發現,發現繪制時在手機屏幕外的區域點擊事件都不會生效。解決方法如【再玩一次】,無論橫屏還是豎屏都計算坐標判斷。
三、音樂播放兼容
Hilo的HTMLAudio聲音播放模塊,官方文檔表示【使用限制:iOS平臺需用戶事件觸發才能播放,很多Android瀏覽器僅能同時播放一個音頻。】但是目前使用來看,瀏覽器測試OK,絕大部分手機都不能正常播放。解決方案,采用DOM的audio,但是同樣iOS平臺需用戶事件觸發才能播放。因此最終的解決方案就是進入游戲之前或者某個合適的環節獲取所有的音樂,先播放再暫停。用戶不會感知,可以完美解決。如下:
// html <audio id="audio" src="xxx.mp3" preload="auto"></audio> // dom為獲取 const dom = document.getElementById('audio'); dom.play(); dom.pause(); 復制代碼四、部分機型游戲場景顯示不全
游戲中可能有某些元素是經常復用的,因此會單獨切出來。如下圖左側
如上圖右側所示效果,最開始的實現方式如下。在初始化的時候就將公用元素Y軸截斷展示,這個效果看似OK,但是在測試階段發現某些iPhone手機不能顯示這2個元素。
new Hilo.Bitmap({// 繪制的圖片image: 'imgurl', // 測試坐標,非精準坐標rect: [0, 100, 50, 300],y: 0, }); new Hilo.Bitmap({// 繪制的圖片image: 'imgurl', // 測試坐標,非精準坐標rect:[0, 150, 50, 300],y: 0, });復制代碼查看Hilo源碼繪制圖片是用CanvasRenderingContext2D.drawImage方法。
CanvasRenderingContext2D.drawImage() 是瀏覽器原生提供的在 canvas 上繪制圖片的方法。
其有以下三種參數形式(詳細用法說明及演示可見 MDN):
| sx, sy | 源圖像的選擇區域的偏移量 |
| sWidth, sHeight | 源圖像的選擇區域的寬高 |
| dx, dy | 目標canvas的選擇區域的偏移量 |
| dWidth, dHeight | 目標canvas的選擇區域的寬高 |
注:
而我們的元素在部分機型上不能顯示就是因為觸發了第3點坑。修復代碼如下,通過完整的繪制圖片,然后通過元素的坐標來達到目標樣式。
new Hilo.Bitmap({// 繪制的圖片image: 'imgurl', // 測試坐標,非精準坐標rect: [0, 0, 50, 300],y: -100, }); new Hilo.Bitmap({// 繪制的圖片image: 'imgurl', // 測試坐標,非精準坐標rect:[0, 0, 50, 300],y: -150, }); 復制代碼參考文章
五、碰撞檢測,撞擊坐標不準確
用Hilo最開始開心的一點也是碰撞檢測不需要自己寫,hitTestObject檢測object參數指定的對象是否與其相交。因此撞擊區域可以書寫撞擊坐標。
// 給如下圖中的一個多邊形實行撞擊坐標 new Hilo.Bitmap({// 繪制的圖片image: 'imgurl', // 測試坐標,非精準坐標rect: [0, 0, 50, 300],y: -100,boundsArea: [// 測試坐標,非精準坐標,圖中紅點的坐標,從左到右{x: 0, y: 0},{x: 0, y: 100},{x: 100, y: 100},{x: 100, y: 200},{x: 200, y: 200},{x: 200, y: 100},{x: 300, y: 100},{x: 300, y: 0},] }); 復制代碼理想中應該是如下黃色區域構成的碰撞檢測區域。
而實際卻是如下黃色區域,空氣墻???用戶反饋為什么沒撞到就死翹翹了。(看了Hilo碰撞檢測這部分的實現源碼,沒太看懂多邊形的處理。。)
解決辦法,類似雪碧圖使用,恩...主要是懶得切圖
new Hilo.Bitmap({// 繪制的圖片image: 'imgurl', // 測試坐標,非精準坐標rect: [0, 0, 100, 100],y: 0,boundsArea: [// 測試坐標,非精準坐標,圖中紅點的坐標,從左到右{x: 0, y: 0},{x: 0, y: 100},{x: 100, y: 100},{x: 100, y: 0},] }); new Hilo.Bitmap({// 繪制的圖片image: 'imgurl', // 測試坐標,非精準坐標rect: [100, 0, 100, 200],y: 0,boundsArea: [// 測試坐標,非精準坐標,圖中紅點的坐標,從左到右{x: 0, y: 0},{x: 0, y: 200},{x: 100, y: 200},{x: 100, y: 0},] }); new Hilo.Bitmap({// 繪制的圖片image: 'imgurl', // 測試坐標,非精準坐標rect: [200, 0, 100, 100],y: 0,boundsArea: [// 測試坐標,非精準坐標,圖中紅點的坐標,從左到右{x: 0, y: 0},{x: 0, y: 100},{x: 100, y: 100},{x: 100, y: 0},] }); 復制代碼其實就是將1張圖裁剪成了3張圖,裁剪出來的區域撞擊坐標都中規中矩。過于不規則的圖形只能盡量寫的粗糙一些。
這么輕松就解決了嗎???當然NO!!!回顧下第四點,部分機型游戲場景顯示不全。上面裁剪的3張圖里,最后一張圖又觸發了safari的bug。o(╥﹏╥)o,所以還是乖乖切圖,或者雪碧圖留一點安全區域吧!
而且后來我才知道雪碧圖對于CANVAS來說更耗性能,還不如多切點圖呢~
轉載于:https://juejin.im/post/5ba0dea5f265da0aa3591f8d
總結
以上是生活随笔為你收集整理的Hilo开发H5小游戏踩坑笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 敏捷世界中的合规性
- 下一篇: 03-高级选择器,属性选择器,伪类选择器