欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Node.js實(shí)現(xiàn)一個多人游戲服務(wù)器引擎

 更新時間:2019年03月13日 10:58:45   作者:瘋狂的技術(shù)宅  
這篇文章主要給大家介紹了關(guān)于如何使用Node.js實(shí)現(xiàn)一個多人游戲服務(wù)器引擎的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用Node.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

摘要

聽說過文字冒險(xiǎn)游戲嗎? 如果你的年齡足夠大的話(就像我一樣),那么你可能聽說過、甚至玩過“back in the day”。在本文中,我將向你展示編寫的整個過程。這不僅僅是一個文本冒險(xiǎn)游戲,而是一個能讓你和你的朋友們一起玩的,可以進(jìn)行任何劇情的文本冒險(xiǎn)游戲引擎。 沒錯,我們將通過在添加多人游戲功能來增加它的趣味性。

文字冒險(xiǎn)是最早的 RPG 形式的游戲之一,回到還沒有圖形畫面的時代,你只能通過閱讀 CRT 顯示器上黑色背景下的描述,并且依賴自己的想象力來推動游戲劇情的發(fā)展。

如果要懷舊的話,可能世界上第一個文字冒險(xiǎn)游戲名叫 Colossal Cave Adventure(也許是叫 Adventure)。

文字冒險(xiǎn)游戲 back in the day 的畫面

上圖是你實(shí)際看到的游戲畫面,這與我們現(xiàn)在的頂級 AAA 冒險(xiǎn)游戲相差甚遠(yuǎn)。 盡管如此,但是他們玩起來卻很有趣,并會很容易的消磨你幾百個小時的時間,因?yàn)橹挥心阕约鹤约鹤陲@示器前,試圖找到打穿它的途徑。

可以理解的是,多年以來,文字冒險(xiǎn)已經(jīng)被更好的視覺效果所取代,特別是在過去幾年里,游戲的協(xié)作性越強(qiáng),你可以和朋友們一起玩。 這是原始的文字冒險(xiǎn)游戲所缺少的,同時也是我想在本文中提到的功能。

我們的目標(biāo)

可能你已經(jīng)從標(biāo)題中猜到了,本文的重點(diǎn)在于創(chuàng)建一個文字冒險(xiǎn)引擎,并且讓你和朋友們一起玩,使你能夠與他們進(jìn)行協(xié)作,就像在玩“龍與地下城”這個游戲一樣。

在創(chuàng)建引擎時,聊天服務(wù)器和客戶端的工作了相當(dāng)大。 在本文中,我將向你展示設(shè)計(jì)思路、解釋引擎背后的架構(gòu)、客戶端如何與服務(wù)器交互以及這個游戲的規(guī)則。

為了讓你對我的目標(biāo)又一個直觀的感受,先上一張圖:

游戲客戶端的 UI 設(shè)計(jì)

這就是我們的目標(biāo)。 一旦達(dá)成這個目標(biāo),將會得到截圖而不是簡單和骯臟的模型。 所以,需要了解這個過程。首先要介紹的就是整體設(shè)計(jì);然后介紹我將用來編碼的相關(guān)工具;最后我將向你展示一些核心代碼(當(dāng)然,還有指向完整代碼庫的鏈接)。

希望到最后,你能夠自己創(chuàng)造一個新的文字冒險(xiǎn)游戲,并與朋友一起樂在其中!

設(shè)計(jì)階段

在設(shè)計(jì)階段,我將描述這個游戲的整體藍(lán)圖。 我會盡力不讓你覺得無聊,不過我認(rèn)為在給你展示第一行代碼之前,很有必要先搞清楚幕后的一些工作。

我想接下來介紹的這四個組件能夠提供相當(dāng)多的細(xì)節(jié):

  • 引擎
    • 這將成為游戲的主服務(wù)器。游戲規(guī)則會在這里實(shí)現(xiàn),它將為任何類型的客戶端提供技術(shù)無關(guān)接口。本項(xiàng)目中我們將實(shí)現(xiàn)終端類型的客戶端,但是你可以用Web客戶端或者你喜歡的任何其他類型。
  • 聊天服務(wù)器
    • 因?yàn)樗膹?fù)雜性足以再寫一篇文章了,所以這項(xiàng)服務(wù)也會擁有自己的模塊。聊天服務(wù)器負(fù)責(zé)讓玩家在游戲的過程中彼此通信。
  • 客戶端
    • 如前文所述,這將是一個終端類型的客戶端,在理想情況下,它看起來與之前的模型類似。它將利用引擎和聊天服務(wù)器所提供的服務(wù)。
  • 游戲( JSON文件 )
    • 最后,我將介紹實(shí)際游戲的定義。這部分的重點(diǎn)是創(chuàng)建一個可以運(yùn)行任何游戲的引擎,只要你的游戲文件符合引擎的要求即可。所以,即使這不需要編碼,我也將解釋如何構(gòu)建冒險(xiǎn)文件以便將來編寫我們自己的冒險(xiǎn)規(guī)則。

引擎

游戲引擎或游戲服務(wù)器將會是REST API,并提供所有必需的功能。

我選擇REST API只是因?yàn)椋▽τ谶@種類型的游戲)HTTP造成的延遲以及他的異步特性不會造成任何麻煩。 但是,我們必須為聊天服務(wù)器采用不同的路線。 在開始定義 API 之前,先需要定義引擎的功能。 所以,讓我們來看看吧。

特性 描述
加入游戲 玩家可以通過指定的游戲ID來加入游戲。
創(chuàng)建一個新游戲 玩家還可以創(chuàng)建新的游戲?qū)嵗?引擎應(yīng)該返回一個ID,以便其他人可以使它來加入游戲。
返回場景 此功能應(yīng)返回玩家所在的當(dāng)前場景。 基本上,它將返回描述,包含所有相關(guān)信息(可能的操作、其中的對象等)。
與場景互動 這將是最復(fù)雜的一個,因?yàn)樗鼘目蛻舳双@取命令并執(zhí)行該操作——例如移動,攻擊,獲取,查看,讀取等等。
檢查庫存 雖然這是與游戲互動的一種方式,但它與場景并沒有直接關(guān)系。 因此,檢查每個玩家的庫存將被視為不同的操作。

關(guān)于移動

我們需要一種用來測量游戲中距離的方法,因?yàn)樵谟螒蛑型婕铱梢圆扇〉暮诵男袆又痪褪且苿印?我們需要用這個數(shù)字作為時間的衡量標(biāo)準(zhǔn),來簡化游戲的玩法。 考慮到這一類型的游戲具有基于回合的動作,例如戰(zhàn)斗,使用實(shí)際時鐘對時間進(jìn)行測量可能不是最好的。 所以我們將使用距離來測量時間(意味著距離為 8 比距離為 2 將需要更多的時間,從而允許我們做一些事情,例如為持續(xù)一定數(shù)量的“距離點(diǎn)”的玩家添加效果)。

考慮運(yùn)動的另一個原因是不是一個人在玩這個游戲。 為簡單起見,引擎不會讓玩家隨意組隊(duì)(雖然這對未來可能是一個有趣的改進(jìn))。 該模塊的初始版本只允許個人朝著大多數(shù)參與者決定的地方移動。因此,必須以協(xié)商一致的方式進(jìn)行移動,這意味著每一步行動都將等待大多數(shù)人在行動之前提出請求。

戰(zhàn)斗

戰(zhàn)斗是這種游戲另一個非常重要的方面,我們不得不考慮將它添加到引擎中,否則我們最終會失去一些樂趣。

說實(shí)話,這并不需要重新發(fā)明輪子?;诨睾现频慕M隊(duì)對戰(zhàn)已經(jīng)存在了幾十年,所以在這里只實(shí)現(xiàn)這個機(jī)制的一個簡單版本。我們將把它與“龍與地下城”中的“主動性”這個概念混合起來,產(chǎn)生一個隨機(jī)數(shù)使戰(zhàn)斗更有活力。

換句話說,就是參與戰(zhàn)斗的每個人的行動順序?qū)浑S機(jī)化,其中包括敵人。

最后(雖然我將在下面詳細(xì)介紹這一點(diǎn)),你可以用設(shè)置的“攻擊力”值的物品。這些是你在戰(zhàn)斗中可以使用的道具;如果一個道具沒有這個屬性的話只能對敵人造成 0 點(diǎn)傷害。當(dāng)你試圖用這樣的道具進(jìn)行戰(zhàn)斗時,我們可能會添加一條消息,這樣你就能知道自己要做的事情是毫無意義的。

客戶端 - 服務(wù)器交互

現(xiàn)在來看看客戶端怎樣基于前面定義的功能與服務(wù)器進(jìn)行交互(目前還沒考慮端點(diǎn),不過馬上就會講到這個):

客戶端與服務(wù)器之間的交互

客戶端和服務(wù)器之間的初始交互(從服務(wù)器的角度來看)是一個新游戲的開始,其步驟如下:

  • 創(chuàng)建一個新游戲。
    • 客戶端請求向服務(wù)器創(chuàng)建新游戲。
  • 創(chuàng)建聊天室。
    • 雖然沒有明確說明,但是服務(wù)器不只是在聊天服務(wù)器中創(chuàng)建聊天室,而且還設(shè)置好了所需的一切,可以允許一組玩家進(jìn)行游戲。
  • 返回游戲的元數(shù)據(jù)。
    • 一旦服務(wù)器為玩家創(chuàng)建好了游戲和聊天室,那么客戶端會在后續(xù)請求用到這個信息。這是客戶端可以用來標(biāo)識自己和將要加入的游戲?qū)嵗囊唤MID。
  • 手動分享游戲ID 。
    • 這一步必須由玩家自己完成。我們可以提出某種共享機(jī)制,但我會將它留在愿望清單上等待將來改進(jìn)。
  • 加入游戲。
    • 這個非常簡單。每個人都有一個 ID,客戶端通過這個 ID 加入游戲。
  • 加入聊天室。
    • 最后,玩家的客戶端程序?qū)⑼ㄟ^游戲的元數(shù)據(jù)加入對應(yīng)的聊天室。這是游戲開始前的最后一步。一旦完成所有操作,玩家就可以開始在游戲中冒險(xiǎn)了!

游戲的動作指令

一旦滿足了先決條件,玩家就可以開始游戲,通過聊天室分享他們的想法,并推動故事的發(fā)展。上圖顯示了所需的四個步驟。

以下步驟將作為游戲循環(huán)的一部分來運(yùn)行,這意味著它們將會不斷重復(fù),一直到游戲結(jié)束。

  • 請求場景。
    • 客戶端程序?qū)⒄埱螽?dāng)前場景的元數(shù)據(jù)。這是循環(huán)每次迭代的第一步。
  • 返回元數(shù)據(jù)。
    • 服務(wù)器將發(fā)回當(dāng)前場景的元數(shù)據(jù)。這些信息中包括一般描述,從中可以找到的對象以及它們彼此之間的關(guān)系。
  • 發(fā)送命令。
    • 好戲開始。這是玩家的主要輸入方式。它包括玩家想要執(zhí)行的操作,以及可選的操作目標(biāo)(例如吹蠟燭、抓住巖石等)。
  • 對發(fā)來的命令做出響應(yīng)。
    • 這應(yīng)該屬于第二步,但為了清楚起見,我把它作為額外步驟。主要區(qū)別在于第二步可以被認(rèn)為是這個循環(huán)的開始,而這一步考慮到你已經(jīng)開始進(jìn)行游戲了,因此,服務(wù)器需要了解這個動作將影響誰(單個或所有玩家)。

作為額外步驟,雖然不是流程的一部分,但服務(wù)器將通知客戶端與它們相關(guān)的狀態(tài)的更新情況。

存在這個額外重復(fù)步驟的原因是玩家可以從其他玩家的動作中獲得更新。回想從一個地方移動另一個地方的需求;正如我之前所說那樣,一旦大多數(shù)玩家選擇了方向,那么所有玩家都會移動(不需要所有球員的輸入)。

不過 HTTP(前面已經(jīng)提到服務(wù)器為REST API)不允許這種類型的行為。所以,我們的選擇是:

  • 每隔 X 秒從客戶端輪詢,
  • 使用某種與客戶端-服務(wù)器連接通信機(jī)制并行工作的通知系統(tǒng)。

根據(jù)我的經(jīng)驗(yàn),我傾向于選擇選項(xiàng) 2。實(shí)際上,我會(在本文中)使用Redis來實(shí)現(xiàn)這種行為。

下圖演示了服務(wù)之間的依賴關(guān)系。

客戶端應(yīng)用程序與游戲引擎之間的交互

聊天服務(wù)器

我將把這個模塊的設(shè)計(jì)細(xì)節(jié)留給開發(fā)階段(本文不涉及這一部分)。話雖如此,我們?nèi)钥梢詻Q定一些事情。

我們可以確定的一件事是服務(wù)器的限制集合,這將簡化我們的工作。如果我們正確地玩牌,最終可能會有一個提供強(qiáng)大界面的服務(wù),從而允許我們?nèi)ミM(jìn)行擴(kuò)展甚至修改實(shí)現(xiàn),以提供更少的限制,而不會影響到游戲。

  • 每個組隊(duì)只有一個房間。
    • 我們不會創(chuàng)建子組隊(duì)。這和不讓組隊(duì)分裂是相輔相成的。也許一旦以后我們實(shí)現(xiàn)了這個增強(qiáng)功能,允許創(chuàng)建子組和自定義聊天室或許是一個好主意。
  • 沒有私信功能。
    • 這純粹是為了簡化,但是只有群聊并不夠好。目前我們不需要私信。請記住,任何時候只研究你的最小化可行產(chǎn)品,盡量避免掉進(jìn)不必要功能的陷阱;這是一條危險(xiǎn)的道路,很難從困境中擺脫出來。
  • 不會保存留言。
    • 換句話說,如果你離開組隊(duì),將會丟失這些信息。這將極大地簡化我們的任務(wù),因?yàn)槲覀儾槐靥幚砣魏晤愋偷臄?shù)據(jù)存儲,也不必浪費(fèi)時間來優(yōu)化存儲和恢復(fù)舊消息的數(shù)據(jù)結(jié)構(gòu)。它們都存在于內(nèi)存中,只要聊天室處于活動狀態(tài),就會一直存在。一旦關(guān)閉,就會簡單地對它們說Goodbye!
  • 通過網(wǎng)絡(luò)套接字進(jìn)行通信。
    • 可悲的是,我們的客戶將不得不處理雙重溝通渠道:游戲引擎的 RESTful 和聊天服務(wù)器的套接字。這可能會增加客戶端的復(fù)雜性,但與此同時,它將為每個模塊使用最佳通信方法。 (在聊天服務(wù)器上強(qiáng)制 REST 或在游戲服務(wù)器上強(qiáng)制使用套接字沒有任何意義。這種方法會增加服務(wù)器端代碼的復(fù)雜性,這也是處理業(yè)務(wù)邏輯的代碼,所以讓我們關(guān)注目前的問題。)

這就是聊天服務(wù)器。畢竟,它不會很復(fù)雜。在開始編碼之前還有很多工作要做,但是對于本文來說已經(jīng)足夠了。

客戶端

這是最后一個需要編碼的模塊,它將是最笨重的一個模塊。根據(jù)經(jīng)驗(yàn)來看,我更喜歡讓客戶端笨重,使服務(wù)器輕巧。這樣為服務(wù)器開發(fā)新的客戶端會更加容易。

這是我們最終應(yīng)該采用的架構(gòu)。

最終架構(gòu)

我們要實(shí)現(xiàn)的ClI客戶端很簡單,不會實(shí)現(xiàn)任何非常復(fù)雜的東西。實(shí)際上,必須要解決的最復(fù)雜的部分是 UI,因?yàn)樗且粋€基于文本的界面。

客戶端應(yīng)用程序必須實(shí)現(xiàn)的功能如下:

  • 創(chuàng)建一個新游戲。
    • 因?yàn)槲蚁MM可能保持簡單,所以這只能通過 CLI 界面完成。實(shí)際用戶界面只會在加入游戲后被用到,這把我們帶到下一個問題。
  • 加入現(xiàn)有游戲。
    • 玩家可以根據(jù)由上一條返回的游戲編號來加入游戲。另外,這件事應(yīng)該能夠在沒有 UI 的情況下完成,因此這個功能將成為開始使用文本 UI 所需的過程的一部分。
  • 解析游戲定義文件。
    • 我們將對這點(diǎn)進(jìn)行的討論,客戶端應(yīng)該能夠理解這些文件,以便能夠理解要顯示的內(nèi)容,并知道應(yīng)該如何使用這個數(shù)據(jù)。
  • 與冒險(xiǎn)互動。
    • 基本上,這使玩家能夠在任何時間與給出描述的環(huán)境進(jìn)行交互。
  • 為每位玩家維護(hù)背包內(nèi)容。
    • 客戶端的每個實(shí)例都將在內(nèi)存中包含一份道具列表。此列表將被備份。
  • 支持聊天。
    • 客戶端程序還需要連接到聊天服務(wù)器,并使用戶登錄到組隊(duì)的聊天室。

稍后將詳細(xì)介紹客戶端的內(nèi)部結(jié)構(gòu)和設(shè)計(jì)。與此同時,讓我們完成設(shè)計(jì)階段的最后一部分:游戲文件。

游戲:JSON文件

這是它變得有趣的地方,因?yàn)榈酱螢橹?,我已?jīng)涵蓋了基本的微服務(wù)定義。其中一些可能會基于 REST,而另外一些可能會使用套接字,但本質(zhì)上它們都是一樣的:你定義并對它們編碼,然后它們提供服務(wù)。

我不打算對這個特定的組件做任何編碼,但我們?nèi)匀恍枰O(shè)計(jì)它?;旧衔覀兪窃趯?shí)現(xiàn)一種協(xié)議來定義游戲、它內(nèi)部的場景以及一切。

如果你想一想,文本冒險(xiǎn)的核心基本上是一組相互連接的房間,里面是你可以與之互動的“事物”,所有這些都與一個引人入勝的故事聯(lián)系在一起?,F(xiàn)在我們的引擎不會處理最后一部分,這部分將取決于你。

現(xiàn)在回到相互連接的房間,對我來說這就像一個圖結(jié)構(gòu),如果我們還添加了前面提到的距離或移動速度的概念,還需要一個加權(quán)圖。這只是一組節(jié)點(diǎn),它們具有權(quán)重(或只是一個數(shù)字 —— 不要糾結(jié)它的名稱),代表了它們之間的路徑。下面是一個示意圖(我喜歡通過觀察進(jìn)行學(xué)習(xí),所以只看圖,好嗎?):

這是一個加權(quán)圖 —— 就是這樣。我相信你已經(jīng)弄明白了,但為了完整起見,讓我告訴你一旦我們的引擎準(zhǔn)備就緒,你將會做些什么。

一旦開始設(shè)置游戲,你將創(chuàng)建地圖(就像你在下圖中左側(cè)看到的那樣)。然后將其轉(zhuǎn)換為加權(quán)圖,如圖所示。引擎將能夠接收它并讓你按正確的順序進(jìn)行瀏覽。

一個地牢的示例圖

通過上面的加權(quán)圖,可以確保玩家不能從入口一下子走到左翼。他們必須通過這兩者之間的節(jié)點(diǎn),這樣做會消耗時間,可以用連接的權(quán)重來測量。

現(xiàn)在,進(jìn)入“有趣”的部分。來看看地圖在 JSON 格式中的樣子。這個JSON將包含很多信息:

{
 "graph": [
  { "id": "entrance", "name": "Entrance", "north": { "node": "1stroom", "distance": 1 } },
 { "id": "1st room", "name": "1st Room", "south": {"node": "entrance", "distance": 1} , "north": { "node": "bigroom", "distance": 1} } ,
 { "id": "bigroom",
 "name": "Big room",
 "south": { "node": "1stroom", "distance": 1},
 "north": { "node": "bossroom", "distance": 2},
 "east": { "node": "rightwing", "distance": 3} ,
 "west": { "node": "leftwing", "distance": 3}
 },
 { "id": "bossroom", "name": "Boss room", "south": {"node": "bigroom", "distance": 2} }
 { "id": "leftwing", "name": "Left Wing", "east": {"node": "bigroom", "distance": 3} }
 { "id": "rightwing", "name": "Right Wing", "west": { "node": "bigroom", "distance": 3 } }
 ],
 "game": {
 "win-condition": {
 "source": "finalboss",
 "condition": {
  "type": "comparison",
  "left": "hp",
  "right": "0",
  "symbol": "<="
 }
 },
 "lose-condition": {
 "source": "player",
 "condition": {
  "type": "comparison",
  "left": "hp",
  "right": "0",
  "symbol": "<="
 }
 }
 },
 "rooms": {
 "entrance": {
 "description": {
  "default": "You're at the entrance of the dungeon. There are two lit torches on each wall (one on your right and one on your left). You see only one path: ahead."
 },
 "items": [
  {
  "id": "littorch1",
  "name": "Lit torch on the right", 
  "triggers": [
  {
  "action": "grab", //grab Lit torch on the right
  "effect":{
   "statusUpdate": "has light",
   "target": "game",
  }
  }
  ] ,
  "destination": "hand"
  },
  {
  "id": "littorch2",
  "name": "Lit torch on the left", 
  "triggers": [
  {
  "action": "grab", //grab Lit torch on the left
  "effect":{
   "statusUpdate": "has light",
   "target": "game",
  }
  }
  ] ,
  "destination": "hand"
  
  }
 ]
 },
 "1stroom": {
 "description": {
  "default": "You're in a very dark room. There are no windows and no source of light, other than the one at the entrance. You get the feeling you're not alone here.",
  "conditionals": {
  "has light": "The room you find yourself in appears to be empty, aside from a single chair in the right corner. There appears to be only one way out: deeper into the dungeon."
  }
 },
 "items": [
  {
  "id": "chair",
  "name": "Wooden chair",
  "details": "It's a wooden chair, nothing fancy about it. It appears to have been sitting here, untouched, for a while now.",
  "subitems": [
  { "id": "woodenleg", 
  "name": "Wooden leg",
  "triggeractions": [
   { "action": "break", "target": "chair"}, //break 
   { "action": "throw", "target": "chair"} //throw 
  ],
  "destination": "inventory",
  "damage": 2
  }
  ]
  }
 ]
 },
 "bigroom": {
 "description": {
  "default": "You've reached the big room. On every wall are torches lighting every corner. The walls are painted white, and the ceiling is tall and filled with painted white stars on a black background. There is a gateway on either side and a big, wooden double door in front of you."
 },
 "exits": {
  "north": { "id": "bossdoor", "name": "Big double door", "status": "locked", "details": "A aig, wooden double door. It seems like something big usually comes through here."}
 },
 "items": []
 },
 "leftwing": {
 "description": {
  "default": "Another dark room. It doesn't look like it's that big, but you can't really tell what's inside. You do, however, smell rotten meat somewhere inside.",
  "conditionals": {
  "has light": "You appear to have found the kitchen. There are tables full of meat everywhere, and a big knife sticking out of what appears to be the head of a cow."
  }
 },
 "items": [
  { "id": "bigknife", "name": "Big knife", "destination": "inventory", "damage": 10}
 ]
 },
 "rightwing": {
 "description": {
  "default": "This appear to be some sort of office. There is a wooden desk in the middle, torches lighting every wall, and a single key resting on top of the desk."
 },
 "items": [
  { "id": "key",
  "name": "Golden key",
  "details": "A small golden key. What use could you have for it?",
  "destination": "inventory",
  "triggers": [{
  "action": "use", //use on north exit (contextual)
  "target": {
  "room": "bigroom",
  "exit": "north"
  },
  "effect": {
  "statusUpdate": "unlocked",
  "target": {
   "room": "bigroom",
   "exit": "north"
  }
  }
  }
  ]
  }
 ]
 },
 "bossroom": {
 "description": {
  "default": "You appear to have reached the end of the dungeon. There are no exits other than the one you just came in through. The only other thing that bothers you is the hulking giant looking like it's going to kill you, standing about 10 feet from you."
 },
 "npcs": [
  {
  "id": "finalboss",
  "name": "Hulking Ogre",
  "details": "A huge, green, muscular giant with a single eye in the middle of his forehead. It doesn't just look bad, it also smells like hell.",
  "stats": {
  "hp": 10,
  "damage": 3
  }
  }
 ]
 }
 }
}

它看起來有很多內(nèi)容,但是如果你把它視為一個簡單的游戲描述,就會明白這是一個含有六個房間的地牢,每個房間都與其他房間相互連接,如上圖所示。

你的任務(wù)是穿越并探索它。你會發(fā)現(xiàn)有兩個地方可以找到武器(無論是在廚房還是在黑暗的房間,只要破壞掉椅子就能得到)。你也將面對一扇上鎖的門,所以,一旦找到鑰匙(位于類似辦公室的房間內(nèi)),就可以打開并用你收集到的武器和BOSS展開一場大戰(zhàn)。

你可以干掉它而獲勝,也可以被它殺死而輸?shù)簟?/p>

現(xiàn)在讓我們更詳細(xì)地了解整個 JSON 結(jié)構(gòu)及其中的三個部分。

Graph

這里包含節(jié)點(diǎn)之間的關(guān)系。基本上這一部分會直接轉(zhuǎn)換為我們之前看到的圖。

這部分的結(jié)構(gòu)非常簡單。它是一個節(jié)點(diǎn)列表,其中每個節(jié)點(diǎn)都包含以下屬性:

  • 一個標(biāo)識游戲中所有其他節(jié)點(diǎn)的唯一 ID;
  • 一個名稱,實(shí)際上是給玩家看到的 ID 版本;
  • 一組指向其他節(jié)點(diǎn)的鏈接。這可以通過四個可能的 key 來描述:north, south, east 和 west.。我們可以通過添加這四個組合來增加更多方向。每個鏈接都包含相關(guān)節(jié)點(diǎn)的 ID 以及該關(guān)系的距離(或權(quán)重)。

Game

本節(jié)包含常規(guī)設(shè)置和條件。特別是在上面的示例中,此部分包含輸贏條件。換句話說,在這兩個條件下,我們會讓游戲知道什么時候結(jié)束。

為了簡單起見,我添加了兩個條件:

  • 要么通過殺死 BOSS 獲勝,
  • 或者因?yàn)楸粴⒍數(shù)簟?/li>

Rooms

這一部分占了 JSON 文件很大的篇幅,也是最復(fù)雜的部分。在這里描述冒險(xiǎn)中所有區(qū)域及其內(nèi)部所有房間。

每個房間都有一把鑰匙,使用我們之前定義的 ID。每個房間都有一個描述,一個物品列表,一個出口(或門)列表和一個非玩家角色(NPC)列表。在這些屬性中,唯一應(yīng)該被強(qiáng)制定義的屬性是描述,因?yàn)橐嫘枰@個屬性才能讓你明白所看到的內(nèi)容。如果有什么東西需要展示,它們只能在那里。

讓我們來看看這些屬性能為游戲做些什么。

description
這一項(xiàng)并不像想象的那么簡單,因?yàn)槟憧吹降姆块g可能會根據(jù)不同的情況而變化。例如:如果你查看第一個房間的描述,就會注意到在默認(rèn)情況下,你將看不到任何東西,除非你有一個點(diǎn)亮的火炬。

因此,拾取物品并使用它們,可能會觸發(fā)影響游戲中其他部分的全局條件。

items

這些代表了你可以在房間內(nèi)找到的所有東西。每個項(xiàng)目都會共享與 graph 節(jié)點(diǎn)相同的 ID 和名稱。

它們還有“目標(biāo)”屬性,該屬性指示一旦拾取該道具應(yīng)放在哪里。這是有意義的,因?yàn)槟闶稚现荒苎b備一個道具,而在背包中可以存放很多的道具。

最后,其中一些道具可能會觸發(fā)其他操作或者狀態(tài)更新,具體取決于玩家決定用它們做什么。其中一個例子就是從入口處點(diǎn)燃的火把。如果你拿著一個,將在游戲中觸發(fā)狀態(tài)更新,這反過來將使游戲向你顯示下一個房間的不同描述。

道具也可以有“子道具”,一旦原始道具被銷毀(例如通過“分解”操作)就會發(fā)揮作用。一個道具可以被分解為多個,并在“subitems”元素中定義。

本質(zhì)上,此元素只是一個新道具的數(shù)組,其中還包含可以觸發(fā)其創(chuàng)建的一組操作?;旧峡梢愿鶕?jù)你對原始道具執(zhí)行的操作創(chuàng)建不同的子道具。

最后,有些物品會有“傷害”屬性。所以如果你用某個道具擊中 NPC,該值用于從中減去生命。

exits

出口是與道具分開的實(shí)體,因?yàn)橐嫘枰滥闶欠衲軌蚋鶕?jù)其狀態(tài)去遍歷它們。否則被鎖定的出口無法讓你通過,除非你把它的狀態(tài)改為已解鎖。

NPC

最后,NPC 將成為另一個列表的一部分。它們是有狀態(tài)信息的項(xiàng)目,引擎將使用這些狀態(tài)信息來了解每個項(xiàng)目的行為方式。在我們的例子中定義的是 “hp”,它代表健康狀態(tài),還有“damage”,就像武器一樣,每次命中將從玩家的健康狀況中減去相應(yīng)的值。

這就是我創(chuàng)造的地牢。內(nèi)容很多,將來我可能會考慮寫一個編輯器,來簡化 JSON 文件的創(chuàng)建。但就目前而言還沒有必要。

你可能還沒有意識到,這樣在文件中定義游戲是有很大好處的,能夠像超級任天堂時代那樣切換 JSON 文件。只需加載一個新文件就能開始另一個游戲。非常簡單!

總結(jié)

感謝你能讀到這里。希望你能喜歡我所經(jīng)歷的設(shè)計(jì)過程,并將想法變?yōu)楝F(xiàn)實(shí)。我正在努力實(shí)現(xiàn)這一目標(biāo)。我們以后可能會意識到,今天定義的內(nèi)容可能會不起作用,出現(xiàn)這種情況時,我們將不得不回溯并修復(fù)它。

我敢肯定,有很多方法可以對這里提出的想法進(jìn)行改善,并創(chuàng)建一個地獄的引擎。但是這需要在本文中添加的更多的內(nèi)容,為了不讓讀者感到無聊,所以就先這樣吧。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • 詳談nodejs異步編程

    詳談nodejs異步編程

    本文詳細(xì)介紹了node.js異步編程的分類以及異步編程存在的問題,非常的詳盡,非常細(xì)致,這里推薦給小伙伴。
    2014-12-12
  • Nodejs 發(fā)布自己的npm包并制作成命令行工具的實(shí)例講解

    Nodejs 發(fā)布自己的npm包并制作成命令行工具的實(shí)例講解

    今天小編就為大家分享一篇Nodejs 發(fā)布自己的npm包并制作成命令行工具的實(shí)例講解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制

    Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制

    這篇文章主要介紹了Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • 使用?Node.js和Express搭建服務(wù)器的過程步驟詳解

    使用?Node.js和Express搭建服務(wù)器的過程步驟詳解

    Node.js?是一個開源、跨平臺的?JavaScript?運(yùn)行時環(huán)境,這篇文章主要介紹了如何使用?Node.js和Express搭建服務(wù)器,需要的朋友可以參考下
    2023-09-09
  • node.js實(shí)現(xiàn)多圖片上傳實(shí)例

    node.js實(shí)現(xiàn)多圖片上傳實(shí)例

    這篇文章主要介紹了node.js實(shí)現(xiàn)多圖片上傳實(shí)例,包括路由、控制器和視圖的源碼,重點(diǎn)在圖片上傳處理程序,需要的朋友可以參考下
    2014-06-06
  • node網(wǎng)頁分段渲染詳解

    node網(wǎng)頁分段渲染詳解

    按照常理,我們渲染一張網(wǎng)頁,必定是網(wǎng)頁全部拼裝完畢,然后生成HTML字符串,傳送至客戶端。這也意味著,如果一張網(wǎng)頁處理的有快有慢的話,必須串行等到所有的邏輯都處理完畢。后端才能進(jìn)行返回。
    2016-09-09
  • 詳解Node.js服務(wù)器靜態(tài)資源處理

    詳解Node.js服務(wù)器靜態(tài)資源處理

    靜態(tài)資源服務(wù)器指的是不會被服務(wù)器的動態(tài)運(yùn)行所改變或者生成的文件,本文主要為大家詳細(xì)介紹了Node.js服務(wù)器靜態(tài)資源處理的相關(guān)知識,需要的可以了解下
    2024-04-04
  • nodejs之base64編碼解碼問題

    nodejs之base64編碼解碼問題

    這篇文章主要介紹了nodejs之base64編碼解碼問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 使用?Node-RED對?MQTT?數(shù)據(jù)流處理

    使用?Node-RED對?MQTT?數(shù)據(jù)流處理

    本文將介紹使用 Node-RED 連接到 MQTT 服務(wù)器,并對 MQTT 數(shù)據(jù)進(jìn)行過濾和處理后再將其發(fā)送至 MQTT 服務(wù)器的完整操作流程。讀者可以快速了解如何使用 Node-RED 對 MQTT 數(shù)據(jù)進(jìn)行簡單的流處理
    2022-05-05
  • nodejs教程之異步I/O

    nodejs教程之異步I/O

    nodejs的核心之一就是非阻塞的異步IO,于是想知道它是怎么實(shí)現(xiàn)的,經(jīng)過一份研究,找到些答案,在此跟大家分享下。
    2014-11-11

最新評論