激情六月丁香婷婷|亚洲色图AV二区|丝袜AV日韩AV|久草视频在线分类|伊人九九精品视频|国产精品一级电影|久草视频在线99|在线看的av网址|伊人99精品无码|午夜无码视频在线

高校合作1:010-59833514 ?咨詢(xún)電話:400-810-1418 服務(wù)與監(jiān)督電話:400-810-1418轉(zhuǎn)接2

javascript能開(kāi)發(fā)游戲嗎(如何用不到 2KB 的 JavaScript 代碼寫(xiě)一個(gè) 3D 賽車(chē)游戲?)

發(fā)布時(shí)間:2023-11-27 13:12:02 瀏覽量:127次

?如何用不到 2KB 的 JavaScript 代碼寫(xiě)一個(gè) 3D 賽車(chē)游戲?

javascript能開(kāi)發(fā)游戲嗎(如何用不到 2KB 的 JavaScript 代碼寫(xiě)一個(gè) 3D 賽車(chē)游戲?)

幾個(gè)月前,JS1k游戲制作節(jié)(JS1K game jam)傳出不再舉辦消息后,許多游戲迷開(kāi)始哀嚎。

Frank Force 也是其中一位,但他還有另一層身份——一位德克薩斯州奧斯汀的獨(dú)立游戲設(shè)計(jì)師。Frank Force 在游戲行業(yè)工作了20年,參與過(guò)9款主流游戲、47個(gè)獨(dú)立游戲的設(shè)計(jì)。在聽(tīng)到這個(gè)消息后,他馬上和其他開(kāi)發(fā)朋友討論了這個(gè)問(wèn)題,并決定做點(diǎn)什么為此紀(jì)念。

在此期間,他們受到三重因素的啟發(fā)。一是賽車(chē)游戲,包括懷舊向的80年代賽車(chē)游戲,他們?cè)诜浅T缙诘挠布贤苿?dòng)實(shí)時(shí) 3D 圖形,所以作者沿用了相同的技術(shù),用純 JavaScript 從頭開(kāi)始實(shí)現(xiàn)做 3D 圖形和物理引擎;還有一些現(xiàn)代賽車(chē)游戲帶來(lái)了視覺(jué)設(shè)計(jì)的靈感,比如《Distance》和《Lonely Mountains: Downhill》;二是之前 Jake Gordon 用 JavaScript 創(chuàng)建一個(gè)虛擬3D賽車(chē)的項(xiàng)目,并分享了代碼;三是 Chris Glover 曾經(jīng)做過(guò)一款小到只有 1KB 的 JS1k 賽車(chē)游戲《Moto1kross by Chris Glover》。

于是 Frank 和他的朋友們決定做一個(gè)壓縮后只有 2KB 的 3D 賽車(chē)游戲。2KB 到底有多小呢?提供一個(gè)參考,一個(gè)3.5英寸軟盤(pán)可以容納700多個(gè)這樣的游戲。

他給這個(gè)游戲取名 Hue Jumper。關(guān)于名字的由來(lái),F(xiàn)rank 表示,游戲的核心操作是移動(dòng)。當(dāng)玩家通過(guò)一個(gè)關(guān)卡時(shí),游戲世界就會(huì)換一個(gè)顏色色調(diào)?!霸谖蚁胂笾?,每通過(guò)過(guò)一個(gè)關(guān)卡,玩家都會(huì)跳轉(zhuǎn)到另一個(gè)維度,有著完全不同的色調(diào)?!?/p>

做完這個(gè)游戲后,F(xiàn)rank 將包含了游戲的全部 JavaScript 代碼都發(fā)布在他的個(gè)人博客上,其中用到的軟件主要也是免費(fèi)或開(kāi)源軟件的。游戲代碼發(fā)布在CodePen,可以在 iframe 中試玩,有興趣的朋友可以去看看。

以下是原博內(nèi)容,AI源創(chuàng)評(píng)論進(jìn)行了不改變?cè)獾木幾g:

javascript能開(kāi)發(fā)游戲嗎(如何用不到 2KB 的 JavaScript 代碼寫(xiě)一個(gè) 3D 賽車(chē)游戲?)

因?yàn)閲?yán)格的大小限制,我需要非常仔細(xì)對(duì)待我的程序。我的總體策略是盡可能保持一切簡(jiǎn)單,為最終目標(biāo)服務(wù)。

為了幫助壓縮代碼,我使用了 Google Closure Compiler,它刪除了所有空格,將變量重命名為1個(gè)字母字符,并進(jìn)行了一些輕量級(jí)優(yōu)化。

用戶可以通過(guò) Google Closure Compiler 官網(wǎng)在線跑代碼。不幸的是,Closure Compiler 做了一些沒(méi)有幫助的事情,比如替換模板字符串、默認(rèn)參數(shù)和其他幫助節(jié)省空間的ES6特性。所以我需要手動(dòng)撤銷(xiāo)其中一些事情,并執(zhí)行一些更“危險(xiǎn)”的壓縮技術(shù)來(lái)擠出最后一個(gè)字節(jié)空間。在壓縮方面,這不算很成功,大部分?jǐn)D出的空間來(lái)自代碼本身的結(jié)構(gòu)優(yōu)化。

代碼需要壓縮到2KB。如果不是非要這么做不可,有一個(gè)類(lèi)似的但功能沒(méi)那么強(qiáng)的工具叫做 RegPack 。

無(wú)論哪種方式,策略都是一樣的:盡最大可能重復(fù)代碼,然后用壓縮工具壓縮。最好的例子是 c.width,c.height和 Math。因此,在閱讀這段代碼時(shí),請(qǐng)記住,你經(jīng)常會(huì)看到我不斷重復(fù)一些東西,最終目的就是為了壓縮。

其實(shí)我的游戲很少使用 html ,因?yàn)樗饕玫降氖?JavaScript 。但這是創(chuàng)建全屏畫(huà)布 Canvas ,也能將畫(huà)布 Canvas 設(shè)為窗口內(nèi)部大小的代碼最小方法。我不知道為什么在 CodePen 上有必要添加 overflow:hiddento the body,當(dāng)直接打開(kāi)時(shí)按理說(shuō)也可以運(yùn)行。

我將 JavaScript 封裝在一個(gè) onload 調(diào)用,得到了一個(gè)更小的最終版本… 但是,在開(kāi)發(fā)過(guò)程中,我不喜歡用這個(gè)壓縮設(shè)置,因?yàn)榇a存儲(chǔ)在一個(gè)字符串中,所以編輯器不能正確地高亮顯示語(yǔ)法。

有許多常量在各方面控制著游戲。當(dāng)代碼被 Google Closure 這樣的工具縮小時(shí),這些常量將被替換,就像 C++ 中的 #define 一樣,把它們放在第一位會(huì)加快游戲微調(diào)的過(guò)程。

鼠標(biāo)是唯一的輸入系統(tǒng)。通過(guò)這段代碼,我們可以跟蹤鼠標(biāo)點(diǎn)擊和光標(biāo)位置,位置顯示為-1到1之間的值。

雙擊是通過(guò) mouseUpFrames 實(shí)現(xiàn)的。mousePressed 變量只在玩家第一次點(diǎn)擊開(kāi)始游戲時(shí)使用這么一次。

這個(gè)游戲使用了一些函數(shù)來(lái)簡(jiǎn)化代碼和減少重復(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ù),通過(guò)取當(dāng)前隨機(jī)數(shù)種子的正弦,乘以一個(gè)大數(shù)字,然后看分?jǐn)?shù)部分來(lái)實(shí)現(xiàn)的。其實(shí)有很多方法可以做到,但這是最小的方法之一,而且對(duì)我們來(lái)說(shuō)也是足夠隨機(jī)。

我們將使用這個(gè)隨機(jī)生成器來(lái)創(chuàng)建各種程序,且不需要保存任何數(shù)據(jù)。例如,山脈、巖石和樹(shù)木的變化不用存到內(nèi)存。在這種情況下,目標(biāo)不是減少內(nèi)存,而是去除存儲(chǔ)和檢索數(shù)據(jù)所需的代碼。

因?yàn)檫@是一個(gè)“真正的3D”游戲,所以有一個(gè) 3D vector class 非常有用,它也能減少代碼量。這個(gè) class 只包含這個(gè)游戲必需的基本元素,一個(gè)帶有加法和乘法函數(shù)的 constructor 可以接受標(biāo)量或向量參數(shù)。為了確定標(biāo)量是否被傳入,我們只需檢查它是否小于一個(gè)大數(shù)。更正確的方法是使用 isNan 或者檢查它的類(lèi)型是否是 Vec3,但是這需要更多的存儲(chǔ)。

LSHA 通過(guò)模板字符串生成一組標(biāo)準(zhǔn)的 HSLA (色調(diào)、飽和度、亮度、alpha)顏色,并且剛剛被重新排序,所以更常用的 component 排在第一位。每過(guò)一關(guān)換一個(gè)整體色調(diào)也是通過(guò)這設(shè)置的。

DrawPoly 繪制一個(gè)梯形形狀,用于渲染場(chǎng)景中的一切。使用 |0 將 Ycomponent 轉(zhuǎn)換為整數(shù),以確保每段多邊形道路都能無(wú)縫連接,不然路段之間就會(huì)有一條細(xì)線。

DrawText 則用于顯示時(shí)間、距離和游戲標(biāo)題等文本渲染。

首先,我們必須生成完整的軌道,而且準(zhǔn)備做到每次游戲軌道都是不同的。如何做呢?我們建立了一個(gè)道路段列表,存儲(chǔ)道路在軌道上每一關(guān)卡的位置和寬度。軌道生成器是非?;A(chǔ)的操作,不同頻率、振幅和寬度的道路都會(huì)逐漸變窄,沿著跑道的距離決定這一段路有多難。

atan2 函數(shù)可以用來(lái)計(jì)算道路俯仰角,據(jù)此來(lái)設(shè)計(jì)物理運(yùn)動(dòng)和光線。

現(xiàn)在跑道就緒,我們只需要預(yù)置一些變量就可以開(kāi)始游戲了。

這是主要的更新功能,用來(lái)更新和渲染游戲中的一切!一般來(lái)說(shuō),如果你的代碼中有一個(gè)很大的函數(shù),這不是好事,為了更簡(jiǎn)潔易懂,我們會(huì)把它分幾個(gè)成子函數(shù)。

首先,我們需要得到一些玩家所在位置的道路信息。為了使物理和渲染感覺(jué)平滑,需要在當(dāng)前和下一個(gè)路段之間插入一些數(shù)值。

玩家的位置和速度是 3D 向量,并受重力、dampening 和其他因素等影響更新。如果玩家跑在地面上時(shí),會(huì)受到加速度影響;當(dāng)他離開(kāi)這段路時(shí),攝像機(jī)還會(huì)抖動(dòng)。另外,在對(duì)游戲測(cè)試后,我決定讓玩家在空中時(shí)仍然可以跑。

接下來(lái)要處理輸入指令,涉及加速、剎車(chē)、跳躍和轉(zhuǎn)彎等操作。雙擊通過(guò) mouseUpFrames 測(cè)試。還有一些代碼是來(lái)跟蹤玩家在空中停留了多少幀,如果時(shí)間很短,游戲允許玩家還可以跳躍。

當(dāng)玩家加速、剎車(chē)和跳躍時(shí),我通過(guò)spring system展示相機(jī)的俯仰角以給玩家動(dòng)態(tài)運(yùn)動(dòng)的感覺(jué)。此外,當(dāng)玩家駕車(chē)翻越山丘或跳躍時(shí),相機(jī)還會(huì)隨著道路傾斜而傾斜。

在渲染之前,canvas 每當(dāng)高度或?qū)挾缺恢卦O(shè)時(shí),畫(huà)布內(nèi)容就會(huì)被清空。這也適用于自適應(yīng)窗口的畫(huà)布。

我們還計(jì)算了將世界點(diǎn)轉(zhuǎn)換到畫(huà)布的投影比例。cameraDepth 值代表攝像機(jī)的視場(chǎng)(FOV)。這個(gè)游戲是90度。計(jì)算結(jié)果是 1/Math.tan(fovRadians/2) ,F(xiàn)OV 是90度的時(shí)候,計(jì)算結(jié)果正好是1。另外為了保持屏幕長(zhǎng)寬比,投影按 c.width 縮放。

空氣背景是用全屏的 linear gradient (徑向漸變)繪制的,它還會(huì)根據(jù)太陽(yáng)的位置改變顏色。

為了節(jié)省存儲(chǔ)空間,太陽(yáng)和月亮在同一個(gè)循環(huán)中,使用了一個(gè)帶有透明度的全屏 radial gradient(線性漸變)。

線性和徑向漸變相結(jié)合,形成一個(gè)完全包圍場(chǎng)景的天空背景。

山脈是通過(guò)在地平線上畫(huà)50個(gè)三角形,然后根據(jù)程序自己生成的。

因?yàn)橛昧斯饩€照明,山脈在面對(duì)太陽(yáng)時(shí)會(huì)更暗,因?yàn)樗鼈兲幱陉幱爸小4送?,越近的山脈顏色越暗,我想以此來(lái)模擬霧氣。這里我有個(gè)訣竅,就是微調(diào)大小和顏色的隨機(jī)值。

背景的最后一部分是繪制地平線,再用純綠填充畫(huà)布的底部。

在渲染道路之前,我們必須首先獲得投影的道路點(diǎn)。第一部分有點(diǎn)棘手,因?yàn)槲覀兊牡缆返?x 值需要轉(zhuǎn)換成世界空間位置。為了使道路看起來(lái)蜿蜒曲折,我們把x值作為二階導(dǎo)數(shù)。這就是為什么有奇怪的代碼“x+=w+=”出現(xiàn)的原因。由于這種工作方式,路段沒(méi)有固定的世界空間位置,每一幀都是根據(jù)玩家的位置重新計(jì)算。

一旦我們有了世界空間位置,我們就可以從道路位置中知道玩家的位置,從而得到本地?cái)z像機(jī)空間位置。代碼的其余部分,首先通過(guò)旋轉(zhuǎn)標(biāo)題、俯仰角來(lái)應(yīng)用變換,然后通過(guò)投影變換,做到近大遠(yuǎn)小的效果,最后將其移動(dòng)到畫(huà)布空間。

現(xiàn)在我們有了每個(gè)路段的畫(huà)布空間點(diǎn),渲染就相當(dāng)簡(jiǎn)單了。我們需要從后向前畫(huà)出每一個(gè)路段,或者更具體地說(shuō),連接上一路段的梯形多邊形。

為了創(chuàng)建道路,這里有4層渲染:地面,條紋路邊緣,道路本身和白色虛線。每一個(gè)都是基于路段的俯仰角和方向來(lái)加陰影,并且根據(jù)該層的表現(xiàn)還有一些額外的邏輯。

有必要檢查路段是在近還是遠(yuǎn)剪輯范圍,以防止渲染出現(xiàn) bug 。此外,還有一個(gè)很好的優(yōu)化方法是,當(dāng)?shù)缆纷兊煤苷瓡r(shí),可以通過(guò) distance 來(lái)減小道路的分辨率。如此,不僅減少了 draw count 一半以上,而且沒(méi)有明顯的質(zhì)量損失,這是一次性能勝利。

游戲有兩種不同類(lèi)型的物體:樹(shù)和石頭。首先,我們通過(guò)使用 R 函數(shù)來(lái)確定是否加一個(gè)對(duì)象。這是隨機(jī)數(shù)和隨機(jī)數(shù)種子特別有意思的地方。我們還將使用 R 為對(duì)象隨機(jī)添加不同的形狀和顏色。

最初我還想涉及其他車(chē)型,但為了達(dá)到 2KB 的要求,必須要進(jìn)行特別多的削減,因此我最后放棄了這個(gè)想法,用風(fēng)景作為障礙。這些位置是隨機(jī)的,也比較靠近道路,不然它們太稀疏,就很容易行駛。為了節(jié)省空間,對(duì)象高度還決定了對(duì)象的類(lèi)型。

這是通過(guò)比較玩家和物體在 3D 空間中的位置來(lái)檢查它們之間的碰撞位置。當(dāng)玩家撞到一個(gè)物體時(shí),玩家減速,該物體被標(biāo)記為“ hit ”,這樣它就可以安全通過(guò)。

為了防止對(duì)象突然出現(xiàn)在地平線上,透明度會(huì)隨著距離的接近而削弱。梯形繪圖函數(shù)定義物體的形狀和顏色,另外隨機(jī)函數(shù)會(huì)改變這兩個(gè)屬性。

游戲的標(biāo)題、時(shí)間和距離是用一個(gè)非?;A(chǔ)的字體渲染系統(tǒng)顯示出來(lái)的,就是之前設(shè)置的 DrawText 函數(shù)。在玩家點(diǎn)擊鼠標(biāo)之前,它會(huì)在屏幕中央顯示標(biāo)題。

按下鼠標(biāo)后,游戲開(kāi)始,然后 HUD 會(huì)顯示剩余時(shí)間和當(dāng)前距離。時(shí)間也在這塊更新,玩過(guò)此類(lèi)游戲的都知道,時(shí)間只在比賽開(kāi)始后減少。

在這個(gè) massive Update function 結(jié)束后,它調(diào)用 requestAnimationFrame (Update) 來(lái)觸發(fā)下一次更新。

HTML 需要一個(gè)結(jié)束腳本標(biāo)簽來(lái)讓所有的代碼能夠跑起來(lái)。

這就是整個(gè)游戲啦!下方的一小段代碼就是壓縮后的最終結(jié)果,我用不同的顏色標(biāo)注了不同的部分。完成所有這些工作后,你能感受到我在2KB內(nèi)就做完了整個(gè)游戲是多么讓我滿意了嗎?而這還是在zip之前的工作,zip還可以進(jìn)一步壓縮大小。

當(dāng)然,還有很多其他 3D 渲染方法可以同時(shí)保證性能和視覺(jué)效果。如果我有更多的可用空間,我會(huì)更傾向于使用一個(gè) WebGL API 比如 three.js ,我在去年制作的一個(gè)類(lèi)似游戲“Bogus Roads”中用過(guò)這個(gè)框架。此外,因?yàn)樗褂玫氖?requestAnimationFrame ,所以需要一些額外的代碼來(lái)確保幀速率不超過(guò)60 fps,增強(qiáng)版本中我會(huì)這么用,盡管我更喜歡使用 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)目中自由使用它。該庫(kù)中還包含 2KB 版本的游戲,準(zhǔn)確說(shuō)是2031字節(jié)!歡迎你添加一些其他的功能,比如音樂(lè)和音效到“增強(qiáng)”版本中。

雷鋒網(wǎng)注意到,F(xiàn)rank Force 在個(gè)人博客發(fā)了這篇文章后,在內(nèi)容、標(biāo)題的加持下,這篇文章后來(lái)被不少?lài)?guó)外媒體轉(zhuǎn)載。在盛贊之余,也有質(zhì)疑的聲音。網(wǎng)友“Anon”在原文下評(píng)論:你是如何在 2KB 安裝一個(gè)完整的 javascript 的,除非你可以隨意忽略 dependencies 插件庫(kù)的大小,或者你將整個(gè)游戲作為 dependency,大小才有可能控制到 2KB,否則就是欺騙。

Frank 回復(fù)表示,大多數(shù) small demos 都需要某種運(yùn)行環(huán)境,即使它是可執(zhí)行的。在這種情況下,就是 javascript 運(yùn)行時(shí)環(huán)境,沒(méi)有其他 dependencies.。因?yàn)?javascript 是解釋的,所以也可以說(shuō)壓縮后的代碼是在2KB以?xún)?nèi)的。

雷鋒網(wǎng)發(fā)現(xiàn),有其他網(wǎng)友表示認(rèn)可 Frank 的說(shuō)法,他們認(rèn)為 JS 是一種解釋語(yǔ)言,不能將其與其他編譯語(yǔ)言相比較。

雷鋒網(wǎng)

javascript能開(kāi)發(fā)游戲嗎(如何用不到 2KB 的 JavaScript 代碼寫(xiě)一個(gè) 3D 賽車(chē)游戲?)

熱門(mén)課程推薦

熱門(mén)資訊

請(qǐng)綁定手機(jī)號(hào)

x

同學(xué)您好!

您已成功報(bào)名0元試學(xué)活動(dòng),老師會(huì)在第一時(shí)間與您取得聯(lián)系,請(qǐng)保持電話暢通!
確定