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

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

javascript能開發(fā)游戲嗎(如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?)

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

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

javascript能開發(fā)游戲嗎(如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?)

幾個月前,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)評論進行了不改變原意的編譯:

javascript能開發(fā)游戲嗎(如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?)

因為嚴格的大小限制,我需要非常仔細對待我的程序。我的總體策略是盡可能保持一切簡單,為最終目標服務(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)

javascript能開發(fā)游戲嗎(如何用不到 2KB 的 JavaScript 代碼寫一個 3D 賽車游戲?)

熱門課程推薦

熱門資訊

請綁定手機號

x

同學(xué)您好!

您已成功報名0元試學(xué)活動,老師會在第一時間與您取得聯(lián)系,請保持電話暢通!
確定