亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

javascript高仿熱血傳奇游戲實現代碼

2019-11-19 14:20:07
字體:
來源:轉載
供稿:網友

前言

游戲的第一個版本開發于14年,瀏覽器端使用html+css+js,服務端使用asp+php,通訊采用ajax,數據存儲使用access+mySql。不過由于一些問題(當時還不會用node,用asp寫復雜的邏輯真的會寫吐;當時對canvas寫的也少,dom渲染很容易達到性能瓶頸),已經廢棄。后來用canvas重制了一版。本文寫于18年。

 

1.開發前的準備

為什么要用Javascript來實現一款比較復雜的PC端游戲

1.js實現PC端網游是可行的。隨著PC、手機硬件配置的升級和瀏覽器的更新換代,以及H5各種庫的發展,js實現一款網游的難度越來越低。這里的難度主要是兩方面:瀏覽器的性能;js代碼是否足夠易于擴展,以滿足于一款邏輯極其復雜的游戲的迭代。

2.現階段的js游戲里,很少有規模較大的可供參考。涉及到多人聯機、服務端數據存儲、復雜交互的游戲,大多數(幾乎全部)都是用flash開發的。但是flash畢竟在衰落,而js發展迅速,并且只要有瀏覽器就可以運行。

為什么選擇了一款2001年的熱血傳奇游戲

第一個原因是對老游戲的情懷; 當然更重要的另一個原因是,別的游戲要么我不會玩、要么我會玩但沒有素材(圖片、音效等)?;ê艽缶θナ占粋€游戲的地圖、人物怪物模型、物品和裝備圖,然后去處理、解析一遍再用于js開發,我覺得是浪費時間。

由于我以前搜集了一些傳奇游戲的素材,并且幸運地找到了提取熱血傳奇客戶端資源文件的方法( github地址 ),所以可以直接開始寫碼,省去了一些準備時間。

可能的困難

1.瀏覽器的運行性能:這個應該是最困難的一點。假如游戲要保持40幀,那么每幀只有25ms的時間留給js計算。并且由于渲染通常比計算耗性能,實際上留給js的時間只有10毫秒左右。

2.防作弊:如何避免用戶直接調用接口或者篡改網絡請求數據?由于目標是用js實現比較復雜的游戲,并且任何網絡游戲都需要考慮這一點,一定會有相對成熟的方案。此處不是本文重點。

2.整體設計

瀏覽器端

畫面渲染使用canvas。

相比dom(div)+css,canvas可以處理比較復雜的場景渲染和事件管理,例如下面這個場景,涉及了四張圖片:玩家、動物、地上的物品、最下層的地圖圖片。(實際還有地上的影子,鼠標指向人物、動物、物品時出現的相應名稱,以及地面上的陰影。為了方便讀懂,先不考慮這么多內容。)

 

這時,如果希望實現“點擊動物、攻擊動物;點擊物品、撿起物品”的效果,那么需要對動物和物品進行事件監聽。如果采用dom的方式,那么會出現幾點難于處理的問題:

a.渲染的順序和事件處理的順序不同(有時候z-index小的需要先處理事件),需要額外處理。例如這個上面的例子里:點擊怪物、點擊物品的時候也容易點到人物,那么需要給人物做“點擊事件穿透”的處理。而且事件處理的順序不固定:假如我有一個技能(例如游戲里的治療)需要點人物才可以釋放,那么這時人物又需要有事件監聽。所以一個元素是否需要處理事件、處理事件的先后,是隨著游戲狀態的不同而變化的,而 dom的事件綁定已經不能滿足需要 。

b.有關聯的元素難以放在同一個dom節點中:例如玩家的模型、玩家的名字和玩家身上的技能畫效,理想情況下是放在一個 <div> 或者 <section> 容器里,便于管理(這樣幾個元素的定位就可以繼承父元素,不用分別處理位置了)。但是這樣,z-index會很難處理。例如玩家A在玩家B的上面,那么A會被B遮擋,因此需要A的z-index小一些,但是又需要讓玩家A的名字不會被B的名字或者影子遮擋,就無法實現。簡單點說, dom結構的可維護性會犧牲畫面展示的效果,反之亦然 。

c.性能問題。即使犧牲了效果,用dom渲染,勢必出現很多嵌套關系,所有元素的style都在頻繁變化,連續觸發瀏覽器的repaint甚至reflow。

canvas渲染邏輯與項目邏輯分離

如果將canvas的各種渲染操作(如 drawImage 、 fillText 等)與項目代碼放在一起,那么勢必導致項目后期無法維護。翻了一下幾款現有的canvas庫,結合vue的數據綁定+調試工具的方式,搞了一個全新的canvas庫Easycanvas( github地址 ),并且像vue一樣支持通過一個插件來調試canvas中的元素。

這樣,整個游戲的渲染部分就容易很多,只需要管理游戲當前的狀態、并且根據服務端從socket傳回來的數據去更新數據就可以。 “數據的變化引起視圖的變化”這個環節由Easycanvas負責 。例如下圖的玩家包裹物品的實現,我們只需要給出包裹容器的位置、背包里每個元素的排布規則,然后將每個包裹的物品綁定到一個array上,然后去管理這個array即可(數據映射到畫面的過程由Easycanvas負責)。

 

例如,5行8列共計40個物品的樣式可以通過如下的形式傳遞給Easycanvas(index為物品索引,物品x方向間距36,y方向間距32)。而這個邏輯是一成不變的,無論物品的數組怎樣變化、包裹被拖拽到什么位置,每個物品的相對位置都是固定的。至于canvas上的渲染則完全不需要項目本身來考慮,所以可維護性較好。

style: { tw: 30, th: 30, tx: function () { return 40 + index % 8 * 36; }, ty: function () { return 31 + Math.floor(index / 8) * 32; }}

canvas分層渲染

假設:游戲需要保持40幀,瀏覽器寬800高600,面積48萬(后面稱48萬為1個屏幕面積)。

如果用同一個canvas來呈現,那么這個canvas的幀數40,每秒至少需要繪制40個屏幕面積。但是同一個坐標點很可能出現多個元素重疊的情況,例如底部的UI、血條、按鈕就是重疊放置,他們又共同遮擋了場景地圖。所以這些加在一起,每秒瀏覽器的繪制量很容易達到100個屏幕面積以上。

這個繪制是很難優化的,因為整個canvas畫布的任何一處都在進行視圖的更新:可能是玩家和動物的移動、可能是按鈕的特效、可能是某個技能效果的變化。這樣的話,即使玩家不動,由于衣服“隨風飄飄”的效果(其實是精靈動畫播放到下一張圖),或者是地面上出現了一瓶藥水,都要引起整個canvas的重繪。因為 游戲中幾乎不可能出現某一幀的畫面與上一幀毫無區別的情況,即使是游戲畫面的一個局部,也很難保持不變 。整個游戲的畫面永遠在更新。

因為 游戲中幾乎不可能出現某一幀的畫面與上一幀毫無區別的情況 ,畫面永遠在更新。

因此,這次我采用了3個canvas重疊排布的方式。由于Easycanvas的事件處理支持傳遞,因此即使點到了最上面的canvas,如果沒有任何元素結束了某一次點擊,后面的canvas也可以接到這次事件。3個canvas分別負責UI、地面(地圖)、精靈(人物、動物、技能特效等):

 

這樣分層的好處是,每層最大幀數可以根據需要來調整:

例如UI層,因為很多UI平時是不動的,即使動也不會需要太精密的繪制,所以可以適當降低幀數,例如降低到20。這樣假如玩家的體力從100降低到20,那么可以在50ms內更新視圖,而50ms的切換是玩家感覺不出來的。因為像體力這種 UI層數據的變化很難在很短的時間內連續變化多次,而50ms的延遲是人很難感知的,所以不需要頻繁的繪制 。假如我們每秒節約了20幀,那么很可能可以節約10個屏幕面積的繪制。

再如地面,只有玩家移動的時候,地圖才會變化。這樣,如果玩家不動,那么每幀可以省去1個屏幕面積。由于需要保證玩家移動時的流暢感,地面的最大幀數不宜太低。假如地面為30幀,那么玩家不動時,每秒就可以節約30個屏幕面積的繪制(這個項目中,地圖是幾乎繪滿屏幕的)。而且其它玩家、動物的移動不會改變地面,也不需要重繪地面這一層。

精靈層最大幀數不能降低,這層會展示游戲的人物動作等核心部分,所以最大幀數設置為40.

這樣,每秒繪制的面積,玩家移動時可能是80~100個屏幕面積,而玩家不移動時可能只有50個屏幕面積。游戲中,玩家停下來打怪、打字、整理物品、釋放技能都是站立不動的,因此 大量的時間里都不會觸發地面的繪制,對性能的節約很大 。

服務器端

由于目標是js實現一款多人網游,所以服務端使用Node,使用socket與瀏覽器通訊。這樣做還有一個好處,就是一些 公用的邏輯可以在兩端復用 ,例如判斷地圖上某個坐標點是否存在障礙物。

Node端的玩家、場景等游戲相關數據全部存儲與內存中,定期同步至文件。每次Node服務啟動時,將數據從文件讀取至內存。這樣可以玩家較多時,文件讀寫的頻率成指數級上升,從而引發的性能問題。(后來為了提高穩定,為文件讀寫增加了一個緩沖,“內存-文件-備份”的方式,以免讀寫過程中服務器重啟導致的文件損壞)。

Node端分接口、數據、實例等多層。“接口”負責和瀏覽器端交互。“數據”是一些靜態數據,例如某個藥品的名稱和效果、某個怪物的速度和體力,是游戲規則的一部分。“實例”是游戲中的當前狀態,例如某個玩家身上的一個藥品,就是“藥品數據”的一個實例。再舉個例子,“鹿的實例”擁有“當前血量”這個屬性,鹿A可能是10,鹿B可能是14,而“鹿”本身只有“初始血量”。

3.場景地圖的實現

地圖場景

下面開始介紹地圖場景部分,仍然是依賴 Easycanvas 進行渲染。

思考

由于玩家是始終固定在屏幕中心的,所以玩家的移動,實際上是地圖的移動。例如玩家像左跑,地圖就向右平移即可。剛才已經提到,玩家處于3個canvas中的中間一層,而地圖屬于底層,因此玩家一定遮擋地圖。

這樣看起來是合理的,但是假如地圖中有一棵樹,那么“玩家的層次始終高于樹”就不對了。這時,有2種大的解決方案:

地圖分層,“地面”與“地上”拆開。將玩家處于兩層之間,例如下圖,左側是地上、右側是地面,然后重疊繪制,把人物夾在中間:

 

這樣看似解決了問題,其實引入了2個新的問題:第一個是,玩家有時可能會被“地上”的東西遮擋(例如一棵樹),有時又需要能夠遮擋“地上”的東西(例如站在這棵樹的下方,頭部會遮擋住樹)。另一個問題是渲染的性能消耗會增加。由于玩家是時刻在變的,“地上”這一層需要頻繁重繪。這樣做也打破了最初的設計――盡量節約地面大地圖的渲染,從而導致canvas的分層更加復雜。

地圖不分層,“地面”與“地上”在一起繪制。當玩家處于樹后的時候,將玩家的透明度設置為0.5,例如下圖:

 

這樣做只有一個壞處:玩家的身體要么都不透明、要么都半透明(怪物在地圖上行走也會有這個效果),不會完全真實。因為理想的效果是存在玩家的身體被遮擋住一部分的場景的。但是這樣做對性能友好,并且代碼易于維護,目前我也采用了這個方案。

那么如何判斷“地圖”這張圖片哪些地方是樹呢?游戲通常會有一個大的地圖描述文件(其實就是一個Array),通過0、1、2這樣的數字來標識哪些地方可以通過、哪些地方存在障礙物、哪些地方是傳送點等等。熱血傳奇中的這個“描述文件”就是48x32為最小單位進行描述的,所以玩家在傳奇中的行動會有一種“棋盤”的感覺。單位越小越流暢,但是占用的體積越大、生成這個描述的過程也就越耗時。

下面開始正題。

實現

我找了一個朋友幫我導出熱血傳奇客戶端中“比奇省”的地圖,寬33600、高22400,是我電腦的幾百倍大。為了避免電腦爆炸,需要拆分成多塊加載。由于傳奇的最小單元是48x32,我們以480x320將地圖拆成了4900(70x70)個圖片文件。

canvas的尺寸我們設定為800x600,這樣玩家只需要加載3x3共計9張圖片就可以鋪滿整個畫布。800/480=1.67,那么為什么不是2x2?因為有可能玩家當前的位置正好導致有的圖片只展示了一部分。如下圖:

 

總結

以上所述是小編給大家介紹的javascript高仿熱血傳奇游戲實現代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成年人网站| 亚洲国产欧美在线成人app| 国产亚洲人成网站在线观看| 亚洲人午夜色婷婷| 伊人久久男人天堂| 久久精品国产久精国产一老狼| 国产日韩换脸av一区在线观看| 在线观看日韩www视频免费| 亚洲成人av片| 欧美国产日本高清在线| 大量国产精品视频| 日韩av网站大全| 国产69精品99久久久久久宅男| 欧美最猛性xxxxx亚洲精品| 成人精品久久一区二区三区| 亚洲a中文字幕| 日韩亚洲精品视频| 亚洲天堂av在线免费观看| 91亚洲精品在线观看| 97视频在线看| 高清在线视频日韩欧美| 欧美麻豆久久久久久中文| 国产精品久久久精品| 亚洲一区二区自拍| 亚洲成人黄色网| 欧美电影免费观看高清完整| 国产精品久久久久av| 国产精品免费久久久久影院| 夜夜嗨av一区二区三区免费区| 国内精品久久久久影院 日本资源| 亚洲精品第一页| 久久天堂电影网| 国产精品亚洲一区二区三区| 国产在线视频2019最新视频| 97热在线精品视频在线观看| 国产噜噜噜噜噜久久久久久久久| 日韩精品在线免费观看视频| 亚洲性夜色噜噜噜7777| www.亚洲男人天堂| 91久久久久久久| 欧美色图在线视频| 国产91精品最新在线播放| 日韩欧美国产免费播放| 亚洲老板91色精品久久| 亚洲国产精品久久91精品| 亚洲人成电影网站| 久久精品99国产精品酒店日本| 亚洲缚视频在线观看| 国产成人精品一区二区| 久久伊人精品一区二区三区| 色综合久久中文字幕综合网小说| 国产在线不卡精品| 97在线视频免费观看| 国产精品高精视频免费| 欧洲亚洲妇女av| 久久久精品视频在线观看| 日韩人体视频一二区| 精品成人69xx.xyz| 黑人巨大精品欧美一区免费视频| 日韩免费在线观看视频| 免费97视频在线精品国自产拍| 日本亚洲欧美三级| 粗暴蹂躏中文一区二区三区| 国产精品27p| 在线日韩中文字幕| 欧美日韩另类视频| 欧美极品少妇xxxxⅹ喷水| 久久人人爽人人爽人人片av高请| 成人做爰www免费看视频网站| 国产欧美日韩中文| 中文字幕亚洲情99在线| 欧美午夜激情小视频| 久久久亚洲福利精品午夜| 亚洲精品福利在线| 亚洲精品在线视频| 色中色综合影院手机版在线观看| 日韩国产精品视频| 国产日本欧美一区二区三区在线| 精品久久久久久久久久国产| 国产美女精品免费电影| 成人美女免费网站视频| 亚洲色图13p| 亚洲高清色综合| 成人黄色av播放免费| 国产成人97精品免费看片| 国产99久久精品一区二区 夜夜躁日日躁| 国产精品十八以下禁看| 久久99精品久久久久久琪琪| 91亚洲精品久久久久久久久久久久| 亚洲精品动漫100p| 欧美日韩激情视频| 日韩在线免费观看视频| 久久国产天堂福利天堂| 亚洲级视频在线观看免费1级| 91精品国产91久久久久久| 国产精品高清在线观看| 国产精品福利无圣光在线一区| 精品magnet| 在线a欧美视频| 欧美又大又粗又长| 欧美日韩中文在线观看| 欧美亚洲第一区| 中文.日本.精品| 国产福利精品在线| 日韩av电影手机在线| 日本久久久久久| www.日韩免费| 91精品国产高清自在线看超| 91大神在线播放精品| 国产欧美欧洲在线观看| 97在线视频免费看| 91探花福利精品国产自产在线| 亚洲3p在线观看| 亚洲精品动漫久久久久| 精品国产福利在线| 亚洲最大福利网站| 精品久久久久久久久久| 久久好看免费视频| 欧美日韩福利视频| 国产精品永久免费观看| 精品免费在线视频| 中文字幕欧美日韩在线| 久久久久久av| 国产一区二区黄| 欧美成人四级hd版| 粉嫩老牛aⅴ一区二区三区| 久久精品视频免费播放| 亚洲激情国产精品| 国产精品18久久久久久首页狼| 最近中文字幕mv在线一区二区三区四区| 福利微拍一区二区| 国产成人在线一区| 欧美巨乳美女视频| 日韩高清电影好看的电视剧电影| 亚洲日韩中文字幕在线播放| 欧美中文在线免费| 国产亚洲视频中文字幕视频| 国产精品久久久av| 九九视频这里只有精品| 中文字幕免费精品一区高清| 久久久亚洲国产天美传媒修理工| 日本精品视频网站| 欧美黄色片免费观看| 国产成人短视频| 欧美性xxxxx| 黑人巨大精品欧美一区二区一视频| 欧美日韩国产成人在线| 国产成人精品av在线| 国产精品igao视频| 亚洲午夜精品视频| 国产精品丝袜一区二区三区| 国产精品久久久久久久久久久久| 久久久国产精彩视频美女艺术照福利| 欧美激情视频免费观看| 欧美孕妇毛茸茸xxxx| 国产精品日韩欧美大师| 91av国产在线| 精品亚洲一区二区三区在线观看| 欧美大成色www永久网站婷| 日韩在线视频网| 欧美亚洲国产另类| 亚洲欧美国产日韩天堂区| 欧美一区二区三区……| 国内精品久久久久久中文字幕|