1. 程式人生 > >JavaScript實現H5遊戲斷線自動重連的技術

JavaScript實現H5遊戲斷線自動重連的技術

斷線重連的需求

尤其是手機上,會因為網路的不穩定或者其他原因,導致使用者的socket連結斷開。這個時候如果直接讓玩家退出遊戲,重新登入,無疑是非常影響使用者體驗的事情。所以根據這個需求,就有需要程式來實現斷線後自動重連回去的技術,是使用者能夠再次快速開始遊戲進行戰鬥。

一、斷線重連原理

原來其實很簡單,就是在斷線的時候,根據使用者的點選(有些時間短的就不用點選,預設是自動重連回來),程式自動識別,是要重新整理重新進入遊戲還是幫使用者自動重連。客戶端會根據自動重連標記,幫使用者自動做事情。比如自動登陸、選角色、進入場景、請求同步後臺資料等等。

根據實現機制,大致可以分兩種實現方法。主要是遊戲內自動重連(不重新整理)和重新整理遊戲自動重連,後面會詳細講兩種實現機制,以及相關的利弊。

二、遊戲內自動重連(不重新整理)

這種是比較難的,因為不重新整理遊戲,那麼會因為一段時間的斷開遊戲,導致客戶端資料跟伺服器資料不同步了。比如怪物的位置、獲得的獎勵、進度等等。這些需要一開始就設計好,如果策劃在後期要求加這個,那幾乎是無法實現的,改動太大了。所以假設要這麼多,大概是類似下面的做法。(如果真要詳細,得一篇新的Blog了:)
1. 客戶端和服務端協定好那些資料需要客戶端自己同步
2. 斷線多久內可以自動重連(策劃以及技術上的實現來互相評估)
3. 服務端提供自動重連的協議,同時使用者斷線第一時間不應該就銷燬掉相關資料(這裡比較複雜,比如自動戰鬥是否要一直在伺服器掛著,以及其他的一些關聯操作)
4. 客戶端不重新整理遊戲,使用新介面重新連線伺服器,自動更新和同步相應的資料(比如同步怪物位置或者其他人物位置等等)

這種技術一般用於回合制之類的遊戲,一般不涉及戰鬥系統。如果arpg的話,只能短暫的時間內可以自動重連,不然的話變數太大。或者需要做一些變種,比如單純場景的怪物之類的重新整理下,但是世界boss之類的場景就得重新載入之類的特殊處理。

三、重新整理遊戲自動重連

我個人感覺這個是簡單粗暴又實用的做法。大部分遊戲都適合使用,只要一重新整理,遊戲的資料都沒了,全部重新開始,客戶端只需要根據標記來做一些自動化的操作,容易很多。,同時伺服器也不用更改,穩定也不容易出錯。唯一不好的就是使用者體驗會稍微差一些。

重連資料

字串資料:

//ip + 使用者標識 + 服id + 服名字  (資料根據自己專案情況)
var reload:string = ip + "#" + token + "#" + serverId + "#" +serverName;

//後面的reload字串都是這裡的內容

重連標識:

reload  //字串

注意:重新整理只能重新整理自己的頁面。(比如在iframe裡面的時候)

Location.replace重置url重連

這種比較簡單,也不會有什麼相容性的問題。就是重連的時候,把之前的登入使用者以及服務端地址給記錄起來
通過url來附帶引數,最後再實際使用中解析出來,通過判斷屬性是否過載,

Location 物件的replace()方法:用新的文件替換當前文件。
通過傳入新的url(其實是原url + 附帶重連資料)

location.replace(oldUrl + "reload#" + reload);

是必須走url,而且還需要和原來的引數進行相容處理。在遊戲遊戲中可能是這樣的url了:

http://localhost:63342/game/index.html?reload=1&host=ws://192.168.0.10:1050/ws&token=soda1&serverId=1&serverName=本地除錯
  1. document.cookie
    cookie 是儲存於訪問者的計算機中的變數。每當同一臺計算機通過瀏覽器請求某個頁面時,就會發送這個 cookie。你可以使用 JavaScript 來建立和取回 cookie 的值。
    利用cookie的本地存放功能,也比較方便,但是會有些手機瀏覽器可能會無法讀取到。
document.cookie = "reload#" + reload;
  1. 使用Html5的window.localStorage

    localStorage 屬性允許你訪問一個 local Storage 物件。localStorage 與 sessionStorage 相似。不同之處在於,儲存在 localStorage 裡面的資料沒有過期時間(expiration time),而儲存在 sessionStorage 裡面的資料會在瀏覽器會話(browsing session)結束時被清除,即瀏覽器關閉時。

    應該注意的是,無論是 localStorage 還是 sessionStorage 中儲存的資料都僅限於該頁面的協議。


既然是H5遊戲,當然重點是使用這個了,先看下localStorage的API
window.localStorage.setItem("reload", reload);
讀取:
var reload = window.localStorage.getItem("reload");
  1. 使用Egret的本地儲存
    使用Egret會更方便,他進行了封裝,H5和打包成本地都可以支援。localStorage.ts
egret.localStorage介面
//儲存資料
export let getItem:(key:string)=>string;
//刪除資料
export let removeItem:(key:string)=>void;
//將所有資料清空
export let clear:()=>void;

Web實現類WebLocalStorage.ts

namespace egret.localStorage.web {
    function getItem(key:string):string {
        return window.localStorage.getItem(key);
    }
    function setItem(key:string, value:string):boolean {
        try{
            window.localStorage.setItem(key, value);
            return true;
        }
        catch(e){
            egret.$warn(1047, key, value);
            return false;
        }
    }
    function removeItem(key:string):void {
        window.localStorage.removeItem(key);
    }

    function clear():void {
        window.localStorage.clear();
    }

    localStorage.getItem = getItem;
    localStorage.setItem = setItem;
    localStorage.removeItem = removeItem;
    localStorage.clear = clear;
}

可以看到內部其實也是採用了window.localStorage來進行實現,同時做了一場處理,最後是通過localStorage介面進行賦值給外部呼叫。下面是實際使用方法:

//使用egret的本地存放方法做
egret.localStorage.setItem("reload",reload);

//遊戲中獲取

var reload:string = egret.localStorage.getItem("reload");

四、實際專案中處理重連機制

這裡的程式碼是重新整理之後重新進入遊戲,然後通過之前的資料(url或者本地快取)解析出相應的資料來進行判斷。

解析url

var reload:string = location.href;

本地快取獲取資料

var reload:string = egret.localStorage.getItem("reload");
console.info("reload資料:" + reload);
if(reload && reload != "")
{
    var cooks:string[] = reload.split("#");

    console.info("斷線重連重新整理過來的");
    this.session.isReload = true;
    this.session.host = cooks[0];
    this.session.token = cooks[1];
    this.session.serverId = Number(cooks[2]);
    this.session.serverName = cooks[3];
}

通過遊戲內的變數進行判斷處理

if(this.session.isReload)
{
    //開始自動重連,走額外的協議以及自動處理
}
else
{
    //走正常的流程
}

最後的總結

斷線重連這裡主要是講了一些思路以及實際專案中的應用。程式碼算是偽5程式碼了,讀者應該根據自己專案實際情況來設計,做一些相應變化,原理是一樣的。

我們有一個專案是有遇到過其中的一個問題,因為一開始沒有考慮自動重連的問題,在客戶端和伺服器都沒這裡的考慮。所以沒辦法做到不重新整理遊戲來進行重連(主要是成本太大,又是arpg遊戲),最終是選擇了遊戲自己重新整理來實現的機制的。當然也會遇到一些坑,比如接入一些平臺,只能重新整理自己的html,無法重新整理平臺的html(遊戲內嵌),導致平臺的sdk的問題(影響充值、關注等等)。不過最終都是有通過變通之類的進行解決了。

相關推薦

JavaScript實現H5遊戲自動技術

斷線重連的需求 尤其是手機上,會因為網路的不穩定或者其他原因,導致使用者的socket連結斷開。這個時候如果直接讓玩家退出遊戲,重新登入,無疑是非常影響使用者體驗的事情。所以根據這個需求,就有需要程式來實現斷線後自動重連回去的技術,是使用者能夠再次快速開始遊戲

Node.js熱部署代碼,實現修改代碼後自動啟服務方便實時調試

iso 用戶 使用方法 了解 super 幫助 應用 https js文件 寫PHP等腳本語言的時候,已經習慣了修改完代碼直接打開瀏覽器去查看最新的效果。而Node.js 只有在第一次引用時才會去解析腳本文件,以後都會直接訪問內存,避免重復載入,這種設計雖然有利於提高性能,

PHP連線MySql閃自動的方法

使用php作為後臺執行程式(例如簡訊群發),在cli模式下執行php,php需要連線mysql迴圈執行資料庫處理。 當mysql連線閃斷時,之後迴圈的執行將會失敗。 我們需要設計一個方法,當mysql閃斷時,可以自動重新連線,使後面的程式可以正常執行下去。 1.建立測試資料表 CREATE&nbs

SHELL指令碼實現服務宕機監控自動

需要先安裝 yum install stat  crontabs (本例項在centos系統下) #!/bin/bash #Shell ##根據修改檔案時間進行監控## content=`ls -l /tmp/log.txt | awk '{ print $5 }'`  

關於javaScript實現select下拉框自動展開

我本來的目的:是想實現滑鼠移動到select下拉框上,下拉框自動展開。 原先思路:使用onmouseover()滑鼠事件呼叫一個openSelect()函式,函式中呼叫onclick()方法,以為就可以了(程式碼如下),我想得太簡單了。 <head&g

JavaScript實現遊戲

伴隨Ajax與網頁遊戲的崛起,曾幾何時JavaScript也成了遊戲開發時可供選擇的技術之一,文字僅列舉數項由JavaScript技術實現的web小遊戲(不含網遊),聊作參考之用。 傳說中的馬里奧網頁版,一比一實現了紅白機時代超級馬里奧中所有功能與關卡,精細程度不遜原

微信小程式 實現websocket長連線 以及斷開連線之後自動

app.js let socketMsgQueue = [] let isLoading = false App({ globalData: { userInfo: null, localSocket: {}, callback: function () {} },

spring-websocket --WebSocketStompClient端實現自動

轉自https://blog.csdn.net/u013174217/article/details/53376793websocketstompclient端實現和服務端建立連線和通訊之後,如果服務端斷開或重啟,client端需要實現自動定時重連機制。查閱了官網和一些資料沒

Jboss數據庫接斷開自動

jbossJboss默認配置是數據庫連接端口後,服務就會出現異常,無法訪問,此時必須重啟Jboss服務才能重新連接上數據庫。在jboss/server/defult/deploy/oracle-ds.xml中加入:<new-connection-sql>select 1 from dual<

[轉]樹莓派.設置自動WiFi

system init.d defaults href ans start class ati call 由於不可知的原因,有可能會導致樹莓派失去連接,這時候需要重新連接WiFi。 自動重連的原理是,定期查看是否斷網,如果斷網了重啟WiFi,參考的文章是這篇,第一步略有修

Delphi使用ADO接網絡數據庫,網後問題

無法 create exit eat bject sender class exce cep 原始文章: https://blog.csdn.net/blog_jihq/article/details/11737699# 使用TADOConnection對象連接網絡數據庫

TCP自動

list save Coding locale [] ext eat blocking one 網上模板: public class Socket_wrapper { public static Socket theSocket = nul

【HP-Socket沉思錄】在 OnClose 中自動

HP-Socket 版本 5.3.2   其實這裡是取了個巧,因為並不是真正意義上的在 OnClose 中。由於同一個連線的事件是序列的,所以 OnClose 事件不完成 socket 的狀態始終懸置。 可以在 OnClose 中

藍芽自動

1利用系統中的自動重連 getDevice().connectGatt(context, autoConnect, coreGattCallback); private BleGattCal

Java NIO SocketChannel客戶端例子(支援連線失敗後自動

這兩天想找找標題裡說的這個示例程式碼,發現網上這麼多教程,連怎麼樣實現自動重連都不講,所以把自己寫的例子貼上來。僅僅使用遞迴,不使用多執行緒,就可以實現初步的目的: import java.io.IOException; import java.net.ConnectExc

jdbc C3P0容錯和自動

1)C3P0容錯和自動重連與以下配置引數有關: breakAfterAcquireFailure :true表示pool向資料庫請求連線失敗後標記整個pool為block並close,就算後端資料庫恢復正常也不進行重連,客戶端對pool的請求都拒絕掉。fals

設定網路對映後,電腦啟後自動

1.     利用批處理檔案來自動對映 ①      首先製作自動對映網路驅動器批處理檔案; ②      利用Net Use命令,其基本格式如下: NET USE [devicename | *] [\\computername\sharename[\volume] [p

SecureCRT自動伺服器的解決方法

在secureCRT上登入時,一段時間不用的話會自動斷開,必須重新連線,有點麻煩,對於密碼為動態的密碼的情況就更為不方便,為了解決此問題,有兩種方案: 1、修改伺服器端的 /etc/profile 檔案

(六)、ZooKeeper自動

       在一套分散式的online services系統中,各service通常不會放在一臺伺服器上,而是通過Zookeeper這樣的東西,將自己的service資訊註冊到上面,service的使用者通過Zookeeper來發現各service的資訊,從而可以將req

activeMQ 自動機制

在使用activeMQ的時候(沒有整合spring),發現當broker掛掉或者重啟的時候,consumer就會斷開,不會在次嘗試去接受訊息, (使用spring整合activeMQ)會解決這個問題. 如果說你不想使用spring,那麼接下來告訴你該怎麼辦. 在apache