中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

html5實現多人飛機游戲的案例

發布時間:2020-10-24 17:16:17 來源:億速云 閱讀:168 作者:小新 欄目:web開發

這篇文章主要介紹了html5實現多人飛機游戲的案例,具有一定借鑒價值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

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

整體架構

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

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

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

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

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

后端websocket

廢話說了這么多,簡單看看一些關鍵代碼如何實現。

// 后端關鍵流程實現

var app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server); // 引入socket.io 庫
io.on('connection', function(socket) { // 開始監聽客戶端的websocket連接請求,connection事件產生 socket 對象
    socket.emit('open'); // 向該客戶端發送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  = { }; // 構建發送給其他客戶端的消息
          obj = msg;
          clients.push(client); // 加入后臺維持的客戶端數組
          socket.broadcast.emit('message', obj); // 廣播歡迎語給其他客戶端
        } else if ( client.name == msg.name ) { // 客戶端發來的飛機狀態消息
            // 廣播給其他客戶端
          socket.broadcast.emit('message', obj);
        }
    }
}

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

前端socket和飛機模型

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

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

其他問題包括:

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

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

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

目前可能子彈飛行過程中碰撞檢測的計算量偏大,會有卡頓問題,CPU占用較高,整個應用消耗內存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幀的情況下,不是每一幀都會隨機微調飛機的方向。而是5%的概率。
        direction += (Math.random() - 0.5) /5;
    }    
    // 根據飛機朝向和速度更新位置。
    point.coordinates[0] += speed * Math.sin(direction) / 100;
    point.coordinates[1] += speed * Math.cos(direction) / 100;
    // 校正飛機的朝向顯示。因為默認情況下mapbox是根據你的視角隨時調整圖標方向。但實際上飛機圖標的朝向必須和飛機運行方向一致,而不是簡單的和標注一樣。
    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);
    }

感謝你能夠認真閱讀完這篇文章,希望小編分享html5實現多人飛機游戲的案例內容對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,遇到問題就找億速云,詳細的解決方法等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

河曲县| 溧水县| 渝北区| 潼关县| 丰顺县| 南乐县| 合水县| 太仆寺旗| 万宁市| 务川| 依兰县| 安远县| 阳西县| 共和县| 通州市| 巨野县| 崇义县| 霞浦县| 方山县| 西乌| 洱源县| 西昌市| 绥江县| 文山县| 枣阳市| 平阴县| 明水县| 洛川县| 衡山县| 新河县| 防城港市| 北宁市| 甘泉县| 如东县| 宜宾市| 普兰店市| 囊谦县| 双鸭山市| 资兴市| 榕江县| 富阳市|