如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車遊戲?

 幾個月前,JS1k遊戲製作節(JS1K game jam)傳出不再舉辦消息后,許多遊戲迷開始哀嚎。

             

Frank Force 也是其中一位,但他還有另一層身份——一位德克薩斯州奧斯汀的獨立遊戲設計師。Frank Force 在遊戲行業工作了20年,參與過9款主流遊戲、47個獨立遊戲的設計。在聽到這個消息后,他馬上和其他開發朋友討論了這個問題,並決定做點什麼為此紀念。

在此期間,他們受到三重因素的啟發。一是賽車遊戲,包括懷舊向的80年代賽車遊戲,他們在非常早期的硬件上推動實時 3D 圖形,所以作者沿用了相同的技術,用純 JavaScript 從頭開始實現做 3D 圖形和物理引擎;還有一些現代賽車遊戲帶來了視覺設計的靈感,比如《Distance》和《Lonely Mountains: Downhill》;二是之前 Jake Gordon 用 JavaScript 創建一個虛擬3D賽車的項目,並分享了代碼;三是 Chris Glover 曾經做過一款小到只有 1KB 的 JS1k 賽車遊戲《Moto1kross by Chris Glover》

於是 Frank 和他的朋友們決定做一個壓縮后只有 2KB 的 3D 賽車遊戲。2KB 到底有多小呢?提供一個參考,一個3.5英寸軟盤可以容納700多個這樣的遊戲。

他給這個遊戲取名 Hue Jumper。關於名字的由來,Frank 表示,遊戲的核心操作是移動。當玩家通過一個關卡時,遊戲世界就會換一個顏色色調。「在我想象中,每通過過一個關卡,玩家都會跳轉到另一個維度,有着完全不同的色調。」

做完這個遊戲后,Frank 將包含了遊戲的全部 JavaScript 代碼都發佈在他的個人博客上,其中用到的軟件主要也是免費或開源軟件的。遊戲代碼發佈在 CodePen,可以在 iframe 中試玩,有興趣的朋友可以去看看。

以下是原博內容,AI源創評論進行了不改變原意的編譯:

確定最高目標

因為嚴格的大小限制,我需要非常仔細對待我的程序。我的總體策略是儘可能保持一切簡單,為最終目標服務。

為了幫助壓縮代碼,我使用了 Google Closure Compiler,它刪除了所有空格,將變量重命名為1個字母字符,並進行了一些輕量級優化。

用戶可以通過 Google Closure Compiler 官網在線跑代碼。不幸的是,Closure Compiler 做了一些沒有幫助的事情,比如替換模板字符串、默認參數和其他幫助節省空間的ES6特性。所以我需要手動撤銷其中一些事情,並執行一些更「危險」的壓縮技術來擠出最後一個位元組空間。在壓縮方面,這不算很成功,大部分擠出的空間來自代碼本身的結構優化。

代碼需要壓縮到2KB。如果不是非要這麼做不可,有一個類似的但功能沒那麼強的工具叫做 RegPack 。

無論哪種方式,策略都是一樣的:盡最大可能重複代碼,然後用壓縮工具壓縮。最好的例子是 c.width,c.height和 Math。因此,在閱讀這段代碼時,請記住,你經常會看到我不斷重複一些東西,最終目的就是為了壓縮。

HTML

其實我的遊戲很少使用 html ,因為它主要用到的是 JavaScript 。但這是創建全屏畫布 Canvas ,也能將畫布 Canvas 設為窗口內部大小的代碼最小方法。我不知道為什麼在 CodePen 上有必要添加 overflow:hiddento the body,當直接打開時按理說也可以運行。

我將 JavaScript 封裝在一個 onload 調用,得到了一個更小的最終版本…< body style = margin:0 onload = " code _ goes _ here " > < canvas id = c >但是,在開發過程中,我不喜歡用這個壓縮設置,因為代碼存儲在一個字符串中,所以編輯器不能正確地高亮顯示語法。


壓縮

這就是整個遊戲啦!下方的一小段代碼就是壓縮后的最終結果,我用不同的顏色標註了不同的部分。完成所有這些工作后,你能感受到我在2KB內就做完了整個遊戲是多麼讓我滿意了嗎?而這還是在zip之前的工作,zip還可以進一步壓縮大小。

警告 Caveats

當然,還有很多其他 3D 渲染方法可以同時保證性能和視覺效果。如果我有更多的可用空間,我會更傾向於使用一個 WebGL API 比如 three.js ,我在去年製作的一個類似遊戲「Bogus Roads」中用過這個框架。此外,因為它使用的是 requestAnimationFrame ,所以需要一些額外的代碼來確保幀速率不超過60 fps,增強版本中我會這麼用,儘管我更喜歡使用 requestAnimationFrame 而不是 setInterval ,因為它是垂直同期的(VSyn,VerticalSynchronization),所以渲染更絲滑。這種代碼的一個主要好處是它非常兼容,可以在任何設備上運行,儘管在我舊 iPhone 上運行有點慢。

遊戲代碼被我放到了 GitHub 上的 GPL-3.0 下(https://github.com/KilledByAPixel/HueJumper2k),所以你可以在自己的項目中自由使用它。該庫中還包含 2KB 版本的遊戲,準確說是2031位元組!歡迎你添加一些其他的功能,比如音樂和音效到「增強」版本中。

後記

雷鋒網注意到,Frank Force 在個人博客發了這篇文章后,在內容、標題的加持下,這篇文章後來被不少國外媒體轉載。在盛讚之餘,也有質疑的聲音。網友「Anon」在原文下評論:你是如何在 2KB 安裝一個完整的 javascript 的,除非你可以隨意忽略 dependencies 插件庫的大小,或者你將整個遊戲作為 dependency,大小才有可能控制到 2KB,否則就是欺騙。

Frank 回復表示,大多數 small demos 都需要某種運行環境,即使它是可執行的。在這種情況下,就是 javascript 運行時環境,沒有其他 dependencies.。因為 javascript 是解釋的,所以也可以說壓縮后的代碼是在2KB以內的。

雷鋒網發現,有其他網友表示認可 Frank 的說法,他們認為 JS 是一種解釋語言,不能將其與其他編譯語言相比較。

雷鋒網

分享到Facebook
技術平台: Nasthon Systems