發(fā)布時間:2023-11-27 13:12:02 瀏覽量:128次
幾個月前,JS1k游戲制作節(jié)(JS1K game jam)傳出不再舉辦消息后,許多游戲迷開始哀嚎。
Frank Force 也是其中一位,但他還有另一層身份——一位德克薩斯州奧斯汀的獨立游戲設(shè)計師。Frank Force 在游戲行業(yè)工作了20年,參與過9款主流游戲、47個獨立游戲的設(shè)計。在聽到這個消息后,他馬上和其他開發(fā)朋友討論了這個問題,并決定做點什么為此紀念。
在此期間,他們受到三重因素的啟發(fā)。一是賽車游戲,包括懷舊向的80年代賽車游戲,他們在非常早期的硬件上推動實時 3D 圖形,所以作者沿用了相同的技術(shù),用純 JavaScript 從頭開始實現(xiàn)做 3D 圖形和物理引擎;還有一些現(xiàn)代賽車游戲帶來了視覺設(shè)計的靈感,比如《Distance》和《Lonely Mountains: Downhill》;二是之前 Jake Gordon 用 JavaScript 創(chuàng)建一個虛擬3D賽車的項目,并分享了代碼;三是 Chris Glover 曾經(jīng)做過一款小到只有 1KB 的 JS1k 賽車游戲《Moto1kross by Chris Glover》。
于是 Frank 和他的朋友們決定做一個壓縮后只有 2KB 的 3D 賽車游戲。2KB 到底有多小呢?提供一個參考,一個3.5英寸軟盤可以容納700多個這樣的游戲。
他給這個游戲取名 Hue Jumper。關(guān)于名字的由來,F(xiàn)rank 表示,游戲的核心操作是移動。當玩家通過一個關(guān)卡時,游戲世界就會換一個顏色色調(diào)?!霸谖蚁胂笾?,每通過過一個關(guān)卡,玩家都會跳轉(zhuǎn)到另一個維度,有著完全不同的色調(diào)。”
做完這個游戲后,F(xiàn)rank 將包含了游戲的全部 JavaScript 代碼都發(fā)布在他的個人博客上,其中用到的軟件主要也是免費或開源軟件的。游戲代碼發(fā)布在CodePen,可以在 iframe 中試玩,有興趣的朋友可以去看看。
以下是原博內(nèi)容,AI源創(chuàng)評論進行了不改變原意的編譯:
因為嚴格的大小限制,我需要非常仔細對待我的程序。我的總體策略是盡可能保持一切簡單,為最終目標服務(wù)。
為了幫助壓縮代碼,我使用了 Google Closure Compiler,它刪除了所有空格,將變量重命名為1個字母字符,并進行了一些輕量級優(yōu)化。
用戶可以通過 Google Closure Compiler 官網(wǎng)在線跑代碼。不幸的是,Closure Compiler 做了一些沒有幫助的事情,比如替換模板字符串、默認參數(shù)和其他幫助節(jié)省空間的ES6特性。所以我需要手動撤銷其中一些事情,并執(zhí)行一些更“危險”的壓縮技術(shù)來擠出最后一個字節(jié)空間。在壓縮方面,這不算很成功,大部分擠出的空間來自代碼本身的結(jié)構(gòu)優(yōu)化。
代碼需要壓縮到2KB。如果不是非要這么做不可,有一個類似的但功能沒那么強的工具叫做 RegPack 。
無論哪種方式,策略都是一樣的:盡最大可能重復(fù)代碼,然后用壓縮工具壓縮。最好的例子是 c.width,c.height和 Math。因此,在閱讀這段代碼時,請記住,你經(jīng)常會看到我不斷重復(fù)一些東西,最終目的就是為了壓縮。
其實我的游戲很少使用 html ,因為它主要用到的是 JavaScript 。但這是創(chuàng)建全屏畫布 Canvas ,也能將畫布 Canvas 設(shè)為窗口內(nèi)部大小的代碼最小方法。我不知道為什么在 CodePen 上有必要添加 overflow:hiddento the body,當直接打開時按理說也可以運行。
我將 JavaScript 封裝在一個 onload 調(diào)用,得到了一個更小的最終版本… 但是,在開發(fā)過程中,我不喜歡用這個壓縮設(shè)置,因為代碼存儲在一個字符串中,所以編輯器不能正確地高亮顯示語法。
有許多常量在各方面控制著游戲。當代碼被 Google Closure 這樣的工具縮小時,這些常量將被替換,就像 C++ 中的 #define 一樣,把它們放在第一位會加快游戲微調(diào)的過程。
鼠標是唯一的輸入系統(tǒng)。通過這段代碼,我們可以跟蹤鼠標點擊和光標位置,位置顯示為-1到1之間的值。
雙擊是通過 mouseUpFrames 實現(xiàn)的。mousePressed 變量只在玩家第一次點擊開始游戲時使用這么一次。
這個游戲使用了一些函數(shù)來簡化代碼和減少重復(fù),一些標準的數(shù)學(xué)函數(shù)用于 Clamp 和 Lerp 值。 ClampAngle 是有用的,因為它在 -PI 和 PI 之間 wrap angles,在許多游戲中已經(jīng)廣泛應(yīng)用。
R函數(shù)就像個魔術(shù)師,因為它生成隨機數(shù),通過取當前隨機數(shù)種子的正弦,乘以一個大數(shù)字,然后看分數(shù)部分來實現(xiàn)的。其實有很多方法可以做到,但這是最小的方法之一,而且對我們來說也是足夠隨機。
我們將使用這個隨機生成器來創(chuàng)建各種程序,且不需要保存任何數(shù)據(jù)。例如,山脈、巖石和樹木的變化不用存到內(nèi)存。在這種情況下,目標不是減少內(nèi)存,而是去除存儲和檢索數(shù)據(jù)所需的代碼。
因為這是一個“真正的3D”游戲,所以有一個 3D vector class 非常有用,它也能減少代碼量。這個 class 只包含這個游戲必需的基本元素,一個帶有加法和乘法函數(shù)的 constructor 可以接受標量或向量參數(shù)。為了確定標量是否被傳入,我們只需檢查它是否小于一個大數(shù)。更正確的方法是使用 isNan 或者檢查它的類型是否是 Vec3,但是這需要更多的存儲。
LSHA 通過模板字符串生成一組標準的 HSLA (色調(diào)、飽和度、亮度、alpha)顏色,并且剛剛被重新排序,所以更常用的 component 排在第一位。每過一關(guān)換一個整體色調(diào)也是通過這設(shè)置的。
DrawPoly 繪制一個梯形形狀,用于渲染場景中的一切。使用 |0 將 Ycomponent 轉(zhuǎn)換為整數(shù),以確保每段多邊形道路都能無縫連接,不然路段之間就會有一條細線。
DrawText 則用于顯示時間、距離和游戲標題等文本渲染。
首先,我們必須生成完整的軌道,而且準備做到每次游戲軌道都是不同的。如何做呢?我們建立了一個道路段列表,存儲道路在軌道上每一關(guān)卡的位置和寬度。軌道生成器是非?;A(chǔ)的操作,不同頻率、振幅和寬度的道路都會逐漸變窄,沿著跑道的距離決定這一段路有多難。
atan2 函數(shù)可以用來計算道路俯仰角,據(jù)此來設(shè)計物理運動和光線。
現(xiàn)在跑道就緒,我們只需要預(yù)置一些變量就可以開始游戲了。
這是主要的更新功能,用來更新和渲染游戲中的一切!一般來說,如果你的代碼中有一個很大的函數(shù),這不是好事,為了更簡潔易懂,我們會把它分幾個成子函數(shù)。
首先,我們需要得到一些玩家所在位置的道路信息。為了使物理和渲染感覺平滑,需要在當前和下一個路段之間插入一些數(shù)值。
玩家的位置和速度是 3D 向量,并受重力、dampening 和其他因素等影響更新。如果玩家跑在地面上時,會受到加速度影響;當他離開這段路時,攝像機還會抖動。另外,在對游戲測試后,我決定讓玩家在空中時仍然可以跑。
接下來要處理輸入指令,涉及加速、剎車、跳躍和轉(zhuǎn)彎等操作。雙擊通過 mouseUpFrames 測試。還有一些代碼是來跟蹤玩家在空中停留了多少幀,如果時間很短,游戲允許玩家還可以跳躍。
當玩家加速、剎車和跳躍時,我通過spring system展示相機的俯仰角以給玩家動態(tài)運動的感覺。此外,當玩家駕車翻越山丘或跳躍時,相機還會隨著道路傾斜而傾斜。
在渲染之前,canvas 每當高度或?qū)挾缺恢卦O(shè)時,畫布內(nèi)容就會被清空。這也適用于自適應(yīng)窗口的畫布。
我們還計算了將世界點轉(zhuǎn)換到畫布的投影比例。cameraDepth 值代表攝像機的視場(FOV)。這個游戲是90度。計算結(jié)果是 1/Math.tan(fovRadians/2) ,F(xiàn)OV 是90度的時候,計算結(jié)果正好是1。另外為了保持屏幕長寬比,投影按 c.width 縮放。
空氣背景是用全屏的 linear gradient (徑向漸變)繪制的,它還會根據(jù)太陽的位置改變顏色。
為了節(jié)省存儲空間,太陽和月亮在同一個循環(huán)中,使用了一個帶有透明度的全屏 radial gradient(線性漸變)。
線性和徑向漸變相結(jié)合,形成一個完全包圍場景的天空背景。
山脈是通過在地平線上畫50個三角形,然后根據(jù)程序自己生成的。
因為用了光線照明,山脈在面對太陽時會更暗,因為它們處于陰影中。此外,越近的山脈顏色越暗,我想以此來模擬霧氣。這里我有個訣竅,就是微調(diào)大小和顏色的隨機值。
背景的最后一部分是繪制地平線,再用純綠填充畫布的底部。
在渲染道路之前,我們必須首先獲得投影的道路點。第一部分有點棘手,因為我們的道路的 x 值需要轉(zhuǎn)換成世界空間位置。為了使道路看起來蜿蜒曲折,我們把x值作為二階導(dǎo)數(shù)。這就是為什么有奇怪的代碼“x+=w+=”出現(xiàn)的原因。由于這種工作方式,路段沒有固定的世界空間位置,每一幀都是根據(jù)玩家的位置重新計算。
一旦我們有了世界空間位置,我們就可以從道路位置中知道玩家的位置,從而得到本地攝像機空間位置。代碼的其余部分,首先通過旋轉(zhuǎn)標題、俯仰角來應(yīng)用變換,然后通過投影變換,做到近大遠小的效果,最后將其移動到畫布空間。
現(xiàn)在我們有了每個路段的畫布空間點,渲染就相當簡單了。我們需要從后向前畫出每一個路段,或者更具體地說,連接上一路段的梯形多邊形。
為了創(chuàng)建道路,這里有4層渲染:地面,條紋路邊緣,道路本身和白色虛線。每一個都是基于路段的俯仰角和方向來加陰影,并且根據(jù)該層的表現(xiàn)還有一些額外的邏輯。
有必要檢查路段是在近還是遠剪輯范圍,以防止渲染出現(xiàn) bug 。此外,還有一個很好的優(yōu)化方法是,當?shù)缆纷兊煤苷瓡r,可以通過 distance 來減小道路的分辨率。如此,不僅減少了 draw count 一半以上,而且沒有明顯的質(zhì)量損失,這是一次性能勝利。
游戲有兩種不同類型的物體:樹和石頭。首先,我們通過使用 R 函數(shù)來確定是否加一個對象。這是隨機數(shù)和隨機數(shù)種子特別有意思的地方。我們還將使用 R 為對象隨機添加不同的形狀和顏色。
最初我還想涉及其他車型,但為了達到 2KB 的要求,必須要進行特別多的削減,因此我最后放棄了這個想法,用風(fēng)景作為障礙。這些位置是隨機的,也比較靠近道路,不然它們太稀疏,就很容易行駛。為了節(jié)省空間,對象高度還決定了對象的類型。
這是通過比較玩家和物體在 3D 空間中的位置來檢查它們之間的碰撞位置。當玩家撞到一個物體時,玩家減速,該物體被標記為“ hit ”,這樣它就可以安全通過。
為了防止對象突然出現(xiàn)在地平線上,透明度會隨著距離的接近而削弱。梯形繪圖函數(shù)定義物體的形狀和顏色,另外隨機函數(shù)會改變這兩個屬性。
游戲的標題、時間和距離是用一個非?;A(chǔ)的字體渲染系統(tǒng)顯示出來的,就是之前設(shè)置的 DrawText 函數(shù)。在玩家點擊鼠標之前,它會在屏幕中央顯示標題。
按下鼠標后,游戲開始,然后 HUD 會顯示剩余時間和當前距離。時間也在這塊更新,玩過此類游戲的都知道,時間只在比賽開始后減少。
在這個 massive Update function 結(jié)束后,它調(diào)用 requestAnimationFrame (Update) 來觸發(fā)下一次更新。
HTML 需要一個結(jié)束腳本標簽來讓所有的代碼能夠跑起來。
這就是整個游戲啦!下方的一小段代碼就是壓縮后的最終結(jié)果,我用不同的顏色標注了不同的部分。完成所有這些工作后,你能感受到我在2KB內(nèi)就做完了整個游戲是多么讓我滿意了嗎?而這還是在zip之前的工作,zip還可以進一步壓縮大小。
當然,還有很多其他 3D 渲染方法可以同時保證性能和視覺效果。如果我有更多的可用空間,我會更傾向于使用一個 WebGL API 比如 three.js ,我在去年制作的一個類似游戲“Bogus Roads”中用過這個框架。此外,因為它使用的是 requestAnimationFrame ,所以需要一些額外的代碼來確保幀速率不超過60 fps,增強版本中我會這么用,盡管我更喜歡使用 requestAnimationFrame 而不是 setInterval ,因為它是垂直同期的(VSyn,VerticalSynchronization),所以渲染更絲滑。這種代碼的一個主要好處是它非常兼容,可以在任何設(shè)備上運行,盡管在我舊 iPhone 上運行有點慢。
游戲代碼被我放到了 GitHub 上的 GPL-3.0 下(
https://github.com/KilledByAPixel/HueJumper2k),所以你可以在自己的項目中自由使用它。該庫中還包含 2KB 版本的游戲,準確說是2031字節(jié)!歡迎你添加一些其他的功能,比如音樂和音效到“增強”版本中。
雷鋒網(wǎng)注意到,F(xiàn)rank Force 在個人博客發(fā)了這篇文章后,在內(nèi)容、標題的加持下,這篇文章后來被不少國外媒體轉(zhuǎn)載。在盛贊之余,也有質(zhì)疑的聲音。網(wǎng)友“Anon”在原文下評論:你是如何在 2KB 安裝一個完整的 javascript 的,除非你可以隨意忽略 dependencies 插件庫的大小,或者你將整個游戲作為 dependency,大小才有可能控制到 2KB,否則就是欺騙。
Frank 回復(fù)表示,大多數(shù) small demos 都需要某種運行環(huán)境,即使它是可執(zhí)行的。在這種情況下,就是 javascript 運行時環(huán)境,沒有其他 dependencies.。因為 javascript 是解釋的,所以也可以說壓縮后的代碼是在2KB以內(nèi)的。
雷鋒網(wǎng)發(fā)現(xiàn),有其他網(wǎng)友表示認可 Frank 的說法,他們認為 JS 是一種解釋語言,不能將其與其他編譯語言相比較。
雷鋒網(wǎng)
熱門資訊
探討游戲引擎的文章,介紹了10款游戲引擎及其代表作品,涵蓋了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戲設(shè)計領(lǐng)域和數(shù)字藝術(shù)教育的重要性,歡迎點擊咨詢報名。
2. 手機游戲如何開發(fā)(如何制作傳奇手游,都需要準備些什么?)
?如何制作傳奇手游,都需要準備些什么?提到傳奇手游相信大家都不陌生,他是許多80、90后的回憶;從起初的端游到現(xiàn)在的手游,說明時代在進步游戲在更新,更趨于方便化移動化。而如果我們想要制作一款傳奇手游的
3. B站視頻剪輯軟件「必剪」:免費、炫酷特效,小白必備工具
B站視頻剪輯軟件「必剪」,完全免費、一鍵制作炫酷特效,適合新手小白??靵碓囋嚕?/span>
游戲中玩家將面臨武俠人生的掙扎抉擇,戰(zhàn)或降?殺或放?每個抉定都將觸發(fā)更多愛恨糾葛的精彩奇遇?!短烀嬗肪哂卸嗑€劇情多結(jié)局,不限主線發(fā)展,高自由...
5. Bigtime加密游戲經(jīng)濟體系揭秘,不同玩家角色的經(jīng)濟活動
Bigtime加密游戲經(jīng)濟模型分析,探討游戲經(jīng)濟特點,幫助玩家更全面了解這款GameFi產(chǎn)品。
6. 3D動畫軟件你知道幾個?3ds Max、Blender、Maya、Houdini大比拼
當提到3D動畫軟件或動畫工具時,指的是數(shù)字內(nèi)容創(chuàng)建工具。它是用于造型、建模以及繪制3D美術(shù)動畫的軟件程序。但是,在3D動畫軟件中還包含了其他類型的...
7. 3D動漫建模全過程,不是一般人能學(xué)的會的,會的多不是人?
步驟01:面部,頸部,身體在一起這次我不準備設(shè)計圖片,我從雕刻進入。這一次,它將是一種純粹關(guān)注建模而非整體繪畫的形式。像往常一樣,我從Sphere創(chuàng)建它...
8. 如何自己開發(fā)一款游戲(游戲開發(fā)入門必看:五大獨立游戲開發(fā)技巧)
?游戲開發(fā)入門必看:五大獨立游戲開發(fā)技巧無論您是剛剛起步開發(fā)自己的第一款游戲,還是已經(jīng)制作了幾款游戲,本篇文章中的5大獨立游戲開發(fā)技巧都可以幫助您更好地設(shè)計下一款游戲。無論你對游戲有著什么樣的概念,都
?三昧動漫對于著名ARPG游戲《巫師》系列,最近CD Projekt 的高層回應(yīng)并不會推出《巫師4》。因為《巫師》系列在策劃的時候一直定位在“三部曲”的故事框架,所以在游戲的出品上不可能出現(xiàn)《巫師4》
10. 3D打印技巧揭秘!Cura設(shè)置讓你的模型更堅固
想讓你的3D打印模型更堅固?不妨嘗試一下Cura參數(shù)設(shè)置和設(shè)計技巧,讓你輕松掌握!
最新文章
同學(xué)您好!