2023年5月14日 星期日

LimeJS : 無法載入多個編譯過的遊戲

2023年5月14日 星期日

 HTML5 FUN 的遊戲與工具大部份是使用 LimeJS 這個 HTML5 game framework 開發的,記得以前曾經試著在不重新載入頁面,動態載入第二個遊戲,但總是卡在一個看不懂的錯誤訊息,也沒去細究問題在哪裡(其實當時也看不出來啦!),最後就這樣擱著。最近打算將 HTML5 FUN 遊戲的製作工具「遊戲式題庫烘焙機 HTML5 FUN Homepage」全部整合在一個頁面中,不得不去面對「在不重新載入頁面,動態載入第二個遊戲」的問題。在一堆已經看不出意義的英文字母中研究了兩天,總算是找到問題了。

當我們利用 lime.py build  並加上參數「-a」時,程式中大部份的變數的幾乎都為了縮短名稱而較難識別,只能從一些字串內容或沒被改名稱的函數來當特徵,去找到問題點。

問題點一:closure/closure/goog/dom/dom.js 

觀察了一下,每次在不重新載入頁面,動態載入已經編譯過的第二個遊戲時,會出現類似這樣的錯誤訊息而無法繼續:

Uncaught TypeError: Cannot read properties of undefined (reading 'querySelectorAll')

比對了兩個遊戲已編譯的的程式碼後,由二支程式中有呼叫「querySelectorAll」的地方往回追溯,有一個全域變數的名稱和第一支程式的一樣;如果重新整理頁面,把兩支程式轉入的順序顛倒,雖然追到的變名稱不同,但是發生錯誤的原因都是一樣,有全域變數被覆蓋了。追到這個函數裡的全域變數「pa」了問題:

function Ob(a) {
  return a ? new Pb(Qb(a)) : pa || (pa = new Pb)
}

而它的宣告段落是這樣:

var pa;
var qa = String.prototype.trim ? function (a) {

註:第二行是故意留作記錄的,「.trim」是找到「pa」的特徵點。

很明顯的,pa 並沒設定初值,導致第二支程式載入後,pa 因為已存在,不會用新的,然後也不是原來的要使用的物件,就發生錯誤而中斷程式了。

追本溯源,比對了原始碼,總算找到 LimeJS 使用了「closure/closure/goog/dom/dom.js」,函數的原始碼如下:

goog.dom.getDomHelper = function (a) {
  return a ? new goog.dom.DomHelper(goog.dom.getOwnerDocument(a)) : goog.dom.defaultDomHelper_ || (goog.dom.defaultDomHelper_ = new goog.dom.DomHelper)
};

變數的「goog.dom.defaultDomHelper_」宣告是這樣:

goog.dom.defaultDomHelper_;

改成指定 null 初始值給它:

goog.dom.defaultDomHelper_ = null;

重新編譯遊戲的原始碼以後,第二個遊戲載入時,果然就不再發生錯誤了。

問題點二:lime.audio.context

dom.js 原始碼的變數初始問題解決後,本以為可以安枕無憂地繼續整合我的「HTML5 FUN 烘焙機」,結果部份遊戲的新錯誤訊息又出現了:

TypeError: Nd.decodeAudioData is not a function

「decodeAudioData」這個特徵很顯,它是在 LimeJS 處理聲音播放的「lime/src/audio/audio.js」檔案中。對照了一下,那個「Nd」指的應該就是原始碼中的「lime.audio.context」。一樣地,追到了聲音物件初始函數的這裡:

lime.audio.Audio.prototype.prepareContext_ = function() {
    if (lime.audio.context) return;

也就是當「lime.audio.context」已有內容時,它就不會再進行初始化的動作了,但是它的舊內容對應到的,又不是真正要使用的聲音物件,然後程式就中斷執行了。所以將那兩行改為:

lime.audio.Audio.prototype.prepareContext_ = function() {
if (typeof(lime.audio.context)!='undefined' 
&& lime.audio.context != null
&& typeof(lime.audio.context['createGain'])!='undefined'
) return;

也就是它必須是物件,而已是帶有「createGain」函數的,才視為已存在。

經過前面兩個問題點的研究,不但「HTML5 FUN 烘焙機」順利地進行功能整合與改進;感覺自己的功力似乎又提升了不少。

目前「遊戲式題庫烘焙機 HTML5 FUN Homepage」已經測試得差不多,再新增幾個遊戲範本,即可以公開給大家使用了,先看看我為它設計的圖示,聞香一下:

相關連結



沒有留言:

張貼留言

 
雄::gsyan © 2009. Design by Pocket