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