Cocos Creator 2.0使用protobufjs6.8,及web的html页面使用protobufjs6.8

最近用golang写斗地主游戏客户端用的是Cocos Creator 因为之前一直使用的是tcp协议与客户端Cocos(lua)使用protobuf通信,切到js上还是遇到了点麻烦。因为不懂nodejs,一直以为Cocos Creator使用的就是js所以遇到了点麻烦。

先说一下在web页面使用protobufjs与服务器之间的通信吧!(直接用web方式在Cocos Creator里一直找不到proto文件,可能还没搞清楚Cocos Creator加载资源的原理跟路径映射)

通信包的格式:前8位(包大小)、2位(主命令)、2位(子命令)、包体;

先引入所需要的js文件:

<script type="text/javascript" src="./dist/long.js"></script>
<script type="text/javascript" src="./dist/bytebuffer.min.js"></script>
<script type="text/javascript" src="./dist/protobuf.min.js"></script>

所以需要两个函数把数值类型转换为所需要的字节类型,一个是转64,一个是转16位

function int64ToByte(num) {
    //只有int类型,小于256点1字节,大于256点两字节,所有只能返过来
    var bytes = new Array();
    //没有64位只能前4位补0
    bytes.push(0);
    bytes.push(0);
    bytes.push(0);
    bytes.push(0);

    bytes.push(num >> 24 & 0xff)
    bytes.push(num >> 16 & 0xff)
    bytes.push(num >> 8 & 0xff)
    bytes.push(num & 0xff)
    return bytes;
}
function int16ToByte(num) {
    //只有int类型,小于256点1字节,大于256点两字节,所有只能返过来
    var bytes = new Array();
    bytes.push(num >> 8 & 0xff)
    bytes.push(num & 0xff)
    return bytes;
}

编写解码函数:
function bytes2int16(arr) {
    return ((arr[0] & 0xFF)<<8)|(arr[1]&0xFF);
}
function bytes2int64(arr) {
    //没有64位只能取后四位
    return ((arr[4] & 0xFF)<<24)|((arr[5] & 0xFF)<<16)|((arr[6] & 0xFF)<<8)|(arr[7]&0xFF);
}

然后就是包体的封装:

class Packet{
    constructor(options){
        this.mainId=options.mainId||0;
        this.subId=options.subId||0;
        this.sendData=options.sendData||new Uint8Array(0);
    }

    encode(){
        //包的总长度
        var all_length = 12 + this.sendData.byteLength;
        //返回的数组
        var myArray = new ArrayBuffer(all_length);
        //以byte形式的数组返回
        var resData = new Uint8Array(myArray);
        //转换成服务器uint64的包头类型
        var all_length_byte = int64ToByte(all_length)
        //添加包头
        for (let i = 0; i < all_length_byte.length; i++) {
            resData[i] = all_length_byte[i];

        }
        
        //主命令
        var mainId_byte = int16ToByte(this.mainId);
        for (let i = 0; i < mainId_byte.length; i++) {
            resData[i + 8] = mainId_byte[i];

        }
        
        //子命令
        var subId_byte = int16ToByte(this.subId);
        for (let i = 0; i < subId_byte.length; i++) {
            resData[i + 10] = subId_byte[i];

        }
        
        //内容
        for (let i = 0; i < this.sendData.length; i++) {
            resData[i + 12] = this.sendData[i];

        }
        return myArray;
    }
}

封装发送数据:

var buffer;
var ModelRegGameServerInfo;
protobuf.load("reg_rpc_model.proto", function (err, root) {
    if (err)
        throw err;
    ModelRegGameServerInfo = root.lookupType("grpcmodel.ModelRegGameServerInfo");
    var server = ModelRegGameServerInfo.create({
        serverId: 23,
        addr: "abc",
        count: 1,
        serverType: 2,
        gameName: "kwo",
        gameType: 3
    });

    //编码
    buffer = ModelRegGameServerInfo.encode(server).finish();
    
    //解码
    // var svr=ModelRegGameServerInfo.decode(buffer);
    // console.log(svr);
});

然后就是发送数据与解析数据:

ws = new WebSocket("ws://localhost:7026/GameWs");
ws.binaryType = "arraybuffer";
// ws.binaryType = "blob";
ws.onopen = function (event) {
    console.log("Send Text WS was opened.");
};
ws.onmessage = function (event) {
    var arr = new Uint8Array(event.data);
    // 包大小
    // console.log(bytes2int64(arr.slice(0, 8)));
    let mainId = bytes2int16(arr.slice(8, 10));
    let subId = bytes2int16(arr.slice(10, 12));
    if (mainId==22&&subId==3&&arr.byteLength > 12) {
        var svr=ModelRegGameServerInfo.decode(arr.slice(12, arr.byteLength));
    	console.log(svr);
    }
};
ws.onerror = function (event) {
    console.log("Send Text fired an error");
};
ws.onclose = function (event) {
    console.log("WebSocket instance closed.");
};

//写个按钮调用这个方法
function send() {
    if (ws.readyState == WebSocket.OPEN) {

        var pck = new Packet({
            mainId: 22,
            subId: 3,
            sendData: buffer
        });


        ws.send(pck.encode());
    }
    else {
        console.log("WebSocket instance wasn't ready...");
    }
}

后来这种方式在Cocos Creator里没法使用,查了好多资料才搞定,便还是需要用到上面包体的封装跟数值与字节的转换。

首先要装的是nodejs在https://nodejs.org/zh-cn/download/下载,我下载的zip版本
将文件解压到要安装的位置,并新建两个目录:node-global :npm全局安装位置、node-cache:npm 缓存路径。
把解压的根目录配置到环境变量里。
输入:node -v 与 npm -v 来测试安装是否成功
配置全局安装位置:npm config set prefix "D:\dev\node\node-global"
配置全局缓存位置:npm config set cache "D:\dev\node\node-cache"
安装protobufjs:npm install -g protobufjs
进入到node-cache\node_modules\protobufjs\dist目录把protobuf.js复制到Cocos Creator里然后导入为插件
进入到node-cache目录下,把写好的proto文件复制一份到此目录下
然后执行:pbjs -t static-module -w commonjs -o reg_rpc_model.js reg_rpc_model.proto
生成所需要的js文件,把js文件复制到Cocos Creator里;把生成的js文件第一行:var $protobuf = require("protobufjs/minimal");改为var $protobuf = protobuf;
然后开始写与服务器通信的代码:

// { grpcmodel }这个是proto文件里的包名 from后面是路径
import { grpcmodel } from "..model/reg_rpc_model"

ws = new WebSocket("ws://localhost:7026/GameWs");
ws.binaryType = "arraybuffer";
// ws.binaryType = "blob";
ws.onopen = function (event) {
    console.log("Send Text WS was opened.");
};
ws.onmessage = function (event) {
    var arr = new Uint8Array(event.data);
    // 包大小
    // console.log(bytes2int64(arr.slice(0, 8)));
    let mainId = bytes2int16(arr.slice(8, 10));
    let subId = bytes2int16(arr.slice(10, 12));
    if (mainId==22&&subId==3&&arr.byteLength > 12) {
        console.log(arr);
        let msg=grpcmodel.ModelRegGameServerInfo.decode(arr.slice(12, arr.byteLength));
        console.log(msg);
    }
};
ws.onerror = function (event) {
    console.log("Send Text fired an error");
};
ws.onclose = function (event) {
    console.log("WebSocket instance closed.");
};
function send(){
	let message = grpcmodel.ModelRegGameServerInfo.create({
	    serverId: 23,
	    addr: "abc",
	    count: 1,
	    serverType: 2,
	    gameName: "kwo",
	    gameType: 3
	});
	let msg_data = grpcmodel.ModelRegGameServerInfo.encode(message).finish();
	if (ws.readyState == WebSocket.OPEN) {
	    var pck = new Packet({
	        mainId: 22,
	        subId: 3,
	        sendData: msg_data
	    });
	    ws.send(pck.encode());
	} else {
	    console.log("web socket not open")
	}
}

原文地址:http://www.1025m.com/37.html

转载于:https://my.oschina.net/wolf2leader/blog/2223380

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值