站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        html5實現(xiàn)一個簡單的多人飛機游戲?qū)嵗斀?/a>

        一年多前見過一個多人聊天室應用,是張丹老師寫的一個 socket.io 教程 (原鏈接點不開,貼一個轉(zhuǎn)帖的),覺得socket這個東西很神奇。后來研究生期間的一個項目也用到了.Net的socket,多個客戶端之間的通信, 覺得很有意思,也是那一次比較全面地認識和應用了事件委托等等一些概念。最近受群里研究mapbox的熱情和@扯淡大叔, @老羽 @F3earth 所有成員的幫助和啟發(fā), 突發(fā)奇想花了點時間基于mapbox gl js和socket.io做了一個 飛機大戰(zhàn)游戲!,雖然功能界面很簡陋。而且代碼也比較原始,還沒有好好重構(gòu)。但是基本有了個架子,簡單記下來分析下。如果對源碼感興趣或者想?yún)⑴c開發(fā)和優(yōu)化工作,請訪問git倉庫: Jqmap2

        整體架構(gòu)

        簡單來說,整個游戲的設計思路就是:

        服務器從啟動開始就監(jiān)聽任何客戶端發(fā)來了websocket 連接請求,有了連接(connection事件)后,就把客戶端初次發(fā)來的用戶名稱、當前飛機的坐標、朝向作為一個client 加入客戶端數(shù)據(jù)池(目前簡單處理為clients數(shù)組)中。那么至此一個客戶端的數(shù)據(jù)就同步到了服務器端。

        以后這個客戶端的飛機坐標、朝向等信息也定時發(fā)送(socket.send)給服務器端,以便于服務器端同時廣播(broadcast)給所有其他客戶端。那么其實服務端就說清楚了,也就是負責中轉(zhuǎn)消息,目的還是讓所有客戶端視野中的玩家飛機狀態(tài)保持一致。

        既然websocket是雙向通信,客戶端也需要定時發(fā)送消息給服務器端,并且更重要的是處理服務器端發(fā)來的各種消息(message事件),分辨哪些是歡迎用戶上線的消息,普通的玩家位置同步消息,抑或是 A 擊敗了 B 這樣的消息。

        這一過程中前端和服務器保持著websocket 連接,并且不斷在通信。相比傳統(tǒng)的輪詢和long poll,這樣更加節(jié)省流量和性能。總體來說,游戲的邏輯是基于各種消息事件的,connection事件產(chǎn)生一個socket連接,socket連接會有message 事件等等。

        后端websocket

        廢話說了這么多,簡單看看一些關(guān)鍵代碼如何實現(xiàn)。

        // 后端關(guān)鍵流程實現(xiàn)

        var app = express(),      server = require('http').createServer(app),      io = require('socket.io').listen(server); // 引入socket.io 庫  io.on('connection', function(socket) { // 開始監(jiān)聽客戶端的websocket連接請求,connection事件產(chǎn)生 socket 對象      socket.emit('open'); // 向該客戶端發(fā)送open事件.      // init client drone obj for each connection !!      var client = {          name: false,          color: getColor(),          direction: 0,          coordinates: [0, 0]      }      // message from client.      socket.on('message', function(msg) {          if (!client.name && msg.name) { // 如果是第一次連接,把用戶的名字存儲起來,并且廣播給所有客戶端。            var obj  = { }; // 構(gòu)建發(fā)送給其他客戶端的消息            obj = msg;            clients.push(client); // 加入后臺維持的客戶端數(shù)組            socket.broadcast.emit('message', obj); // 廣播歡迎語給其他客戶端          } else if ( client.name == msg.name ) { // 客戶端發(fā)來的飛機狀態(tài)消息              // 廣播給其他客戶端            socket.broadcast.emit('message', obj);          }      }  }

        后臺處理過程相對簡單,基本只需接受某客戶端發(fā)來的消息,轉(zhuǎn)發(fā)給其他客戶端即可( 隨機敵機位置什么的就不講了,當然后期要改成所有客戶端共享一套敵機信息,這樣就可以一起打同一個BOSS了)。但前端需要根據(jù)業(yè)務需求將服務器傳來的消息分別處理

        前端socket和飛機模型

        前端業(yè)務相對復雜, 除了應對websocket 消息之外,需要構(gòu)建一套飛機的數(shù)據(jù)模型,包括位置,速度,朝向,血量,武器裝備等(可以非常復雜,目前就簡單處理)。

        var socket;  try {      socket = io.connect("http://123.206.201.245:3002");      socket.on('open', function(){  // 當服務端確認連接后,開始發(fā)送第一次數(shù)據(jù)。          statusBar.innerText = "已經(jīng)連上服務器..";          var askName = prompt("來,取個名字", "");      }      socket.on("message", function(json) { // 其實收到的是js 對象,這一點很牛逼。因為雙向通信過程中傳遞的是 Binary 形式的數(shù)據(jù),不需要再次解析了。        if (json.type === "welcome" && json.text.name) {            // .. 顯示其他用戶登錄消息        } else if (json.type === "defeat") {            // .. 在前端的敵機數(shù)據(jù)模型中移除空血槽的飛機        } else if (drone && json.text.name != drone.name) {            // .. 傳來的其他客戶端飛機消息            featureCol.features.forEach(function(drone) {            // featureCol 是所有敵機數(shù)據(jù)集合,根據(jù)用戶名check是更新還是新增.            }        }     }

        其他問題包括:

        飛機的數(shù)據(jù)涉及到隨時變更上傳服務器,以及渲染兩個用處。渲染采用geojson對象 作為 mapbox api中source 的data,那么是否是一接到服務器端消息就去重繪所有飛機位置呢。這邊通過setInterval 定時調(diào)用source 的 setData()方法,實現(xiàn)重繪。

        飛機子彈的軌跡計算,涉及到用戶按下空格鍵的瞬間飛機的位置和朝向,根據(jù)設定的子彈飛行時間做一個動畫顯示

        子彈和敵機的碰撞檢測,簡化處理:設定一個常數(shù)作為飛機體積,在子彈飛行過程中實時計算子彈和敵機距離。在地圖處于小比例尺下增大檢測半徑,地圖處于大比例尺下相應減小檢測半徑。

        目前可能子彈飛行過程中碰撞檢測的計算量偏大,會有卡頓問題,CPU占用較高,整個應用消耗內(nèi)存100~130Mb左右… 好多小問題不說了。。確實廢了一些腦子。

        挑一兩點分析下,一個是子彈的飛行過程,一個是Robot敵機的隨機行為控制

        // setPostion is to update Mydrone position.  function setPosition() {      // direction in Rad. Generally, 1 Rad stands for 100km      var current_rotate = map.getBearing();       if (!manual && Math.random() > 0.95) { // 這邊有意思,在每秒50幀的情況下,不是每一幀都會隨機微調(diào)飛機的方向。而是5%的概率。          direction += (Math.random() - 0.5) /5;      }          // 根據(jù)飛機朝向和速度更新位置。      point.coordinates[0] += speed * Math.sin(direction) / 100;      point.coordinates[1] += speed * Math.cos(direction) / 100;      // 校正飛機的朝向顯示。因為默認情況下mapbox是根據(jù)你的視角隨時調(diào)整圖標方向。但實際上飛機圖標的朝向必須和飛機運行方向一致,而不是簡單的和標注一樣。      current_rotate = (-current_rotate) + direction * (180 / Math.PI);  }

        以下是子彈飛行的計算過程.

        // start: fire location, target: bullet destination, duration: total animation time  function renderBulvar(start, target, direction, duration) {      // target is geojson POINT, add Temp point in layer..       var interval = 20, ratio = interval/duration, real_point = start, range = 0.4, count = 0, hitted = false;      if (target.coordinates) {          var targetSource = map.getSource('drone-target');          window.setInterval(function(){              if (count > duration/interval) { // 到達終點,不計算了              } else {                  // 子彈每一幀跑一定比例的路程,最終到達指定終點                  real_point.coordinates[0] += Math.sin(direction)*ratio*range;                  real_point.coordinates[1] += Math.cos(direction)*ratio*range;                  targetSource.setData(real_point);                  if (!hitted){                      hitted = testCrash(real_point.coordinates); // 感覺這里的hitted 有問題.                  }                  count += 1;              }          }, interval);      }

        到這里其實基本介紹了這個游戲的制作過程,經(jīng)歷了一些不成熟的想法,總共花了近十個小時完成目前的開發(fā)。還沒有嚴謹?shù)乜紤]過代碼結(jié)構(gòu)和 函數(shù)復雜程序,特別是子彈飛行和碰撞等部分,碰撞到后就終結(jié)子彈飛行等等。各位如果感興趣,愿意完成 To DO list中的事情或者有何建議,請訪問git倉庫: Jqmap2 。請各位大神多提修改意見!

        喜歡的同學請關(guān)注、收藏相關(guān)專題,會不斷更新文章。希望和大家分享!!

        【相關(guān)推薦】

        1. 特別推薦:“php程序員工具箱”V0.1版本下載

        2. 免費h5在線視頻教程

        3. php.cn原創(chuàng)html5視頻教程

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 国产欧美精品一区二区三区| 国产精品欧美久久久久无广告| 2023国产精品自拍| 无码日韩精品一区二区三区免费| 国产精品 码ls字幕影视| 99国产精品永久免费视频| 亚洲精品无码99在线观看| 国产微拍精品一区二区| 久久91综合国产91久久精品| 亚洲国产美女精品久久久久∴| 精品一区二区三区免费观看| 亚洲综合一区二区国产精品| 嫩草影院久久国产精品| 99国产精品一区二区| 久久精品黄AA片一区二区三区| 在线精品动漫一区二区无广告| 久久国产精品免费一区| 国产精品一区三区| 国产精品99久久不卡| 国产A级毛片久久久精品毛片 | 亚洲精品国精品久久99热| 久久精品成人免费观看97| 国产日韩精品无码区免费专区国产| 青青青国产精品国产精品久久久久| 精品视频一区二区三区在线观看 | 四虎成人精品国产永久免费无码| 精品无码国产污污污免费网站国产 | 久久精品天天中文字幕人妻| 日产精品久久久一区二区| 午夜DY888国产精品影院| 久久青青草原精品国产| 精品熟女少妇a∨免费久久| 国产精品无码A∨精品影院| 99在线精品视频观看免费| 国产成人精品免费视| 久久精品国产99国产电影网 | 国产成人精品AA毛片| 国产福利91精品一区二区| 一区二区三区日韩精品| 成人亚洲日韩精品免费视频| 精品一区二区三区高清免费观看|